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}