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