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