azalea_buf/
write.rs

1use std::{
2    collections::HashMap,
3    io::{self, Write},
4    sync::Arc,
5};
6
7use byteorder::{BigEndian, WriteBytesExt};
8use indexmap::IndexMap;
9
10use super::{MAX_STRING_LENGTH, UnsizedByteArray};
11
12fn write_utf_with_len(buf: &mut impl Write, string: &str, len: usize) -> io::Result<()> {
13    if string.len() > len {
14        panic!(
15            "String too big (was {} bytes encoded, max {})",
16            string.len(),
17            len
18        );
19    }
20    string.as_bytes().to_vec().azalea_write(buf)?;
21    Ok(())
22}
23
24pub trait AzaleaWrite {
25    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()>;
26}
27
28pub trait AzaleaWriteVar {
29    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()>;
30}
31
32impl AzaleaWrite for () {
33    fn azalea_write(&self, _buf: &mut impl Write) -> io::Result<()> {
34        Ok(())
35    }
36}
37
38impl AzaleaWrite for i32 {
39    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
40        WriteBytesExt::write_i32::<BigEndian>(buf, *self)
41    }
42}
43
44impl AzaleaWriteVar for i32 {
45    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
46        let mut buffer = [0];
47        let mut value = *self;
48        if value == 0 {
49            buf.write_all(&buffer)?;
50        }
51        while value != 0 {
52            buffer[0] = (value & 0b0111_1111) as u8;
53            value = (value >> 7) & (i32::MAX >> 6);
54            if value != 0 {
55                buffer[0] |= 0b1000_0000;
56            }
57            buf.write_all(&buffer)?;
58        }
59        Ok(())
60    }
61}
62
63impl AzaleaWrite for UnsizedByteArray {
64    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
65        buf.write_all(self)
66    }
67}
68
69impl<T: AzaleaWrite> AzaleaWrite for Vec<T> {
70    default fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
71        self[..].azalea_write(buf)
72    }
73}
74impl<T: AzaleaWrite> AzaleaWrite for Box<[T]> {
75    default fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
76        self[..].azalea_write(buf)
77    }
78}
79
80impl<T: AzaleaWrite> AzaleaWrite for [T] {
81    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
82        (self.len() as u32).azalea_write_var(buf)?;
83        for item in self {
84            T::azalea_write(item, buf)?;
85        }
86        Ok(())
87    }
88}
89
90macro_rules! impl_for_map_type {
91    ($ty: ident) => {
92        impl<K: AzaleaWrite, V: AzaleaWrite> AzaleaWrite for $ty<K, V> {
93            fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
94                u32::azalea_write_var(&(self.len() as u32), buf)?;
95                for (key, value) in self {
96                    key.azalea_write(buf)?;
97                    value.azalea_write(buf)?;
98                }
99
100                Ok(())
101            }
102        }
103        impl<K: AzaleaWrite, V: AzaleaWriteVar> AzaleaWriteVar for $ty<K, V> {
104            fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
105                u32::azalea_write_var(&(self.len() as u32), buf)?;
106                for (key, value) in self {
107                    key.azalea_write(buf)?;
108                    value.azalea_write_var(buf)?;
109                }
110
111                Ok(())
112            }
113        }
114    };
115}
116
117impl_for_map_type!(HashMap);
118impl_for_map_type!(IndexMap);
119
120impl AzaleaWrite for Vec<u8> {
121    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
122        (self.len() as u32).azalea_write_var(buf)?;
123        buf.write_all(self)
124    }
125}
126
127impl AzaleaWrite for String {
128    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
129        self.as_str().azalea_write(buf)
130    }
131}
132
133impl AzaleaWrite for Box<str> {
134    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
135        (&**self).azalea_write(buf)
136    }
137}
138
139impl AzaleaWrite for &str {
140    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
141        write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
142    }
143}
144
145impl AzaleaWrite for u32 {
146    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
147        i32::azalea_write(&(*self as i32), buf)
148    }
149}
150
151impl AzaleaWriteVar for u32 {
152    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
153        i32::azalea_write_var(&(*self as i32), buf)
154    }
155}
156
157impl AzaleaWriteVar for i64 {
158    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
159        let mut buffer = [0];
160        let mut value = *self;
161        if value == 0 {
162            buf.write_all(&buffer).unwrap();
163        }
164        while value != 0 {
165            buffer[0] = (value & 0b0111_1111) as u8;
166            value = (value >> 7) & (i64::MAX >> 6);
167            if value != 0 {
168                buffer[0] |= 0b1000_0000;
169            }
170            buf.write_all(&buffer)?;
171        }
172        Ok(())
173    }
174}
175
176impl AzaleaWriteVar for u64 {
177    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
178        i64::azalea_write_var(&(*self as i64), buf)
179    }
180}
181
182impl AzaleaWrite for u16 {
183    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
184        i16::azalea_write(&(*self as i16), buf)
185    }
186}
187
188impl AzaleaWriteVar for u16 {
189    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
190        i32::azalea_write_var(&(*self as i32), buf)
191    }
192}
193
194impl<T: AzaleaWriteVar> AzaleaWriteVar for [T] {
195    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
196        u32::azalea_write_var(&(self.len() as u32), buf)?;
197        for i in self {
198            i.azalea_write_var(buf)?;
199        }
200        Ok(())
201    }
202}
203impl<T: AzaleaWriteVar> AzaleaWriteVar for Vec<T> {
204    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
205        self[..].azalea_write_var(buf)
206    }
207}
208impl<T: AzaleaWriteVar> AzaleaWriteVar for Box<[T]> {
209    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
210        self[..].azalea_write_var(buf)
211    }
212}
213
214impl AzaleaWrite for u8 {
215    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
216        WriteBytesExt::write_u8(buf, *self)
217    }
218}
219
220impl AzaleaWrite for i16 {
221    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
222        WriteBytesExt::write_i16::<BigEndian>(buf, *self)
223    }
224}
225
226impl AzaleaWrite for i64 {
227    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
228        WriteBytesExt::write_i64::<BigEndian>(buf, *self)
229    }
230}
231
232impl AzaleaWrite for u64 {
233    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
234        i64::azalea_write(&(*self as i64), buf)
235    }
236}
237
238impl AzaleaWrite for bool {
239    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
240        let byte = u8::from(*self);
241        byte.azalea_write(buf)
242    }
243}
244
245impl AzaleaWrite for i8 {
246    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
247        (*self as u8).azalea_write(buf)
248    }
249}
250
251impl AzaleaWrite for f32 {
252    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
253        WriteBytesExt::write_f32::<BigEndian>(buf, *self)
254    }
255}
256
257impl AzaleaWrite for f64 {
258    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
259        WriteBytesExt::write_f64::<BigEndian>(buf, *self)
260    }
261}
262
263impl<T: AzaleaWrite> AzaleaWrite for Option<T> {
264    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
265        if let Some(s) = self {
266            true.azalea_write(buf)?;
267            s.azalea_write(buf)?;
268        } else {
269            false.azalea_write(buf)?;
270        };
271        Ok(())
272    }
273}
274
275impl<T: AzaleaWriteVar> AzaleaWriteVar for Option<T> {
276    fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> {
277        if let Some(s) = self {
278            true.azalea_write(buf)?;
279            s.azalea_write_var(buf)?;
280        } else {
281            false.azalea_write(buf)?;
282        };
283        Ok(())
284    }
285}
286
287// [T; N]
288impl<T: AzaleaWrite, const N: usize> AzaleaWrite for [T; N] {
289    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
290        for i in self {
291            i.azalea_write(buf)?;
292        }
293        Ok(())
294    }
295}
296
297impl AzaleaWrite for simdnbt::owned::NbtTag {
298    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
299        let mut data = Vec::new();
300        self.write(&mut data);
301        buf.write_all(&data)
302    }
303}
304
305impl AzaleaWrite for simdnbt::owned::NbtCompound {
306    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
307        let mut data = Vec::new();
308        simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data);
309        buf.write_all(&data)
310    }
311}
312
313impl AzaleaWrite for simdnbt::owned::Nbt {
314    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
315        let mut data = Vec::new();
316        self.write_unnamed(&mut data);
317        buf.write_all(&data)
318    }
319}
320
321impl<T> AzaleaWrite for Box<T>
322where
323    T: AzaleaWrite,
324{
325    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
326        T::azalea_write(&**self, buf)
327    }
328}
329
330impl<A: AzaleaWrite, B: AzaleaWrite> AzaleaWrite for (A, B) {
331    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
332        self.0.azalea_write(buf)?;
333        self.1.azalea_write(buf)
334    }
335}
336
337impl<T: AzaleaWrite> AzaleaWrite for Arc<T> {
338    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
339        T::azalea_write(&**self, buf)
340    }
341}