1use anyhow::{bail, Result};
2use byteorder::{ReadBytesExt, WriteBytesExt, BE};
3use std::io;
4use uuid::Uuid;
5
6#[inline]
7pub fn write_bool(t: &mut impl io::Write, v: bool) -> Result<()> {
8 t.write_u8(v as u8).map_err(From::from)
9}
10
11#[inline]
12pub fn read_bool(t: &mut impl io::Read) -> Result<bool> {
13 let i = t.read_u8()?;
14 if i == 0 {
15 return Ok(false);
16 } else if i == 1 {
17 return Ok(true);
18 }
19 Err(anyhow::Error::msg("not a bool"))
20}
21
22#[inline]
23pub fn write_byte(t: &mut impl io::Write, v: i8) -> Result<()> {
24 t.write_i8(v).map_err(From::from)
25}
26
27#[inline]
28pub fn read_byte(t: &mut impl io::Read) -> Result<i8> {
29 t.read_i8().map_err(From::from)
30}
31
32#[inline]
33pub fn write_unsigned_byte(t: &mut impl io::Write, v: u8) -> Result<()> {
34 t.write_u8(v).map_err(From::from)
35}
36
37#[inline]
38pub fn read_unsigned_byte(t: &mut impl io::Read) -> Result<u8> {
39 t.read_u8().map_err(From::from)
40}
41
42#[inline]
43pub fn write_short(t: &mut impl io::Write, v: i16) -> Result<()> {
44 t.write_i16::<BE>(v).map_err(From::from)
45}
46
47#[inline]
48pub fn read_short(t: &mut impl io::Read) -> Result<i16> {
49 t.read_i16::<BE>().map_err(From::from)
50}
51
52#[inline]
53pub fn write_unsigned_short(t: &mut impl io::Write, v: u16) -> Result<()> {
54 t.write_u16::<BE>(v).map_err(From::from)
55}
56
57#[inline]
58pub fn read_unsigned_short(t: &mut impl io::Read) -> Result<u16> {
59 t.read_u16::<BE>().map_err(From::from)
60}
61
62#[inline]
63pub fn write_int(t: &mut impl io::Write, v: i32) -> Result<()> {
64 t.write_i32::<BE>(v).map_err(From::from)
65}
66
67#[inline]
68pub fn read_int(t: &mut impl io::Read) -> Result<i32> {
69 t.read_i32::<BE>().map_err(From::from)
70}
71
72#[inline]
73pub fn write_long(t: &mut impl io::Write, v: i64) -> Result<()> {
74 t.write_i64::<BE>(v).map_err(From::from)
75}
76
77#[inline]
78pub fn read_long(t: &mut impl io::Read) -> Result<i64> {
79 t.read_i64::<BE>().map_err(From::from)
80}
81
82#[inline]
83pub fn write_float(t: &mut impl io::Write, v: f32) -> Result<()> {
84 t.write_f32::<BE>(v).map_err(From::from)
85}
86
87#[inline]
88pub fn read_float(t: &mut impl io::Read) -> Result<f32> {
89 t.read_f32::<BE>().map_err(From::from)
90}
91
92#[inline]
93pub fn write_double(t: &mut impl io::Write, v: f64) -> Result<()> {
94 t.write_f64::<BE>(v).map_err(From::from)
95}
96
97#[inline]
98pub fn read_double(t: &mut impl io::Read) -> Result<f64> {
99 t.read_f64::<BE>().map_err(From::from)
100}
101
102#[inline]
103pub fn write_string(t: &mut impl io::Write, v: &String) -> Result<()> {
104 write_var_int(t, v.len() as i32)?;
105 t.write_all(v.as_bytes()).map_err(From::from)
106}
107
108#[inline]
109pub fn read_string(t: &mut impl io::Read) -> Result<String> {
110 let len = read_var_int(t)? as usize;
111 let mut buf = vec![0; len];
112 t.read_exact(&mut buf)?;
113 Ok(String::from_utf8(buf)?)
114}
115
116#[inline]
117pub fn write_chat(t: &mut impl io::Write, v: &String) -> Result<()> {
118 if v.len() > 262144 {
119 return Err(anyhow::Error::msg(
120 "chat message exceeds maximum length of 26144",
121 ));
122 }
123 write_string(t, v)
124}
125
126#[inline]
127pub fn read_chat(t: &mut impl io::Read) -> Result<String> {
128 let chat = read_string(t)?;
129 if chat.len() > 262144 {
130 return Err(anyhow::Error::msg(
131 "chat message exceeds maximum length of 26144",
132 ));
133 }
134 Ok(chat)
135}
136
137#[inline]
138pub fn write_identifier(t: &mut impl io::Write, v: &String) -> Result<()> {
139 if v.len() > 32767 {
140 return Err(anyhow::Error::msg(
141 "identifier exceeds maximum length of 32767",
142 ));
143 }
144 write_string(t, v)
145}
146
147#[inline]
148pub fn read_identifier(t: &mut impl io::Read) -> Result<String> {
149 let id = read_string(t)?;
150 if id.len() > 32767 {
151 return Err(anyhow::Error::msg(
152 "identifier exceeds maximum length of 32767",
153 ));
154 }
155 Ok(id)
156}
157
158#[inline]
159pub fn write_uuid(t: &mut impl io::Write, v: Uuid) -> Result<()> {
160 t.write_all(v.as_bytes()).map_err(From::from)
161}
162
163#[inline]
164pub fn read_uuid(t: &mut impl io::Read) -> Result<Uuid> {
165 let mut bytes = [0; 16];
166 t.read_exact(&mut bytes)?;
167 Ok(Uuid::from_bytes(bytes))
168}
169
170#[inline]
171pub fn write_byte_array(t: &mut impl io::Write, v: &Vec<u8>) -> Result<()> {
172 write_var_int(t, v.len() as i32)?;
173 t.write_all(v.as_slice()).map_err(From::from)
174}
175
176#[inline]
177pub fn read_byte_array(t: &mut impl io::Read) -> Result<Vec<u8>> {
178 let len = read_var_int(t)? as usize;
179 let mut buf = vec![0; len];
180 t.read_exact(&mut buf[..])?;
181 Ok(buf)
182}
183
184#[inline]
185pub fn write_var_int(t: &mut impl io::Write, v: i32) -> Result<()> {
186 let mut x = v as u32;
187 loop {
188 let mut temp = (x & 0b0111_1111) as u8;
189 x >>= 7;
190 if x != 0 {
191 temp |= 0b1000_0000;
192 }
193
194 t.write_all(&[temp])?;
195
196 if x == 0 {
197 break;
198 }
199 }
200 Ok(())
201}
202
203#[inline]
204pub fn read_var_int(t: &mut impl io::Read) -> Result<i32> {
205 let mut num_read = 0;
206 let mut result = 0;
207
208 loop {
209 let read = t.read_u8()?;
210 let value = i32::from(read & 0b0111_1111);
211 result |= value.overflowing_shl(7 * num_read).0;
212
213 num_read += 1;
214
215 if num_read > 5 {
216 bail!("Varint is too large");
217 }
218 if read & 0b1000_0000 == 0 {
219 break;
220 }
221 }
222
223 Ok(result)
224}
225
226#[inline]
227pub fn write_var_long(t: &mut impl io::Write, v: i64) -> Result<()> {
228 let mut x = v as u64;
229 loop {
230 let mut temp = (x & 0b0111_1111) as u8;
231 x >>= 7;
232 if x != 0 {
233 temp |= 0b1000_0000;
234 }
235
236 t.write_u8(temp).unwrap();
237
238 if x == 0 {
239 break;
240 }
241 }
242
243 Ok(())
244}
245
246#[inline]
247pub fn read_var_long(t: &mut impl io::Read) -> Result<i64> {
248 let mut num_read = 0;
249 let mut result = 0;
250
251 loop {
252 let read = read_unsigned_byte(t)?;
253 let value = i64::from(read & 0b0111_1111);
254 result |= value.overflowing_shl(7 * num_read).0;
255
256 num_read += 1;
257
258 if num_read > 10 {
259 bail!("VarLong is too large.");
260 }
261 if read & 0b1000_0000 == 0 {
262 break;
263 }
264 }
265 Ok(result)
266}
267
268#[inline]
269pub fn write_bitset(t: &mut impl io::Write, v: &Vec<i64>) -> Result<()> {
270 write_var_int(t, v.len() as i32)?;
271 for i in v {
272 write_long(t, *i)?
273 }
274 Ok(())
275}
276
277#[inline]
278pub fn read_bitset(t: &mut impl io::Read) -> Result<Vec<i64>> {
279 let mut data: Vec<i64> = Vec::new();
280 let len = read_var_int(t)? as usize;
281 for i in 0..len {
282 data.insert(i, read_long(t)?);
283 }
284 Ok(data)
285}
286
287#[inline]
288pub fn write_position(t: &mut impl io::Write, x: i32, y: i32, z: i32) -> Result<()> {
289 t.write_u64::<BE>(
290 (x as u64 & 0x3FFFFFF) << 38 | (z as u64 & 0x3FFFFFF) << 12 | (y as u64 & 0xFFF),
291 )
292 .map_err(From::from)
293}
294
295#[inline]
296pub fn read_position(t: &mut impl io::Read) -> Result<(i32, i32, i32)> {
297 let v = read_long(t)?;
298
299 let mut x = (v >> 38) as i32;
300 let mut y = (v & 0xFFF) as i32;
301 let mut z = (v << 26 >> 38) as i32;
302
303 if x >= 1 << 25 {
304 x -= 1 << 26;
305 }
306 if y >= 1 << 11 {
307 y -= 1 << 12;
308 }
309 if z >= 1 << 25 {
310 z -= 1 << 26;
311 }
312 return Ok((x, y, z));
313}
314
315#[inline]
316pub fn write_nbt(t: &mut impl io::Write, v: &nbt::Blob) -> Result<()> {
317 v.to_writer(t).map_err(From::from)
318}
319
320#[inline]
321pub fn read_nbt(t: &mut impl io::Read) -> Result<nbt::Blob> {
322 nbt::Blob::from_reader(t).map_err(From::from)
323}