azalea_buf/
write.rs

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