lilliput_core/value/
map.rs

1#[cfg(any(test, feature = "testing"))]
2use proptest::{prelude::*, sample::SizeRange};
3#[cfg(any(test, feature = "testing"))]
4use proptest_derive::Arbitrary;
5
6use super::Value;
7
8/// An ordered map.
9#[cfg(feature = "preserve_order")]
10pub type Map = ordermap::OrderMap<Value, Value>;
11
12/// An unordered map.
13#[cfg(not(feature = "preserve_order"))]
14pub type Map = std::collections::BTreeMap<Value, Value>;
15
16#[cfg(any(test, feature = "testing"))]
17pub(crate) fn arbitrary_map() -> impl Strategy<Value = Map> {
18    arbitrary_map_with(Value::arbitrary(), Value::arbitrary(), 0..10)
19}
20
21#[cfg(any(test, feature = "testing"))]
22pub(crate) fn arbitrary_map_with(
23    key: impl Strategy<Value = Value>,
24    value: impl Strategy<Value = Value>,
25    size: impl Into<SizeRange>,
26) -> impl Strategy<Value = Map> {
27    proptest::collection::hash_map(key, value, size.into()).prop_map(Map::from_iter)
28}
29
30/// Represents a map of key-value pairs.
31#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
32#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
33pub struct MapValue(
34    #[cfg_attr(any(test, feature = "testing"), proptest(strategy = "arbitrary_map()"))] pub Map,
35);
36
37impl MapValue {
38    /// Returns a reference to the internal map.
39    pub fn as_map_ref(&self) -> &Map {
40        &self.0
41    }
42
43    /// Returns the internal map, consuming `self`.
44    pub fn into_map(self) -> Map {
45        self.0
46    }
47
48    /// Returns the length of the internal map.
49    pub fn len(&self) -> usize {
50        self.0.len()
51    }
52
53    /// Returns `true`, if the internal map is empty, otherwise `false`.
54    pub fn is_empty(&self) -> bool {
55        self.0.is_empty()
56    }
57}
58
59impl From<Map> for MapValue {
60    fn from(value: Map) -> Self {
61        Self(value)
62    }
63}
64
65impl<'a> From<&'a MapValue> for &'a Map {
66    fn from(value: &'a MapValue) -> Self {
67        &value.0
68    }
69}
70
71impl From<MapValue> for Map {
72    fn from(value: MapValue) -> Self {
73        value.0
74    }
75}
76
77impl std::fmt::Debug for MapValue {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        f.debug_map().entries(self.0.iter()).finish()
80    }
81}
82
83#[cfg(feature = "serde")]
84impl serde::Serialize for MapValue {
85    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86    where
87        S: serde::Serializer,
88    {
89        self.0.serialize(serializer)
90    }
91}
92
93#[cfg(feature = "serde")]
94impl<'de> serde::Deserialize<'de> for MapValue {
95    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96    where
97        D: serde::Deserializer<'de>,
98    {
99        Ok(Self(Map::deserialize(deserializer)?))
100    }
101}
102
103#[cfg(feature = "serde")]
104pub(crate) struct MapKeyClassifier;
105
106#[cfg(feature = "serde")]
107pub(crate) enum MapKeyClass {
108    Map(Value),
109}
110
111#[cfg(feature = "serde")]
112impl<'de> serde::de::DeserializeSeed<'de> for MapKeyClassifier {
113    type Value = MapKeyClass;
114
115    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
116    where
117        D: serde::Deserializer<'de>,
118    {
119        use serde::Deserialize as _;
120
121        Ok(MapKeyClass::Map(Value::deserialize(deserializer)?))
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use proptest::prelude::*;
128    use test_log::test;
129
130    use crate::{
131        config::EncoderConfig,
132        decoder::Decoder,
133        encoder::Encoder,
134        io::{SliceReader, VecWriter},
135        value::{NullValue, Value},
136    };
137
138    use super::*;
139
140    #[test]
141    fn debug() {
142        let mut map = Map::default();
143        map.insert(Value::Null(NullValue), Value::Null(NullValue));
144        let value = MapValue::from(map);
145
146        assert_eq!(format!("{value:?}"), "{null: null}");
147        assert_eq!(
148            format!("{value:#?}"),
149            "{\n    Null(\n        null,\n    ): Null(\n        null,\n    ),\n}"
150        );
151    }
152
153    proptest! {
154        #[test]
155        fn encode_decode_roundtrip(value in MapValue::arbitrary(), config in EncoderConfig::arbitrary()) {
156            let mut encoded: Vec<u8> = Vec::new();
157            let writer = VecWriter::new(&mut encoded);
158            let mut encoder = Encoder::new(writer, config);
159            encoder.encode_map(&value.0).unwrap();
160
161            // the encoded length of a map depends on the items
162            // contained within, so we're not checking it here.
163
164            let reader = SliceReader::new(&encoded);
165            let mut decoder = Decoder::from_reader(reader);
166            let decoded = decoder.decode_map().unwrap();
167            prop_assert_eq!(&decoded, &value.0);
168
169            let reader = SliceReader::new(&encoded);
170            let mut decoder = Decoder::from_reader(reader);
171            let decoded = decoder.decode_value().unwrap();
172            let Value::Map(decoded) = decoded else {
173                panic!("expected map value");
174            };
175            prop_assert_eq!(&decoded, &value);
176        }
177    }
178}