1extern crate alloc;
7
8use crate::{
9 codec::{EncodeSize, Read, Write},
10 error::Error,
11 RangeCfg,
12};
13use alloc::collections::BTreeMap;
14use bytes::{Buf, BufMut};
15use core::cmp::Ordering;
16
17const BTREEMAP_TYPE: &str = "BTreeMap";
18
19fn read_ordered_map<K, V, F>(
21 buf: &mut impl Buf,
22 len: usize,
23 k_cfg: &K::Cfg,
24 v_cfg: &V::Cfg,
25 mut insert: F,
26 map_type: &'static str,
27) -> Result<(), Error>
28where
29 K: Read + Ord,
30 V: Read,
31 F: FnMut(K, V) -> Option<V>,
32{
33 let mut last: Option<(K, V)> = None;
34 for _ in 0..len {
35 let key = K::read_cfg(buf, k_cfg)?;
37
38 if let Some((ref last_key, _)) = last {
40 match key.cmp(last_key) {
41 Ordering::Equal => return Err(Error::Invalid(map_type, "Duplicate key")),
42 Ordering::Less => return Err(Error::Invalid(map_type, "Keys must ascend")),
43 _ => {}
44 }
45 }
46
47 let value = V::read_cfg(buf, v_cfg)?;
49
50 if let Some((last_key, last_value)) = last.take() {
52 insert(last_key, last_value);
53 }
54 last = Some((key, value));
55 }
56
57 if let Some((last_key, last_value)) = last {
59 insert(last_key, last_value);
60 }
61
62 Ok(())
63}
64
65impl<K: Ord + Eq + Write, V: Write> Write for BTreeMap<K, V> {
68 fn write(&self, buf: &mut impl BufMut) {
69 self.len().write(buf);
70
71 for (k, v) in self {
73 k.write(buf);
74 v.write(buf);
75 }
76 }
77}
78
79impl<K: Ord + Eq + EncodeSize, V: EncodeSize> EncodeSize for BTreeMap<K, V> {
80 fn encode_size(&self) -> usize {
81 let mut size = self.len().encode_size();
83
84 for (k, v) in self {
86 size += k.encode_size();
87 size += v.encode_size();
88 }
89 size
90 }
91}
92
93impl<K: Read + Clone + Ord + Eq, V: Read + Clone> Read for BTreeMap<K, V> {
94 type Cfg = (RangeCfg<usize>, (K::Cfg, V::Cfg));
95
96 fn read_cfg(buf: &mut impl Buf, (range, (k_cfg, v_cfg)): &Self::Cfg) -> Result<Self, Error> {
97 let len = usize::read_cfg(buf, range)?;
99 let mut map = BTreeMap::new();
100
101 read_ordered_map(
103 buf,
104 len,
105 k_cfg,
106 v_cfg,
107 |k, v| map.insert(k, v),
108 BTREEMAP_TYPE,
109 )?;
110
111 Ok(map)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use crate::{Decode, Encode, FixedSize};
119 use bytes::{Bytes, BytesMut};
120 use core::fmt::Debug;
121
122 fn round_trip_btree<K, V, KCfg, VCfg>(
124 map: &BTreeMap<K, V>,
125 range_cfg: RangeCfg<usize>,
126 k_cfg: KCfg,
127 v_cfg: VCfg,
128 ) where
129 K: Write + EncodeSize + Read<Cfg = KCfg> + Clone + Ord + Eq + PartialEq + Debug,
130 V: Write + EncodeSize + Read<Cfg = VCfg> + Clone + PartialEq + Debug,
131 BTreeMap<K, V>: Read<Cfg = (RangeCfg<usize>, (K::Cfg, V::Cfg))>
132 + Decode<Cfg = (RangeCfg<usize>, (K::Cfg, V::Cfg))>
133 + PartialEq
134 + Write
135 + EncodeSize,
136 {
137 let encoded = map.encode();
138 assert_eq!(encoded.len(), map.encode_size());
139 let config_tuple = (range_cfg, (k_cfg, v_cfg));
140 let decoded = BTreeMap::<K, V>::decode_cfg(encoded, &config_tuple)
141 .expect("decode_cfg failed for BTreeMap");
142 assert_eq!(map, &decoded);
143 }
144
145 #[test]
146 fn test_empty_btreemap() {
147 let map = BTreeMap::<u32, u64>::new();
148 round_trip_btree(&map, (..).into(), (), ());
149 assert_eq!(map.encode_size(), 1); let encoded = map.encode();
151 assert_eq!(encoded, Bytes::from_static(&[0]));
152 }
153
154 #[test]
155 fn test_simple_btreemap_u32_u64() {
156 let mut map = BTreeMap::new();
157 map.insert(1u32, 100u64);
158 map.insert(5u32, 500u64);
159 map.insert(2u32, 200u64);
160 round_trip_btree(&map, (..).into(), (), ());
161 assert_eq!(map.encode_size(), 1 + 3 * (u32::SIZE + u64::SIZE));
162 let mut expected = BytesMut::new();
164 3usize.write(&mut expected); 1u32.write(&mut expected);
166 100u64.write(&mut expected);
167 2u32.write(&mut expected);
168 200u64.write(&mut expected);
169 5u32.write(&mut expected);
170 500u64.write(&mut expected);
171 assert_eq!(map.encode(), expected.freeze());
172 }
173
174 #[test]
175 fn test_large_btreemap() {
176 let mut map = BTreeMap::new();
178 for i in 0..1000 {
179 map.insert(i as u16, i as u64 * 2);
180 }
181 round_trip_btree(&map, (0..=1000).into(), (), ());
182
183 let mut map = BTreeMap::new();
185 for i in 0..1000usize {
186 map.insert(i, 1000usize + i);
187 }
188 round_trip_btree(
189 &map,
190 (0..=1000).into(),
191 (..=1000).into(),
192 (1000..=2000).into(),
193 );
194 }
195
196 #[test]
197 fn test_btreemap_decode_length_limit_exceeded() {
198 let mut map = BTreeMap::new();
199 map.insert(1u32, 100u64);
200 map.insert(5u32, 500u64);
201
202 let encoded = map.encode();
203 let config_tuple = ((0..=1).into(), ((), ()));
204
205 let result = BTreeMap::<u32, u64>::decode_cfg(encoded, &config_tuple);
206 assert!(matches!(result, Err(Error::InvalidLength(2))));
207 }
208
209 #[test]
210 fn test_btreemap_decode_invalid_key_order() {
211 let mut encoded = BytesMut::new();
212 2usize.write(&mut encoded); 5u32.write(&mut encoded); 500u64.write(&mut encoded); 2u32.write(&mut encoded); 200u64.write(&mut encoded); let range = (..).into();
219 let config_tuple = (range, ((), ()));
220
221 let result = BTreeMap::<u32, u64>::decode_cfg(encoded, &config_tuple);
222 assert!(matches!(
223 result,
224 Err(Error::Invalid("BTreeMap", "Keys must ascend"))
225 ));
226 }
227
228 #[test]
229 fn test_btreemap_decode_duplicate_key() {
230 let mut encoded = BytesMut::new();
231 2usize.write(&mut encoded); 1u32.write(&mut encoded); 100u64.write(&mut encoded); 1u32.write(&mut encoded); 200u64.write(&mut encoded); let range = (..).into();
238 let config_tuple = (range, ((), ()));
239
240 let result = BTreeMap::<u32, u64>::decode_cfg(encoded, &config_tuple);
241 assert!(matches!(
242 result,
243 Err(Error::Invalid("BTreeMap", "Duplicate key"))
244 ));
245 }
246
247 #[test]
248 fn test_btreemap_deterministic_encoding() {
249 let mut map2 = BTreeMap::new();
251 (0..=1000u32).for_each(|i| {
252 map2.insert(i, i * 2);
253 });
254
255 let mut map1 = BTreeMap::new();
257 (0..=1000u32).rev().for_each(|i| {
258 map1.insert(i, i * 2);
259 });
260
261 assert_eq!(map1.encode(), map2.encode());
262 }
263}