use std::{ collections::HashMap, io::{self, Write}, sync::Arc, }; use byteorder::{BigEndian, WriteBytesExt}; use super::{MAX_STRING_LENGTH, UnsizedByteArray}; fn write_utf_with_len(buf: &mut impl Write, string: &str, len: usize) -> Result<(), io::Error> { if string.len() > len { panic!( "String too big (was {} bytes encoded, max {})", string.len(), len ); } string.as_bytes().to_vec().azalea_write(buf)?; Ok(()) } pub trait AzaleaWrite { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error>; } pub trait AzaleaWriteVar { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error>; } impl AzaleaWrite for i32 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { WriteBytesExt::write_i32::(buf, *self) } } impl AzaleaWriteVar for i32 { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { let mut buffer = [0]; let mut value = *self; if value == 0 { buf.write_all(&buffer).unwrap(); } while value != 0 { buffer[0] = (value & 0b0111_1111) as u8; value = (value >> 7) & (i32::MAX >> 6); if value != 0 { buffer[0] |= 0b1000_0000; } buf.write_all(&buffer)?; } Ok(()) } } impl AzaleaWrite for UnsizedByteArray { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { buf.write_all(self) } } impl AzaleaWrite for Vec { default fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { self[..].azalea_write(buf) } } impl AzaleaWrite for Box<[T]> { default fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { self[..].azalea_write(buf) } } impl AzaleaWrite for [T] { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { (self.len() as u32).azalea_write_var(buf)?; for item in self { T::azalea_write(item, buf)?; } Ok(()) } } impl AzaleaWrite for HashMap { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { u32::azalea_write_var(&(self.len() as u32), buf)?; for (key, value) in self { key.azalea_write(buf)?; value.azalea_write(buf)?; } Ok(()) } } impl AzaleaWriteVar for HashMap { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { u32::azalea_write_var(&(self.len() as u32), buf)?; for (key, value) in self { key.azalea_write(buf)?; value.azalea_write_var(buf)?; } Ok(()) } } impl AzaleaWrite for Vec { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { (self.len() as u32).azalea_write_var(buf)?; buf.write_all(self) } } impl AzaleaWrite for String { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { write_utf_with_len(buf, self, MAX_STRING_LENGTH.into()) } } impl AzaleaWrite for &str { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { write_utf_with_len(buf, self, MAX_STRING_LENGTH.into()) } } impl AzaleaWrite for u32 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { i32::azalea_write(&(*self as i32), buf) } } impl AzaleaWriteVar for u32 { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { i32::azalea_write_var(&(*self as i32), buf) } } impl AzaleaWriteVar for i64 { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { let mut buffer = [0]; let mut value = *self; if value == 0 { buf.write_all(&buffer).unwrap(); } while value != 0 { buffer[0] = (value & 0b0111_1111) as u8; value = (value >> 7) & (i64::MAX >> 6); if value != 0 { buffer[0] |= 0b1000_0000; } buf.write_all(&buffer)?; } Ok(()) } } impl AzaleaWriteVar for u64 { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { i64::azalea_write_var(&(*self as i64), buf) } } impl AzaleaWrite for u16 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { i16::azalea_write(&(*self as i16), buf) } } impl AzaleaWriteVar for u16 { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { i32::azalea_write_var(&(*self as i32), buf) } } impl AzaleaWriteVar for [T] { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { u32::azalea_write_var(&(self.len() as u32), buf)?; for i in self { i.azalea_write_var(buf)?; } Ok(()) } } impl AzaleaWriteVar for Vec { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { self[..].azalea_write_var(buf) } } impl AzaleaWriteVar for Box<[T]> { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { self[..].azalea_write_var(buf) } } impl AzaleaWrite for u8 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { WriteBytesExt::write_u8(buf, *self) } } impl AzaleaWrite for i16 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { WriteBytesExt::write_i16::(buf, *self) } } impl AzaleaWrite for i64 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { WriteBytesExt::write_i64::(buf, *self) } } impl AzaleaWrite for u64 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { i64::azalea_write(&(*self as i64), buf) } } impl AzaleaWrite for bool { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { let byte = u8::from(*self); byte.azalea_write(buf) } } impl AzaleaWrite for i8 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { (*self as u8).azalea_write(buf) } } impl AzaleaWrite for f32 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { WriteBytesExt::write_f32::(buf, *self) } } impl AzaleaWrite for f64 { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { WriteBytesExt::write_f64::(buf, *self) } } impl AzaleaWrite for Option { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { if let Some(s) = self { true.azalea_write(buf)?; s.azalea_write(buf)?; } else { false.azalea_write(buf)?; }; Ok(()) } } impl AzaleaWriteVar for Option { fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> { if let Some(s) = self { true.azalea_write(buf)?; s.azalea_write_var(buf)?; } else { false.azalea_write(buf)?; }; Ok(()) } } // [T; N] impl AzaleaWrite for [T; N] { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { for i in self { i.azalea_write(buf)?; } Ok(()) } } impl AzaleaWrite for simdnbt::owned::NbtTag { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { let mut data = Vec::new(); self.write(&mut data); buf.write_all(&data) } } impl AzaleaWrite for simdnbt::owned::NbtCompound { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { let mut data = Vec::new(); simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data); buf.write_all(&data) } } impl AzaleaWrite for simdnbt::owned::Nbt { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { let mut data = Vec::new(); self.write_unnamed(&mut data); buf.write_all(&data) } } impl AzaleaWrite for Box where T: AzaleaWrite, { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { T::azalea_write(&**self, buf) } } impl AzaleaWrite for (A, B) { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { self.0.azalea_write(buf)?; self.1.azalea_write(buf) } } impl AzaleaWrite for Arc { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { T::azalea_write(&**self, buf) } }