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
287impl<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}