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