azalea_buf/impls/
extra.rs

1use std::{
2    collections::HashMap,
3    hash::Hash,
4    io::{self, Cursor, Write},
5    sync::Arc,
6};
7
8use indexmap::IndexMap;
9
10use crate::{
11    AzBuf, AzBufLimited, AzBufVar, BufReadError, MAX_STRING_LENGTH, UnsizedByteArray, read_bytes,
12    read_utf_with_len, write_utf_with_len,
13};
14
15impl AzBuf for UnsizedByteArray {
16    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
17        // read to end of the buffer
18        let data = buf.get_ref()[buf.position() as usize..].to_vec();
19        buf.set_position((buf.position()) + data.len() as u64);
20        Ok(UnsizedByteArray(data))
21    }
22    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
23        buf.write_all(self)
24    }
25}
26
27macro_rules! impl_for_map_type {
28    ($ty: ident) => {
29        impl<K: AzBuf + Eq + Hash, V: AzBuf> AzBuf for $ty<K, V> {
30            fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
31                let length = i32::azalea_read_var(buf)? as usize;
32                let mut contents = Self::with_capacity(usize::min(length, 65536));
33                for _ in 0..length {
34                    contents.insert(K::azalea_read(buf)?, V::azalea_read(buf)?);
35                }
36                Ok(contents)
37            }
38            fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
39                u32::azalea_write_var(&(self.len() as u32), buf)?;
40                for (key, value) in self {
41                    key.azalea_write(buf)?;
42                    value.azalea_write(buf)?;
43                }
44
45                Ok(())
46            }
47        }
48        impl<K: AzBuf + Eq + Hash, V: AzBufVar> AzBufVar for $ty<K, V> {
49            fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
50                let length = i32::azalea_read_var(buf)? as usize;
51                let mut contents = Self::with_capacity(usize::min(length, 65536));
52                for _ in 0..length {
53                    contents.insert(K::azalea_read(buf)?, V::azalea_read_var(buf)?);
54                }
55                Ok(contents)
56            }
57            fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
58                u32::azalea_write_var(&(self.len() as u32), buf)?;
59                for (key, value) in self {
60                    key.azalea_write(buf)?;
61                    value.azalea_write_var(buf)?;
62                }
63
64                Ok(())
65            }
66        }
67    };
68}
69
70impl_for_map_type!(HashMap);
71impl_for_map_type!(IndexMap);
72
73macro_rules! impl_for_list_type {
74    ($ty: ty) => {
75        impl<T: AzBuf> AzBuf for $ty {
76            default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
77                let length = u32::azalea_read_var(buf)? as usize;
78                // we limit the capacity to not get exploited into allocating a bunch
79                let mut contents = Vec::with_capacity(usize::min(length, 65536));
80                for _ in 0..length {
81                    contents.push(T::azalea_read(buf)?);
82                }
83                Ok(contents.into())
84            }
85            default fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
86                (self.len() as u32).azalea_write_var(buf)?;
87                for item in self {
88                    T::azalea_write(item, buf)?;
89                }
90                Ok(())
91            }
92        }
93        impl<T: AzBufVar> AzBufVar for $ty {
94            fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
95                let length = i32::azalea_read_var(buf)? as usize;
96                let mut contents = Vec::with_capacity(usize::min(length, 65536));
97                for _ in 0..length {
98                    contents.push(T::azalea_read_var(buf)?);
99                }
100                Ok(contents.into())
101            }
102            fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
103                (self.len() as u32).azalea_write_var(buf)?;
104                for item in self {
105                    T::azalea_write_var(item, buf)?;
106                }
107                Ok(())
108            }
109        }
110        impl<T: AzBuf> AzBufLimited for $ty {
111            fn azalea_read_limited(
112                buf: &mut Cursor<&[u8]>,
113                limit: u32,
114            ) -> Result<Self, BufReadError> {
115                let length = u32::azalea_read_var(buf)?;
116                if length > limit {
117                    return Err(BufReadError::VecLengthTooLong {
118                        length: length as u32,
119                        max_length: limit as u32,
120                    });
121                }
122
123                let mut contents = Vec::with_capacity(u32::min(length, 65536) as usize);
124                for _ in 0..length {
125                    contents.push(T::azalea_read(buf)?);
126                }
127                Ok(contents.into())
128            }
129        }
130    };
131}
132
133impl_for_list_type!(Vec<T>);
134impl_for_list_type!(Box<[T]>);
135
136impl AzBuf for Vec<u8> {
137    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
138        let length = i32::azalea_read_var(buf)? as usize;
139        read_bytes(buf, length).map(|b| b.to_vec())
140    }
141    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
142        (self.len() as u32).azalea_write_var(buf)?;
143        buf.write_all(self)
144    }
145}
146
147impl AzBuf for String {
148    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
149        read_utf_with_len(buf, MAX_STRING_LENGTH).map(Into::into)
150    }
151    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
152        write_utf_with_len(buf, self, MAX_STRING_LENGTH)
153    }
154}
155impl AzBufLimited for String {
156    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError> {
157        read_utf_with_len(buf, limit).map(Into::into)
158    }
159}
160
161impl AzBuf for Box<str> {
162    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
163        read_utf_with_len(buf, MAX_STRING_LENGTH).map(Into::into)
164    }
165    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
166        write_utf_with_len(buf, self, MAX_STRING_LENGTH)
167    }
168}
169
170impl AzBufLimited for Box<str> {
171    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError> {
172        String::azalea_read_limited(buf, limit).map(Into::into)
173    }
174}
175
176impl<T: AzBuf> AzBuf for Option<T> {
177    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
178        let present = bool::azalea_read(buf)?;
179        Ok(if present {
180            Some(T::azalea_read(buf)?)
181        } else {
182            None
183        })
184    }
185    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
186        if let Some(s) = self {
187            true.azalea_write(buf)?;
188            s.azalea_write(buf)?;
189        } else {
190            false.azalea_write(buf)?;
191        };
192        Ok(())
193    }
194}
195
196impl<T: AzBufVar> AzBufVar for Option<T> {
197    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
198        let present = bool::azalea_read(buf)?;
199        Ok(if present {
200            Some(T::azalea_read_var(buf)?)
201        } else {
202            None
203        })
204    }
205    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
206        if let Some(s) = self {
207            true.azalea_write(buf)?;
208            s.azalea_write_var(buf)?;
209        } else {
210            false.azalea_write(buf)?;
211        };
212        Ok(())
213    }
214}
215impl<T: AzBufLimited> AzBufLimited for Option<T> {
216    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError> {
217        let present = bool::azalea_read(buf)?;
218        Ok(if present {
219            Some(T::azalea_read_limited(buf, limit)?)
220        } else {
221            None
222        })
223    }
224}
225
226impl<T: AzBuf, const N: usize> AzBuf for [T; N] {
227    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
228        let mut contents = Vec::with_capacity(N);
229        for _ in 0..N {
230            contents.push(T::azalea_read(buf)?);
231        }
232        Ok(contents
233            .try_into()
234            .unwrap_or_else(|_| unreachable!("The vec is the same size as the array")))
235    }
236    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
237        for i in self {
238            i.azalea_write(buf)?;
239        }
240        Ok(())
241    }
242}
243
244impl AzBuf for simdnbt::owned::NbtTag {
245    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
246        Ok(simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)?)
247    }
248    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
249        let mut data = Vec::new();
250        self.write(&mut data);
251        buf.write_all(&data)
252    }
253}
254
255impl AzBuf for simdnbt::owned::NbtCompound {
256    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
257        match simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)? {
258            simdnbt::owned::NbtTag::Compound(compound) => Ok(compound),
259            _ => Err(BufReadError::Custom("Expected compound tag".to_owned())),
260        }
261    }
262    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
263        let mut data = Vec::new();
264        simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data);
265        buf.write_all(&data)
266    }
267}
268
269impl AzBuf for simdnbt::owned::Nbt {
270    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
271        Ok(simdnbt::owned::read_unnamed(buf)?)
272    }
273    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
274        let mut data = Vec::new();
275        self.write_unnamed(&mut data);
276        buf.write_all(&data)
277    }
278}
279
280impl<T> AzBuf for Box<T>
281where
282    T: AzBuf,
283{
284    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
285        T::azalea_read(buf).map(Box::new)
286    }
287    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
288        T::azalea_write(&**self, buf)
289    }
290}
291
292impl<A: AzBuf, B: AzBuf> AzBuf for (A, B) {
293    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
294        Ok((A::azalea_read(buf)?, B::azalea_read(buf)?))
295    }
296    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
297        self.0.azalea_write(buf)?;
298        self.1.azalea_write(buf)
299    }
300}
301
302impl<T: AzBuf> AzBuf for Arc<T> {
303    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
304        Ok(Arc::new(T::azalea_read(buf)?))
305    }
306    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
307        T::azalea_write(&**self, buf)
308    }
309}