use crate::io;
use alloc::collections::BTreeMap;
use super::{Deserialize, Error, Serialize, VarUint32};
use core::iter::{FromIterator, IntoIterator};
#[derive(Debug, Default)]
pub struct IndexMap<T> {
entries: BTreeMap<u32, T>,
}
impl<T> IndexMap<T> {
pub fn new() -> IndexMap<T> {
IndexMap { entries: BTreeMap::new() }
}
#[deprecated]
pub fn with_capacity(_capacity: usize) -> IndexMap<T> {
Self::new()
}
#[inline]
pub fn clear(&mut self) {
self.entries.clear();
}
#[inline]
pub fn get(&self, idx: u32) -> Option<&T> {
self.entries.get(&idx)
}
#[inline]
pub fn contains_key(&self, idx: u32) -> bool {
self.entries.contains_key(&idx)
}
#[inline]
pub fn insert(&mut self, idx: u32, value: T) -> Option<T> {
self.entries.insert(idx, value)
}
#[inline]
pub fn remove(&mut self, idx: u32) -> Option<T> {
self.entries.remove(&idx)
}
#[inline]
pub fn len(&self) -> usize {
self.entries.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (u32, &T)> {
self.entries.iter().map(|(k, v)| (*k, v))
}
pub fn deserialize_with<R, F>(
max_entry_space: usize,
deserialize_value: &F,
rdr: &mut R,
) -> Result<IndexMap<T>, Error>
where
R: io::Read,
F: Fn(u32, &mut R) -> Result<T, Error>,
{
let len: u32 = VarUint32::deserialize(rdr)?.into();
let mut map = IndexMap::new();
let mut prev_idx = None;
for _ in 0..len {
let idx: u32 = VarUint32::deserialize(rdr)?.into();
if idx as usize >= max_entry_space {
return Err(Error::Other("index is larger than expected"))
}
match prev_idx {
Some(prev) if prev >= idx => {
return Err(Error::Other("indices are out of order"))
},
_ => {
prev_idx = Some(idx);
},
}
let val = deserialize_value(idx, rdr)?;
map.insert(idx, val);
}
Ok(map)
}
}
impl<T: Clone> Clone for IndexMap<T> {
fn clone(&self) -> IndexMap<T> {
IndexMap { entries: self.entries.clone() }
}
}
impl<T: PartialEq> PartialEq<IndexMap<T>> for IndexMap<T> {
fn eq(&self, other: &IndexMap<T>) -> bool {
self.entries.eq(&other.entries)
}
}
impl<T: Eq> Eq for IndexMap<T> {}
impl<T> FromIterator<(u32, T)> for IndexMap<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (u32, T)>,
{
let iter = iter.into_iter();
let mut map = IndexMap::new();
for (idx, value) in iter {
map.insert(idx, value);
}
map
}
}
impl<T> IntoIterator for IndexMap<T> {
type Item = (u32, T);
type IntoIter = <BTreeMap<u32, T> as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
impl<T> Serialize for IndexMap<T>
where
T: Serialize,
Error: From<<T as Serialize>::Error>,
{
type Error = Error;
fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.len()).serialize(wtr)?;
for (idx, value) in self.entries.into_iter() {
VarUint32::from(idx).serialize(wtr)?;
value.serialize(wtr)?;
}
Ok(())
}
}
impl<T: Deserialize> IndexMap<T>
where
T: Deserialize,
Error: From<<T as Deserialize>::Error>,
{
pub fn deserialize<R: io::Read>(max_entry_space: usize, rdr: &mut R) -> Result<Self, Error> {
let deserialize_value: fn(u32, &mut R) -> Result<T, Error> =
|_idx, rdr| T::deserialize(rdr).map_err(Error::from);
Self::deserialize_with(max_entry_space, &deserialize_value, rdr)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::io;
#[test]
fn default_is_empty_no_matter_how_we_look_at_it() {
let map = IndexMap::<String>::default();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
assert_eq!(map.iter().count(), 0);
assert_eq!(map.into_iter().count(), 0);
}
#[test]
fn new_creates_empty_map() {
let map = IndexMap::<String>::new();
assert!(map.is_empty());
}
#[test]
fn clear_removes_all_values() {
let mut map = IndexMap::<String>::default();
map.insert(0, "sample value".to_string());
assert_eq!(map.len(), 1);
map.clear();
assert_eq!(map.len(), 0);
}
#[test]
fn get_returns_elements_that_are_there_but_nothing_else() {
let mut map = IndexMap::<String>::default();
map.insert(1, "sample value".to_string());
assert_eq!(map.len(), 1);
assert_eq!(map.get(0), None);
assert_eq!(map.get(1), Some(&"sample value".to_string()));
assert_eq!(map.get(2), None);
}
#[test]
fn contains_key_returns_true_when_a_key_is_present() {
let mut map = IndexMap::<String>::default();
map.insert(1, "sample value".to_string());
assert!(!map.contains_key(0));
assert!(map.contains_key(1));
assert!(!map.contains_key(2));
}
#[test]
fn insert_behaves_like_other_maps() {
let mut map = IndexMap::<String>::default();
assert_eq!(map.insert(1, "val 1".to_string()), None);
assert_eq!(map.len(), 1);
assert!(map.contains_key(1));
assert_eq!(map.insert(0, "val 0".to_string()), None);
assert_eq!(map.len(), 2);
assert!(map.contains_key(0));
assert_eq!(map.insert(1, "val 1.1".to_string()), Some("val 1".to_string()));
assert_eq!(map.len(), 2);
assert!(map.contains_key(1));
assert_eq!(map.get(1), Some(&"val 1.1".to_string()));
}
#[test]
fn remove_behaves_like_other_maps() {
let mut map = IndexMap::<String>::default();
assert_eq!(map.insert(1, "val 1".to_string()), None);
assert_eq!(map.remove(2), None);
assert_eq!(map.len(), 1);
assert_eq!(map.remove(0), None);
assert_eq!(map.len(), 1);
assert_eq!(map.remove(1), Some("val 1".to_string()));
assert_eq!(map.len(), 0);
}
#[test]
fn partial_eq_works_as_expected_in_simple_cases() {
let mut map1 = IndexMap::<String>::default();
let mut map2 = IndexMap::<String>::default();
assert_eq!(map1, map2);
map1.insert(1, "a".to_string());
map2.insert(1, "a".to_string());
assert_eq!(map1, map2);
map1.insert(0, "b".to_string());
assert_ne!(map1, map2);
map1.remove(0);
assert_eq!(map1, map2);
map1.insert(1, "not a".to_string());
assert_ne!(map1, map2);
}
#[test]
fn partial_eq_is_smart_about_none_values_at_the_end() {
let mut map1 = IndexMap::<String>::default();
let mut map2 = IndexMap::<String>::default();
map1.insert(1, "a".to_string());
map2.insert(1, "a".to_string());
map2.insert(10, "b".to_string());
map2.remove(10);
assert_eq!(map1, map2);
map1.insert(100, "b".to_string());
map1.remove(100);
assert_eq!(map1, map2);
map2.insert(1, "b".to_string());
assert_ne!(map1, map2);
}
#[test]
fn from_iterator_builds_a_map() {
let data = &[
(3, "val 3"),
(2, "val 2"),
(5, "val 5"),
];
let iter = data.iter().map(|&(idx, val)| (idx, val.to_string()));
let map = iter.collect::<IndexMap<_>>();
assert_eq!(map.len(), 3);
assert_eq!(map.get(2), Some(&"val 2".to_string()));
assert_eq!(map.get(3), Some(&"val 3".to_string()));
assert_eq!(map.get(5), Some(&"val 5".to_string()));
}
#[test]
fn iterators_are_well_behaved() {
let data = &[(3, "val 3"), (2, "val 2"), (5, "val 5")];
let src_iter = data.iter().map(|&(idx, val)| (idx, val.to_string()));
let mut map = src_iter.collect::<IndexMap<_>>();
map.remove(5);
{
let mut iter1 = map.iter();
assert_eq!(iter1.size_hint(), (2, Some(2)));
assert_eq!(iter1.next(), Some((2, &"val 2".to_string())));
assert_eq!(iter1.size_hint(), (1, Some(1)));
assert_eq!(iter1.next(), Some((3, &"val 3".to_string())));
assert_eq!(iter1.size_hint(), (0, Some(0)));
assert_eq!(iter1.next(), None);
assert_eq!(iter1.size_hint(), (0, Some(0)));
assert_eq!(iter1.next(), None);
assert_eq!(iter1.size_hint(), (0, Some(0)));
}
let mut iter2 = map.into_iter();
assert_eq!(iter2.size_hint(), (2, Some(2)));
assert_eq!(iter2.next(), Some((2, "val 2".to_string())));
assert_eq!(iter2.size_hint(), (1, Some(1)));
assert_eq!(iter2.next(), Some((3, "val 3".to_string())));
assert_eq!(iter2.size_hint(), (0, Some(0)));
assert_eq!(iter2.next(), None);
assert_eq!(iter2.size_hint(), (0, Some(0)));
assert_eq!(iter2.next(), None);
assert_eq!(iter2.size_hint(), (0, Some(0)));
}
#[test]
fn serialize_and_deserialize() {
let mut map = IndexMap::<String>::default();
map.insert(1, "val 1".to_string());
let mut output = vec![];
map.clone().serialize(&mut output).expect("serialize failed");
let mut input = io::Cursor::new(&output);
let deserialized = IndexMap::deserialize(2, &mut input).expect("deserialize failed");
assert_eq!(deserialized, map);
}
#[test]
fn deserialize_requires_elements_to_be_in_order() {
let mut valid = vec![];
VarUint32::from(2u32).serialize(&mut valid).unwrap();
VarUint32::from(0u32).serialize(&mut valid).unwrap();
"val 0".to_string().serialize(&mut valid).unwrap();
VarUint32::from(1u32).serialize(&mut valid).unwrap();
"val 1".to_string().serialize(&mut valid).unwrap();
let map = IndexMap::<String>::deserialize(2, &mut io::Cursor::new(valid))
.expect("unexpected error deserializing");
assert_eq!(map.len(), 2);
let mut invalid = vec![];
VarUint32::from(2u32).serialize(&mut invalid).unwrap();
VarUint32::from(1u32).serialize(&mut invalid).unwrap();
"val 1".to_string().serialize(&mut invalid).unwrap();
VarUint32::from(0u32).serialize(&mut invalid).unwrap();
"val 0".to_string().serialize(&mut invalid).unwrap();
let res = IndexMap::<String>::deserialize(2, &mut io::Cursor::new(invalid));
assert!(res.is_err());
}
#[test]
fn deserialize_enforces_max_idx() {
let mut invalid = vec![];
VarUint32::from(1u32).serialize(&mut invalid).unwrap();
VarUint32::from(5u32).serialize(&mut invalid).unwrap();
"val 5".to_string().serialize(&mut invalid).unwrap();
let res = IndexMap::<String>::deserialize(1, &mut io::Cursor::new(invalid));
assert!(res.is_err());
}
#[test]
fn deserialize_with_capacity() {
let mut invalid = vec![];
VarUint32::from(u32::MAX).serialize(&mut invalid).unwrap();
VarUint32::from(5u32).serialize(&mut invalid).unwrap();
"fooba".to_string().serialize(&mut invalid).unwrap();
let _error = IndexMap::<String>::deserialize(6, &mut io::Cursor::new(invalid)).unwrap_err();
}
#[test]
fn very_large_idx() {
let mut invalid = vec![];
VarUint32::from(1u32).serialize(&mut invalid).unwrap();
VarUint32::from(u32::MAX - 1).serialize(&mut invalid).unwrap();
"fooba".to_string().serialize(&mut invalid).unwrap();
let indexmap =
IndexMap::<String>::deserialize(u32::MAX as usize, &mut io::Cursor::new(invalid))
.unwrap();
assert_eq!(indexmap.get(u32::MAX - 1), Some(&"fooba".to_string()));
assert_eq!(indexmap.len(), 1);
}
}