Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rustonaut/total-order-multi-map
A multimap with at the same time keeps the total insertion ordering of all elements
https://github.com/rustonaut/total-order-multi-map
Last synced: about 2 months ago
JSON representation
A multimap with at the same time keeps the total insertion ordering of all elements
- Host: GitHub
- URL: https://github.com/rustonaut/total-order-multi-map
- Owner: rustonaut
- Created: 2018-01-16T15:44:47.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2019-10-11T14:07:56.000Z (over 5 years ago)
- Last Synced: 2024-11-10T06:11:39.219Z (3 months ago)
- Language: Rust
- Size: 54.7 KB
- Stars: 1
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
total-order-multi-map [![Crates.io](https://img.shields.io/crates/v/total-order-multi-map.svg)](https://crates.io/crates/total-order-multi-map) [![total-order-multi-map](https://docs.rs/total-order-multi-map/badge.svg)](https://docs.rs/total-order-multi-map) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
=============A multi-map with at the same time keeps the total insertion ordering of all elements,
this means if you insert following key-value pairs: `(K1, V1)`, `(K2, V2)`, `(K1, V3)`
It will remember that the insertion oder was exact this (`V1`, `V2`, `V3`) i.e.
it won't collapse the insertion order on a per-key basis.At the same time it should have similar performance for accessing entries as a normal
`HashMap` (else we could have just created a `Vec`).It does so by limiting its values to such which implement `StableDeref`, e.g.
`Box` through which it can have more than one ~reference~ pointer to
a value. While it uses unsafety internally the provided interface is safe.
It also makes sure to be unwind + resume safe.Example
--------```rust
extern crate total_order_multi_map as tomm;use std::fmt::{self, Display};
use tomm::TotalOrderMultiMap;/// for now the key has to be copy
type Key = &'static str;/// the map is made for thinks which dereference
/// e.g. trait objects, through e.g. `String` or
/// `Rc` would be fine, too.
type Value = Box;fn main() {
let mut map = TotalOrderMultiMap::::new();map.add("key1", mk_box_str("val1"));
map.add("key1", mk_my_thingy("val2"));
map.add("key2", mk_box_str("val3"));
map.add("key1", mk_my_thingy("val4"));
map.add("key0", mk_box_str("val5"));let stringed = map
.iter()
// val is of type `&Display`
.map(|(key, val)| format!("{}:{}", key, val))
.collect::>();// as it can be seen the total insertion order was kept
assert_eq!(stringed, &[
"key1:val1".to_owned(),
"key1:val2".to_owned(),
"key2:val3".to_owned(),
"key1:val4".to_owned(),
"key0:val5".to_owned()
]);// It's also still a multi map.
// Note that the get operation has roughly the same
// performance as in a hash map (through you then
// iterate over the elements associated with the key
// roughly with the speed of iterating over an `Vec`).
{
let values = map.get("key1").expect("key1 is in the map");
let stringed = values
.map(|val| format!("{}", val))
.collect::>();assert_eq!(stringed, &[ "val1", "val2", "val4" ]);
}// but as we have an order we can remove
// "the last inserted" element
let (key, val) = map.pop().unwrap();
assert_eq!(format!("{}:{}", key, val), "key0:val5");// or remove all for an specific key as it's
// an multi map
map.remove_all("key1");
assert!(map.get("key1").is_none());println!("DONE (I only contain asserts)")
}//---- some function to create dummy values for the example ----
fn mk_box_str(inp: &str) -> Box {
// sadly we can't cast Box to Box
// (you would need non static vtables for this...)
Box::new(inp.to_owned())
}#[derive(Debug)]
struct MyThingy { val: String }impl Display for MyThingy {
fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
write!(fter, "{}", self.val)
}
}fn mk_my_thingy(inp: &str) -> Box {
Box::new(MyThingy { val: inp.to_owned() })
}
```Missing Parts
-------------Following thinks can be implemented and should
be added to further versions:- benchmarks
- use `SmallVec` for the multi map
- allow `&mut` access to `V::Target` if `V: StableDeref + DerefMut`
- indexed access
- indexed get off key-value pairs
- indexed remove
- indexed get _in_ the return value of `get`, i.e. a multi map group
- improved entry api
- allow access to other values for same key
- potentially turn the result of entry + insert into the result of get + unwrap
- improved grouped iteration, maybe??
- the current implementation groups by key but doesn't indicate
when it switches to the next value
- allow non-copy keys??
- we still don't want to duplicate/clone keys so we would have to do
some trickery thereLicense
-------Licensed under either of
- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)at your option.
Contribution
------------Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.Change Log
------------ `v0.3`:
- `TotalOrderMultiMap.retain` now accepts a predicate accepting `&V::Target` instead
of `&V`
- `v0.4.1`:
- flatten return value to `get` to return empty iterators instead
of `None`
- requires `DerefMut` instead of just `Deref`
- has mutable access methods like `get_mut`
- split `insert` into `add` and `set` where `set` replaces any value
associated with the key prev. with the new value returning the old
value
- `v0.4.2`:
- mut iter to non mut iter conversions
- Iter from IterMut
- Values from ValuesMut
- EntryValues from EntryValuesMut
- `v0.4.3`:
- Added missing re-exports. Values, Values,
GroupedValuesMut are now public as they
should have been from the beginning.
- `v0.4.4`:
- Added `truncate` method allowing the removal
of any think inserted after the first `size`
elements
- `v0.4.5`:
- For entries added `values`,`values_mut` methods to
iterate over the values associated with the key used
to create the entry.