cbor_core/map.rs
1use std::collections::{BTreeMap, HashMap};
2
3use crate::{Error, Value};
4
5/// Conversion helper for [`Value::map`].
6///
7/// This type wraps `BTreeMap<Value, Value>` and provides `From`
8/// implementations for common collection types, so that
9/// `Value::map()` can accept them all through a single
10/// `impl Into<Map>` bound.
11///
12/// Supported source types (where `K: Into<Value>`, `V: Into<Value>`):
13///
14/// - `[(K, V); N]` (fixed-size array of pairs)
15/// - `&[(K, V)]` (slice of pairs; requires `K: Copy, V: Copy`)
16/// - `Vec<(K, V)>` (vector of pairs)
17/// - `Box<[(K, V)]>` (boxed slice of pairs)
18/// - `BTreeMap<Value, Value>` (already-sorted map; moved as-is)
19/// - `&BTreeMap<K, V>` (borrowed map; requires `K: Copy, V: Copy`)
20/// - `&HashMap<K, V>` (borrowed hash map; requires `K: Copy, V: Copy`)
21/// - `()` (empty map)
22///
23/// Keys and values are converted via their `Into<Value>`
24/// implementations. Keys are automatically sorted in CBOR canonical
25/// order.
26///
27/// ```
28/// # use cbor_core::Value;
29/// // From a fixed-size array of pairs:
30/// let m = Value::map([("x", 1), ("y", 2)]);
31///
32/// // From a Vec of pairs with mixed key types:
33/// let pairs: Vec<(Value, Value)> = vec![
34/// (Value::from(1), Value::from("one")),
35/// (Value::from(2), Value::from("two")),
36/// ];
37/// let m = Value::map(pairs);
38///
39/// // From a BTreeMap:
40/// let mut bt = std::collections::BTreeMap::new();
41/// bt.insert(Value::from("a"), Value::from(1));
42/// let m = Value::map(bt);
43///
44/// // From a &HashMap:
45/// let mut hm = std::collections::HashMap::new();
46/// hm.insert(1, 2);
47/// let m = Value::map(&hm);
48///
49/// // Empty map via ():
50/// let m = Value::map(());
51/// assert_eq!(m.len(), Some(0));
52/// ```
53#[derive(Debug, Default, Clone, PartialEq, Eq)]
54pub struct Map<'a>(pub(crate) BTreeMap<Value<'a>, Value<'a>>);
55
56impl<'a> Map<'a> {
57 /// Create an empty map.
58 #[must_use]
59 pub const fn new() -> Self {
60 Self(BTreeMap::new())
61 }
62
63 /// Borrow the inner `BTreeMap`.
64 #[must_use]
65 pub const fn get_ref(&self) -> &BTreeMap<Value<'a>, Value<'a>> {
66 &self.0
67 }
68
69 /// Mutably borrow the inner `BTreeMap`.
70 pub const fn get_mut(&mut self) -> &mut BTreeMap<Value<'a>, Value<'a>> {
71 &mut self.0
72 }
73
74 /// Unwrap into the inner `BTreeMap`.
75 #[must_use]
76 pub fn into_inner(self) -> BTreeMap<Value<'a>, Value<'a>> {
77 self.0
78 }
79
80 /// Build a map from a lazy iterator of key/value pairs.
81 ///
82 /// Duplicate keys silently overwrite (last write wins). Input order
83 /// does not matter; the returned map is sorted in CBOR canonical
84 /// order. For the strict variant that rejects duplicate keys, see
85 /// [`try_from_pairs`](Self::try_from_pairs).
86 ///
87 /// ```
88 /// # use cbor_core::Map;
89 /// let pairs = [("a", 1), ("b", 2), ("a", 3)];
90 /// let m = Map::from_pairs(pairs);
91 /// assert_eq!(m.get_ref().len(), 2);
92 /// ```
93 pub fn from_pairs<K, V, I>(pairs: I) -> Self
94 where
95 K: Into<Value<'a>>,
96 V: Into<Value<'a>>,
97 I: IntoIterator<Item = (K, V)>,
98 {
99 Self(pairs.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
100 }
101
102 /// Build a map from a lazy iterator of key/value pairs, rejecting
103 /// duplicate keys.
104 ///
105 /// Input order does not matter; the returned map is sorted in CBOR
106 /// canonical order. For the lenient variant, see
107 /// [`from_pairs`](Self::from_pairs).
108 ///
109 /// # Errors
110 ///
111 /// Returns [`Error::NonDeterministic`] on the first duplicate key.
112 ///
113 /// ```
114 /// # use cbor_core::{Map, Error};
115 /// let ok = Map::try_from_pairs([("a", 1), ("b", 2)]).unwrap();
116 /// assert_eq!(ok.get_ref().len(), 2);
117 ///
118 /// let err = Map::try_from_pairs([("a", 1), ("a", 2)]).unwrap_err();
119 /// assert_eq!(err, Error::NonDeterministic);
120 /// ```
121 pub fn try_from_pairs<K, V, I>(pairs: I) -> Result<Self, Error>
122 where
123 K: Into<Value<'a>>,
124 V: Into<Value<'a>>,
125 I: IntoIterator<Item = (K, V)>,
126 {
127 let mut map = BTreeMap::new();
128 for (k, v) in pairs {
129 if map.insert(k.into(), v.into()).is_some() {
130 return Err(Error::NonDeterministic);
131 }
132 }
133 Ok(Self(map))
134 }
135
136 /// Build a map from a CBOR sequence of alternating key/value items.
137 ///
138 /// Applies the same determinism checks as the binary decoder.
139 ///
140 /// For the fallible input produced by
141 /// [`SequenceDecoder`](crate::SequenceDecoder) and
142 /// [`SequenceReader`](crate::SequenceReader), use
143 /// [`try_from_sequence`](Self::try_from_sequence).
144 ///
145 /// # Errors
146 ///
147 /// * [`Error::UnexpectedEof`] if the sequence has an odd number of
148 /// items (a key with no following value).
149 /// * [`Error::NonDeterministic`] on a duplicate key, or on a key that
150 /// is not strictly greater than the previous key.
151 ///
152 /// ```
153 /// # use cbor_core::{Map, Value};
154 /// let items = [Value::from("a"), Value::from(1), Value::from("b"), Value::from(2)];
155 /// let m = Map::from_sequence(items).unwrap();
156 /// assert_eq!(m.get_ref().len(), 2);
157 /// ```
158 pub fn from_sequence<I>(items: I) -> Result<Self, Error>
159 where
160 I: IntoIterator<Item = Value<'a>>,
161 {
162 let mut iter = items.into_iter();
163 let mut map: BTreeMap<Value<'a>, Value<'a>> = BTreeMap::new();
164 while let Some(key) = iter.next() {
165 let value = iter.next().ok_or(Error::UnexpectedEof)?;
166 if let Some((last_key, _)) = map.last_key_value()
167 && *last_key >= key
168 {
169 return Err(Error::NonDeterministic);
170 }
171 map.insert(key, value);
172 }
173 Ok(Self(map))
174 }
175
176 /// Build a map from a fallible sequence of alternating key/value
177 /// items, stopping at the first error.
178 ///
179 /// Accepts any `IntoIterator<Item = Result<Value, E>>` whose error
180 /// type can carry a CBOR [`Error`] (via `E: From<Error>`). This
181 /// covers both [`SequenceDecoder`](crate::SequenceDecoder)
182 /// (`E = Error`) and [`SequenceReader`](crate::SequenceReader)
183 /// (`E = IoError`).
184 ///
185 /// Determinism checks are the same as
186 /// [`from_sequence`](Self::from_sequence) and are surfaced through
187 /// `E`'s `From<Error>` implementation.
188 ///
189 /// # Errors
190 ///
191 /// Returns the first `Err` yielded by the iterator, or any of the
192 /// determinism errors documented on [`from_sequence`](Self::from_sequence)
193 /// (converted via `E: From<Error>`).
194 ///
195 /// ```
196 /// # use cbor_core::{DecodeOptions, Format, Map};
197 /// // Diagnostic-notation sequence: "a": 1, "b": 2
198 /// let m = Map::try_from_sequence(
199 /// DecodeOptions::new()
200 /// .format(Format::Diagnostic)
201 /// .sequence_decoder(br#""a", 1, "b", 2"#),
202 /// ).unwrap();
203 /// assert_eq!(m.get_ref().len(), 2);
204 /// ```
205 pub fn try_from_sequence<I, E>(items: I) -> Result<Self, E>
206 where
207 I: IntoIterator<Item = Result<Value<'a>, E>>,
208 E: From<Error>,
209 {
210 let mut iter = items.into_iter();
211 let mut map: BTreeMap<Value<'a>, Value<'a>> = BTreeMap::new();
212 while let Some(key) = iter.next() {
213 let key = key?;
214 let value = iter.next().ok_or(Error::UnexpectedEof)??;
215 if let Some((last_key, _)) = map.last_key_value()
216 && *last_key >= key
217 {
218 return Err(Error::NonDeterministic.into());
219 }
220 map.insert(key, value);
221 }
222 Ok(Self(map))
223 }
224}
225
226impl<'a> From<BTreeMap<Value<'a>, Value<'a>>> for Map<'a> {
227 fn from(map: BTreeMap<Value<'a>, Value<'a>>) -> Self {
228 Map(map)
229 }
230}
231
232impl<'a, K: Into<Value<'a>> + Copy, V: Into<Value<'a>> + Copy> From<&BTreeMap<K, V>> for Map<'a> {
233 fn from(map: &BTreeMap<K, V>) -> Self {
234 Map(map.iter().map(|(&k, &v)| (k.into(), v.into())).collect())
235 }
236}
237
238impl<'a, K: Into<Value<'a>> + Copy, V: Into<Value<'a>> + Copy> From<&HashMap<K, V>> for Map<'a> {
239 fn from(map: &HashMap<K, V>) -> Self {
240 Map(map.iter().map(|(&k, &v)| (k.into(), v.into())).collect())
241 }
242}
243
244impl<'a, K: Into<Value<'a>> + Copy, V: Into<Value<'a>> + Copy> From<&[(K, V)]> for Map<'a> {
245 fn from(slice: &[(K, V)]) -> Self {
246 Self(slice.iter().map(|&(k, v)| (k.into(), v.into())).collect())
247 }
248}
249
250impl<'a, const N: usize, K: Into<Value<'a>>, V: Into<Value<'a>>> From<[(K, V); N]> for Map<'a> {
251 fn from(array: [(K, V); N]) -> Self {
252 Self(array.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
253 }
254}
255
256impl<'a, K: Into<Value<'a>>, V: Into<Value<'a>>> From<Vec<(K, V)>> for Map<'a> {
257 fn from(vec: Vec<(K, V)>) -> Self {
258 Self(vec.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
259 }
260}
261
262impl<'a, K: Into<Value<'a>>, V: Into<Value<'a>>> From<Box<[(K, V)]>> for Map<'a> {
263 fn from(boxed: Box<[(K, V)]>) -> Self {
264 Self(
265 Vec::from(boxed)
266 .into_iter()
267 .map(|(k, v)| (k.into(), v.into()))
268 .collect(),
269 )
270 }
271}
272
273impl From<()> for Map<'_> {
274 fn from((): ()) -> Self {
275 Self(BTreeMap::new())
276 }
277}