commonware_codec/types/
btree_set.rs1extern crate alloc;
7
8use crate::{
9 codec::{BufsMut, EncodeSize, Read, Write},
10 error::Error,
11 types::read_ordered_set,
12 RangeCfg,
13};
14use alloc::collections::BTreeSet;
15use bytes::{Buf, BufMut};
16
17const BTREESET_TYPE: &str = "BTreeSet";
18
19impl<K: Ord + Eq + Write> Write for BTreeSet<K> {
22 fn write(&self, buf: &mut impl BufMut) {
23 self.len().write(buf);
24
25 for item in self {
27 item.write(buf);
28 }
29 }
30
31 fn write_bufs(&self, buf: &mut impl BufsMut) {
32 self.len().write(buf);
33
34 for item in self {
36 item.write_bufs(buf);
37 }
38 }
39}
40
41impl<K: Ord + Eq + EncodeSize> EncodeSize for BTreeSet<K> {
42 fn encode_size(&self) -> usize {
43 let mut size = self.len().encode_size();
44 for item in self {
45 size += item.encode_size();
46 }
47 size
48 }
49
50 fn encode_inline_size(&self) -> usize {
51 let mut size = self.len().encode_size();
52 for item in self {
53 size += item.encode_inline_size();
54 }
55 size
56 }
57}
58
59impl<K: Read + Clone + Ord + Eq> Read for BTreeSet<K> {
60 type Cfg = (RangeCfg<usize>, K::Cfg);
61
62 fn read_cfg(buf: &mut impl Buf, (range, cfg): &Self::Cfg) -> Result<Self, Error> {
63 let len = usize::read_cfg(buf, range)?;
65 let mut set = Self::new();
66
67 read_ordered_set(buf, len, cfg, |item| set.insert(item), BTREESET_TYPE)?;
69
70 Ok(set)
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::{
78 codec::{Decode, Encode},
79 FixedSize,
80 };
81 use bytes::{Bytes, BytesMut};
82 use core::fmt::Debug;
83
84 fn round_trip_btree<K>(set: &BTreeSet<K>, range_cfg: RangeCfg<usize>, item_cfg: K::Cfg)
86 where
87 K: Write + EncodeSize + Read + Clone + Ord + Eq + Debug + PartialEq,
88 BTreeSet<K>: Read<Cfg = (RangeCfg<usize>, K::Cfg)>
89 + Decode<Cfg = (RangeCfg<usize>, K::Cfg)>
90 + Debug
91 + PartialEq
92 + Write
93 + EncodeSize,
94 {
95 let encoded = set.encode();
96 assert_eq!(set.encode_size(), encoded.len());
97 let config_tuple = (range_cfg, item_cfg);
98 let decoded = BTreeSet::<K>::decode_cfg(encoded, &config_tuple).expect("decode_cfg failed");
99 assert_eq!(set, &decoded);
100 }
101
102 #[test]
103 fn test_empty_btreeset() {
104 let set = BTreeSet::<u32>::new();
105 round_trip_btree(&set, (..).into(), ());
106 assert_eq!(set.encode_size(), 1); let encoded = set.encode();
108 assert_eq!(encoded, Bytes::from_static(&[0]));
109 }
110
111 #[test]
112 fn test_simple_btreeset_u32() {
113 let mut set = BTreeSet::new();
114 set.insert(1u32);
115 set.insert(5u32);
116 set.insert(2u32);
117 round_trip_btree(&set, (..).into(), ());
118 assert_eq!(set.encode_size(), 1 + 3 * u32::SIZE);
119 }
120
121 #[test]
122 fn test_large_btreeset() {
123 let set: BTreeSet<_> = (0..1000u16).collect();
125 round_trip_btree(&set, (1000..=1000).into(), ());
126
127 let set: BTreeSet<_> = (0..1000usize).collect();
129 round_trip_btree(&set, (1000..=1000).into(), (..=1000).into());
130 }
131
132 #[test]
133 fn test_btreeset_decode_length_limit_exceeded() {
134 let mut set = BTreeSet::new();
135 set.insert(1u32);
136 set.insert(5u32);
137 let encoded = set.encode();
138
139 let config_tuple = ((0..=1).into(), ());
140 let result = BTreeSet::<u32>::decode_cfg(encoded, &config_tuple);
141 assert!(matches!(result, Err(Error::InvalidLength(2))));
142 }
143
144 #[test]
145 fn test_btreeset_decode_invalid_item_order() {
146 let mut encoded = BytesMut::new();
147 2usize.write(&mut encoded); 5u32.write(&mut encoded); 2u32.write(&mut encoded); let config_tuple = ((..).into(), ());
152 let result = BTreeSet::<u32>::decode_cfg(encoded, &config_tuple);
153 assert!(matches!(
154 result,
155 Err(Error::Invalid("BTreeSet", "Items must ascend"))
156 ));
157 }
158
159 #[test]
160 fn test_btreeset_decode_duplicate_item() {
161 let mut encoded = BytesMut::new();
162 2usize.write(&mut encoded); 1u32.write(&mut encoded); 1u32.write(&mut encoded); let config_tuple = ((..).into(), ());
167 let result = BTreeSet::<u32>::decode_cfg(encoded, &config_tuple);
168 assert!(matches!(
169 result,
170 Err(Error::Invalid("BTreeSet", "Duplicate item"))
171 ));
172 }
173
174 #[test]
175 fn test_btreeset_deterministic_encoding() {
176 let mut set1 = BTreeSet::new();
177 (0..1000u32).for_each(|i| {
178 set1.insert(i);
179 });
180
181 let mut set2 = BTreeSet::new();
182 (0..1000u32).rev().for_each(|i| {
183 set2.insert(i);
184 });
185
186 assert_eq!(set1.encode(), set2.encode());
187 }
188
189 #[cfg(feature = "arbitrary")]
190 mod conformance {
191 use super::*;
192 use crate::conformance::CodecConformance;
193
194 commonware_conformance::conformance_tests! {
195 CodecConformance<BTreeSet<u8>>,
196 }
197 }
198}