1extern crate alloc;
7
8use crate::{
9 codec::{BufsMut, EncodeSize, Read, Write},
10 error::Error,
11 types::read_ordered_map,
12 RangeCfg,
13};
14use alloc::collections::BTreeMap;
15use bytes::{Buf, BufMut};
16
17const BTREEMAP_TYPE: &str = "BTreeMap";
18
19impl<K: Ord + Eq + Write, V: Write> Write for BTreeMap<K, V> {
22 fn write(&self, buf: &mut impl BufMut) {
23 self.len().write(buf);
24
25 for (k, v) in self {
27 k.write(buf);
28 v.write(buf);
29 }
30 }
31
32 fn write_bufs(&self, buf: &mut impl BufsMut) {
33 self.len().write(buf);
34
35 for (k, v) in self {
37 k.write_bufs(buf);
38 v.write_bufs(buf);
39 }
40 }
41}
42
43impl<K: Ord + Eq + EncodeSize, V: EncodeSize> EncodeSize for BTreeMap<K, V> {
44 fn encode_size(&self) -> usize {
45 let mut size = self.len().encode_size();
47
48 for (k, v) in self {
50 size += k.encode_size();
51 size += v.encode_size();
52 }
53 size
54 }
55
56 fn encode_inline_size(&self) -> usize {
57 let mut size = self.len().encode_size();
59
60 for (k, v) in self {
62 size += k.encode_inline_size();
63 size += v.encode_inline_size();
64 }
65 size
66 }
67}
68
69impl<K: Read + Clone + Ord + Eq, V: Read + Clone> Read for BTreeMap<K, V> {
70 type Cfg = (RangeCfg<usize>, (K::Cfg, V::Cfg));
71
72 fn read_cfg(buf: &mut impl Buf, (range, (k_cfg, v_cfg)): &Self::Cfg) -> Result<Self, Error> {
73 let len = usize::read_cfg(buf, range)?;
75 let mut map = Self::new();
76
77 read_ordered_map(
79 buf,
80 len,
81 k_cfg,
82 v_cfg,
83 |k, v| map.insert(k, v),
84 BTREEMAP_TYPE,
85 )?;
86
87 Ok(map)
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use crate::{Decode, Encode, FixedSize};
95 use bytes::{Bytes, BytesMut};
96 use core::fmt::Debug;
97
98 fn round_trip_btree<K, V, KCfg, VCfg>(
100 map: &BTreeMap<K, V>,
101 range_cfg: RangeCfg<usize>,
102 k_cfg: KCfg,
103 v_cfg: VCfg,
104 ) where
105 K: Write + EncodeSize + Read<Cfg = KCfg> + Clone + Ord + Eq + PartialEq + Debug,
106 V: Write + EncodeSize + Read<Cfg = VCfg> + Clone + PartialEq + Debug,
107 BTreeMap<K, V>: Read<Cfg = (RangeCfg<usize>, (K::Cfg, V::Cfg))>
108 + Decode<Cfg = (RangeCfg<usize>, (K::Cfg, V::Cfg))>
109 + PartialEq
110 + Write
111 + EncodeSize,
112 {
113 let encoded = map.encode();
114 assert_eq!(encoded.len(), map.encode_size());
115 let config_tuple = (range_cfg, (k_cfg, v_cfg));
116 let decoded = BTreeMap::<K, V>::decode_cfg(encoded, &config_tuple)
117 .expect("decode_cfg failed for BTreeMap");
118 assert_eq!(map, &decoded);
119 }
120
121 #[test]
122 fn test_empty_btreemap() {
123 let map = BTreeMap::<u32, u64>::new();
124 round_trip_btree(&map, (..).into(), (), ());
125 assert_eq!(map.encode_size(), 1); let encoded = map.encode();
127 assert_eq!(encoded, Bytes::from_static(&[0]));
128 }
129
130 #[test]
131 fn test_simple_btreemap_u32_u64() {
132 let mut map = BTreeMap::new();
133 map.insert(1u32, 100u64);
134 map.insert(5u32, 500u64);
135 map.insert(2u32, 200u64);
136 round_trip_btree(&map, (..).into(), (), ());
137 assert_eq!(map.encode_size(), 1 + 3 * (u32::SIZE + u64::SIZE));
138 let mut expected = BytesMut::new();
140 3usize.write(&mut expected); 1u32.write(&mut expected);
142 100u64.write(&mut expected);
143 2u32.write(&mut expected);
144 200u64.write(&mut expected);
145 5u32.write(&mut expected);
146 500u64.write(&mut expected);
147 assert_eq!(map.encode(), expected.freeze());
148 }
149
150 #[test]
151 fn test_large_btreemap() {
152 let mut map = BTreeMap::new();
154 for i in 0..1000 {
155 map.insert(i as u16, i as u64 * 2);
156 }
157 round_trip_btree(&map, (0..=1000).into(), (), ());
158
159 let mut map = BTreeMap::new();
161 for i in 0..1000usize {
162 map.insert(i, 1000usize + i);
163 }
164 round_trip_btree(
165 &map,
166 (0..=1000).into(),
167 (..=1000).into(),
168 (1000..=2000).into(),
169 );
170 }
171
172 #[test]
173 fn test_btreemap_decode_length_limit_exceeded() {
174 let mut map = BTreeMap::new();
175 map.insert(1u32, 100u64);
176 map.insert(5u32, 500u64);
177
178 let encoded = map.encode();
179 let config_tuple = ((0..=1).into(), ((), ()));
180
181 let result = BTreeMap::<u32, u64>::decode_cfg(encoded, &config_tuple);
182 assert!(matches!(result, Err(Error::InvalidLength(2))));
183 }
184
185 #[test]
186 fn test_btreemap_decode_invalid_key_order() {
187 let mut encoded = BytesMut::new();
188 2usize.write(&mut encoded); 5u32.write(&mut encoded); 500u64.write(&mut encoded); 2u32.write(&mut encoded); 200u64.write(&mut encoded); let range = (..).into();
195 let config_tuple = (range, ((), ()));
196
197 let result = BTreeMap::<u32, u64>::decode_cfg(encoded, &config_tuple);
198 assert!(matches!(
199 result,
200 Err(Error::Invalid("BTreeMap", "Keys must ascend"))
201 ));
202 }
203
204 #[test]
205 fn test_btreemap_decode_duplicate_key() {
206 let mut encoded = BytesMut::new();
207 2usize.write(&mut encoded); 1u32.write(&mut encoded); 100u64.write(&mut encoded); 1u32.write(&mut encoded); 200u64.write(&mut encoded); let range = (..).into();
214 let config_tuple = (range, ((), ()));
215
216 let result = BTreeMap::<u32, u64>::decode_cfg(encoded, &config_tuple);
217 assert!(matches!(
218 result,
219 Err(Error::Invalid("BTreeMap", "Duplicate key"))
220 ));
221 }
222
223 #[test]
224 fn test_btreemap_deterministic_encoding() {
225 let mut map2 = BTreeMap::new();
227 (0..=1000u32).for_each(|i| {
228 map2.insert(i, i * 2);
229 });
230
231 let mut map1 = BTreeMap::new();
233 (0..=1000u32).rev().for_each(|i| {
234 map1.insert(i, i * 2);
235 });
236
237 assert_eq!(map1.encode(), map2.encode());
238 }
239
240 #[cfg(feature = "arbitrary")]
241 mod conformance {
242 use super::*;
243 use crate::conformance::CodecConformance;
244
245 commonware_conformance::conformance_tests! {
246 CodecConformance<BTreeMap<u32, u32>>,
247 }
248 }
249}