azalea_buf/
write.rs

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