For my project I want to collect some data, where the order in which the data is added should be maintained. BTreeMap does sort it's keys and HashMap warns that the keys are in no particular order.
So I created another Map type:
/// Map implementation that keeps the keys in the order at which they are created.
///
/// ```rust
/// # use d3rs::data_collections::SequenceMap;
///
/// let map = SequenceMap::from([("B", 102), ("D", 204), ("D", 301), ("B", 403)]);
/// let mut iter = map.iter();
/// assert_eq!(iter.next(), Some((&"B", &403)));
/// assert_eq!(iter.next(), Some((&"D", &301)));
/// assert_eq!(iter.next(), None);
/// ```
#[derive(Debug, Default)]
pub struct SequenceMap<K, V> {
data: HashMap<K, V>,
sequence: Vec<K>,
}
impl<K, V> SequenceMap<K, V>
where
K: Display + Hash + Eq,
{
pub fn new() -> Self {
Self {
data: HashMap::new(),
sequence: Vec::new(),
}
}
pub fn insert(&mut self, key: K, value: V) -> Option<V>
where
K: Copy,
{
let result = self.data.insert(key, value);
if result.is_none() {
self.sequence.push(key);
}
result
}
// some other methods skipped
}
The trait bounds for K are similar to those for HashMap, but for the implementation of the insert method a subtle addition is required: Copy.
Now, one of the great things about HashMap is that you can use any key type (as long as it has Hash + Eq, which are derivable). This means that even String and user defined types can be used as the key, where the various iterators and the get method get a borrow to the key type as an argument.
In order to have the keys returned in the order in which they were defined, I use an internal Vector to hold the keys in that order. This is why the Copy trait is now required for the Key type, otherwise the borrow checker wouldn't allow the push after the insert.
But this makes it cumbersome to have Strings and user defined types as the keys, since they should now also implement Copy (which is a potentially time-consuming process)
How could I remove the Copy restriction?