diff --git a/Cargo.toml b/Cargo.toml index fab3ca3..d2f3f8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ strip=true [features] default = ["std"] -std = ["serde/std"] +std = [] # TODO: maybe add an FFI feature, to allow C projects to use it? idk if that's worth it really... [dependencies] diff --git a/src/lib.rs b/src/lib.rs index 5d01ca1..4961e28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -213,10 +213,43 @@ where K: Collapse /// A small hashtable-like map with byte sized key indecies. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))] // TODO: Replace with `SmallVec<[Page; 1]>` when feature that adds `smallvec` is enabled (this will allocate the first page on the stack, and the rest on the heap. pub struct Map(Vec>); +#[derive(Default)] +struct MapVisitor { + _pd: core::marker::PhantomData<(TKey, TValue)>, +} + +/// Just taken from [serde.rs' examples](https://serde.rs/deserialize-map.html) +#[cfg(feature = "serde")] +impl<'de, TKey, TValue> serde::de::Visitor<'de> for MapVisitor where TKey: Collapse + serde::Deserialize<'de>, TValue: serde::Deserialize<'de> { + type Value = Map; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("A map") + } + + fn visit_map(self, mut access: A) -> Result where A: serde::de::MapAccess<'de> { + let mut map = Map::with_capacity(access.size_hint().unwrap_or(0)); + while let Some((key, value)) = access.next_entry()? { + map.insert(key, value); + } + Ok(map) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Map where TKey: Collapse + serde::Serialize, TValue: serde::Serialize { + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { + let mut m = serializer.serialize_map(Some(self.len()))?; + for (k, v) in self.iter() { + m.serialize_entry(k, v)?; + } + m.end() + } +} + impl Map { /// Returns the currently allocated size of the map in bytes (including currently unused reserved space.) @@ -500,6 +533,8 @@ impl core::iter::Extend<(K,V)> for Map use core::hash::{Hash, Hasher,}; use core::ops::{Index, IndexMut}; +#[cfg(feature = "serde")] +use serde::ser::SerializeMap; impl Collapse for T {