valence_protocol/impls/
map.rs
1use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
2use std::hash::{BuildHasher, Hash};
3use std::io::Write;
4
5use anyhow::ensure;
6
7use crate::impls::cautious_capacity;
8use crate::{Decode, Encode, VarInt};
9
10impl<T> Encode for BTreeSet<T>
11where
12 T: Encode,
13{
14 fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
15 let len = self.len();
16
17 ensure!(
18 i32::try_from(len).is_ok(),
19 "length of B-tree set ({len}) exceeds i32::MAX"
20 );
21
22 VarInt(len as i32).encode(&mut w)?;
23
24 for val in self {
25 val.encode(&mut w)?;
26 }
27
28 Ok(())
29 }
30}
31
32impl<'a, T> Decode<'a> for BTreeSet<T>
33where
34 T: Ord + Decode<'a>,
35{
36 fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
37 let len = VarInt::decode(r)?.0;
38 ensure!(
39 len >= 0,
40 "attempt to decode B-tree set with negative length"
41 );
42 let len = len as usize;
43
44 let mut set = BTreeSet::new();
45
46 for _ in 0..len {
47 ensure!(
48 set.insert(T::decode(r)?),
49 "encountered duplicate item while decoding B-tree set"
50 );
51 }
52
53 Ok(set)
54 }
55}
56
57impl<T, S> Encode for HashSet<T, S>
58where
59 T: Encode,
60{
61 fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
62 let len = self.len();
63
64 ensure!(
65 i32::try_from(len).is_ok(),
66 "length of hash set ({len}) exceeds i32::MAX"
67 );
68
69 VarInt(len as i32).encode(&mut w)?;
70
71 for val in self {
72 val.encode(&mut w)?;
73 }
74
75 Ok(())
76 }
77}
78
79impl<'a, T, S> Decode<'a> for HashSet<T, S>
80where
81 T: Eq + Hash + Decode<'a>,
82 S: BuildHasher + Default,
83{
84 fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
85 let len = VarInt::decode(r)?.0;
86 ensure!(len >= 0, "attempt to decode hash set with negative length");
87 let len = len as usize;
88
89 let mut set = HashSet::with_capacity_and_hasher(cautious_capacity::<T>(len), S::default());
90
91 for _ in 0..len {
92 ensure!(
93 set.insert(T::decode(r)?),
94 "encountered duplicate item while decoding hash set"
95 );
96 }
97
98 Ok(set)
99 }
100}
101
102impl<K, V> Encode for BTreeMap<K, V>
103where
104 K: Encode,
105 V: Encode,
106{
107 fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
108 let len = self.len();
109
110 ensure!(
111 i32::try_from(len).is_ok(),
112 "length of B-tree map ({len}) exceeds i32::MAX"
113 );
114
115 VarInt(len as i32).encode(&mut w)?;
116
117 for pair in self {
118 pair.encode(&mut w)?;
119 }
120
121 Ok(())
122 }
123}
124
125impl<'a, K, V> Decode<'a> for BTreeMap<K, V>
126where
127 K: Ord + Decode<'a>,
128 V: Decode<'a>,
129{
130 fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
131 let len = VarInt::decode(r)?.0;
132 ensure!(
133 len >= 0,
134 "attempt to decode B-tree map with negative length"
135 );
136 let len = len as usize;
137
138 let mut map = BTreeMap::new();
139
140 for _ in 0..len {
141 ensure!(
142 map.insert(K::decode(r)?, V::decode(r)?).is_none(),
143 "encountered duplicate key while decoding B-tree map"
144 );
145 }
146
147 Ok(map)
148 }
149}
150
151impl<K, V, S> Encode for HashMap<K, V, S>
152where
153 K: Encode,
154 V: Encode,
155{
156 fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
157 let len = self.len();
158
159 ensure!(
160 i32::try_from(len).is_ok(),
161 "length of hash map ({len}) exceeds i32::MAX"
162 );
163
164 VarInt(len as i32).encode(&mut w)?;
165
166 for pair in self {
167 pair.encode(&mut w)?;
168 }
169
170 Ok(())
171 }
172}
173
174impl<'a, K, V, S> Decode<'a> for HashMap<K, V, S>
175where
176 K: Eq + Hash + Decode<'a>,
177 V: Decode<'a>,
178 S: BuildHasher + Default,
179{
180 fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
181 let len = VarInt::decode(r)?.0;
182 ensure!(len >= 0, "attempt to decode hash map with negative length");
183 let len = len as usize;
184
185 let mut map =
186 HashMap::with_capacity_and_hasher(cautious_capacity::<(K, V)>(len), S::default());
187
188 for _ in 0..len {
189 ensure!(
190 map.insert(K::decode(r)?, V::decode(r)?).is_none(),
191 "encountered duplicate item while decoding hash map"
192 );
193 }
194
195 Ok(map)
196 }
197}