1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

get rid of Readable & Writable (#21)

This commit is contained in:
mat 2022-09-02 12:11:14 -05:00 committed by GitHub
parent 32458d743f
commit cfb190d00c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 232 additions and 442 deletions

View file

@ -1,3 +1,5 @@
# Azalea Buf
An implementation of Minecraft's FriendlyByteBuf. This is used frequently in the game for serialization and deserialization of data.
Note that there are some minor implementation differences such as using unsigned integers in places where Minecraft uses signed integers. This doesn't cause issues normally, but does technically make usage of azalea-buf detectable if a server really wants to since it won't error in places where vanilla Minecraft would.

View file

@ -145,7 +145,7 @@ fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt
quote! {
impl azalea_buf::McBufWritable for #ident {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
azalea_buf::Writable::write_varint(buf, *self as i32)
azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf)
}
}
}

View file

@ -9,9 +9,9 @@ mod write;
pub use azalea_buf_macros::*;
pub use definitions::*;
pub use read::{read_varint_async, BufReadError, McBufReadable, McBufVarReadable, Readable};
pub use read::{read_varint_async, BufReadError, McBufReadable, McBufVarReadable};
pub use serializable_uuid::*;
pub use write::{McBufVarWritable, McBufWritable, Writable};
pub use write::{McBufVarWritable, McBufWritable};
// const DEFAULT_NBT_QUOTA: u32 = 2097152;
const MAX_STRING_LENGTH: u16 = 32767;
@ -20,173 +20,146 @@ const MAX_STRING_LENGTH: u16 = 32767;
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
use std::{collections::HashMap, io::Cursor};
#[test]
fn test_write_varint() {
let mut buf = Vec::new();
buf.write_varint(0).unwrap();
0.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![0]);
let mut buf = Vec::new();
buf.write_varint(1).unwrap();
1.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![1]);
let mut buf = Vec::new();
buf.write_varint(2).unwrap();
2.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![2]);
let mut buf = Vec::new();
buf.write_varint(127).unwrap();
127.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![127]);
let mut buf = Vec::new();
buf.write_varint(128).unwrap();
128.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![128, 1]);
let mut buf = Vec::new();
buf.write_varint(255).unwrap();
255.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![255, 1]);
let mut buf = Vec::new();
buf.write_varint(25565).unwrap();
25565.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![221, 199, 1]);
let mut buf = Vec::new();
buf.write_varint(2097151).unwrap();
2097151.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![255, 255, 127]);
let mut buf = Vec::new();
buf.write_varint(2147483647).unwrap();
2147483647.var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![255, 255, 255, 255, 7]);
let mut buf = Vec::new();
buf.write_varint(-1).unwrap();
(-1).var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![255, 255, 255, 255, 15]);
let mut buf = Vec::new();
buf.write_varint(-2147483648).unwrap();
(-2147483648).var_write_into(&mut buf).unwrap();
assert_eq!(buf, vec![128, 128, 128, 128, 8]);
}
#[test]
fn test_read_varint() {
let mut buf = Cursor::new(vec![0]);
assert_eq!(buf.read_varint().unwrap(), 0);
assert_eq!(buf.get_varint_size(0), 1);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 0);
let mut buf = Cursor::new(vec![1]);
assert_eq!(buf.read_varint().unwrap(), 1);
assert_eq!(buf.get_varint_size(1), 1);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 1);
let mut buf = Cursor::new(vec![2]);
assert_eq!(buf.read_varint().unwrap(), 2);
assert_eq!(buf.get_varint_size(2), 1);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2);
let mut buf = Cursor::new(vec![127]);
assert_eq!(buf.read_varint().unwrap(), 127);
assert_eq!(buf.get_varint_size(127), 1);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 127);
let mut buf = Cursor::new(vec![128, 1]);
assert_eq!(buf.read_varint().unwrap(), 128);
assert_eq!(buf.get_varint_size(128), 2);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 128);
let mut buf = Cursor::new(vec![255, 1]);
assert_eq!(buf.read_varint().unwrap(), 255);
assert_eq!(buf.get_varint_size(255), 2);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 255);
let mut buf = Cursor::new(vec![221, 199, 1]);
assert_eq!(buf.read_varint().unwrap(), 25565);
assert_eq!(buf.get_varint_size(25565), 3);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 25565);
let mut buf = Cursor::new(vec![255, 255, 127]);
assert_eq!(buf.read_varint().unwrap(), 2097151);
assert_eq!(buf.get_varint_size(2097151), 3);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2097151);
let mut buf = Cursor::new(vec![255, 255, 255, 255, 7]);
assert_eq!(buf.read_varint().unwrap(), 2147483647);
assert_eq!(buf.get_varint_size(2147483647), 5);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2147483647);
let mut buf = Cursor::new(vec![255, 255, 255, 255, 15]);
assert_eq!(buf.read_varint().unwrap(), -1);
assert_eq!(buf.get_varint_size(-1), 5);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), -1);
let mut buf = Cursor::new(vec![128, 128, 128, 128, 8]);
assert_eq!(buf.read_varint().unwrap(), -2147483648);
assert_eq!(buf.get_varint_size(-2147483648), 5);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), -2147483648);
}
#[test]
fn test_read_varint_longer() {
let mut buf = Cursor::new(vec![138, 56, 0, 135, 56, 123]);
assert_eq!(buf.read_varint().unwrap(), 7178);
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 7178);
}
#[test]
fn test_list() {
let original_vec = vec!["a".to_string(), "bc".to_string(), "def".to_string()];
let mut buf = Vec::new();
buf.write_list(&vec!["a", "bc", "def"], |buf, s| buf.write_utf(s))
.unwrap();
original_vec.write_into(&mut buf).unwrap();
dbg!(&buf);
// there's no read_list because idk how to do it in rust
let mut buf = Cursor::new(buf);
let mut result = Vec::new();
let length = buf.read_varint().unwrap();
for _ in 0..length {
result.push(buf.read_utf().unwrap());
}
assert_eq!(result, vec!["a", "bc", "def"]);
let result = Vec::<String>::read_from(&mut buf).unwrap();
assert_eq!(result, original_vec);
}
#[test]
fn test_int_id_list() {
let mut buf = Vec::new();
buf.write_list(&vec![1, 2, 3], |buf, i| buf.write_varint(*i))
.unwrap();
vec![1, 2, 3].var_write_into(&mut buf).unwrap();
let mut buf = Cursor::new(buf);
let result = buf.read_int_id_list().unwrap();
let result = Vec::<i32>::var_read_from(&mut buf).unwrap();
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_map() {
let original_map = HashMap::from([
("a".to_string(), 1),
("bc".to_string(), 23),
("def".to_string(), 456),
]);
let mut buf = Vec::new();
buf.write_map(
vec![("a", 1), ("bc", 23), ("def", 456)],
Vec::write_utf,
Vec::write_varint,
)
.unwrap();
original_map.var_write_into(&mut buf).unwrap();
let mut buf = Cursor::new(buf);
let mut result = Vec::new();
let length = buf.read_varint().unwrap();
for _ in 0..length {
result.push((buf.read_utf().unwrap(), buf.read_varint().unwrap()));
}
let result = HashMap::<String, i32>::var_read_from(&mut buf).unwrap();
assert_eq!(
result,
vec![
("a".to_string(), 1),
("bc".to_string(), 23),
("def".to_string(), 456)
]
);
assert_eq!(result, original_map);
}
#[test]
fn test_long() {
let mut buf = Vec::new();
buf.write_long(123456).unwrap();
123456u64.write_into(&mut buf).unwrap();
let mut buf = Cursor::new(buf);
assert_eq!(buf.read_long().unwrap(), 123456);
assert_eq!(u64::read_from(&mut buf).unwrap(), 123456);
}
}

View file

@ -12,14 +12,10 @@ pub enum BufReadError {
InvalidVarLong,
#[error("Error reading bytes")]
CouldNotReadBytes,
#[error("The received encoded string buffer length is less than zero! Weird string!")]
StringLengthLessThanZero,
#[error("The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})")]
StringLengthTooLong { length: i32, max_length: u32 },
StringLengthTooLong { length: u32, max_length: u32 },
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("Boolean value is not 0 or 1")]
InvalidBoolean,
#[error("Invalid UTF-8")]
InvalidUtf8,
#[error("Unexpected enum variant {id}")]
@ -33,106 +29,9 @@ pub enum BufReadError {
Deserialization(#[from] serde_json::Error),
}
// TODO: get rid of Readable and use McBufReadable everywhere
pub trait Readable {
fn read_int_id_list(&mut self) -> Result<Vec<i32>, BufReadError>;
fn read_varint(&mut self) -> Result<i32, BufReadError>;
fn get_varint_size(&mut self, value: i32) -> u8;
fn get_varlong_size(&mut self, value: i32) -> u8;
fn read_byte_array(&mut self) -> Result<Vec<u8>, BufReadError>;
fn read_bytes_with_len(&mut self, n: usize) -> Result<Vec<u8>, BufReadError>;
fn read_bytes(&mut self) -> Result<Vec<u8>, BufReadError>;
fn read_utf(&mut self) -> Result<String, BufReadError>;
fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, BufReadError>;
fn read_byte(&mut self) -> Result<u8, BufReadError>;
fn read_int(&mut self) -> Result<i32, BufReadError>;
fn read_boolean(&mut self) -> Result<bool, BufReadError>;
fn read_long(&mut self) -> Result<i64, BufReadError>;
fn read_short(&mut self) -> Result<i16, BufReadError>;
fn read_float(&mut self) -> Result<f32, BufReadError>;
fn read_double(&mut self) -> Result<f64, BufReadError>;
}
impl<R> Readable for R
where
R: Read,
{
fn read_int_id_list(&mut self) -> Result<Vec<i32>, BufReadError> {
let len = self.read_varint()?;
let mut list = Vec::with_capacity(len as usize);
for _ in 0..len {
list.push(self.read_varint()?);
}
Ok(list)
}
// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
/// Read a single varint from the reader and return the value
fn read_varint(&mut self) -> Result<i32, BufReadError> {
let mut buffer = [0];
let mut ans = 0;
for i in 0..5 {
self.read_exact(&mut buffer)
.map_err(|_| BufReadError::InvalidVarInt)?;
ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i);
if buffer[0] & 0b1000_0000 == 0 {
break;
}
}
Ok(ans)
}
fn get_varint_size(&mut self, value: i32) -> u8 {
for i in 1..5 {
if (value & -1 << (i * 7)) != 0 {
continue;
}
return i;
}
5
}
fn get_varlong_size(&mut self, value: i32) -> u8 {
for i in 1..10 {
if (value & -1 << (i * 7)) != 0 {
continue;
}
return i;
}
10
}
fn read_byte_array(&mut self) -> Result<Vec<u8>, BufReadError> {
let length = self.read_varint()? as usize;
self.read_bytes_with_len(length)
}
fn read_bytes_with_len(&mut self, n: usize) -> Result<Vec<u8>, BufReadError> {
let mut buffer = vec![0; n];
self.read_exact(&mut buffer)
.map_err(|_| BufReadError::CouldNotReadBytes)?;
Ok(buffer)
}
fn read_bytes(&mut self) -> Result<Vec<u8>, BufReadError> {
// read to end of the buffer
let mut bytes = vec![];
self.read_to_end(&mut bytes)
.map_err(|_| BufReadError::CouldNotReadBytes)?;
Ok(bytes)
}
fn read_utf(&mut self) -> Result<String, BufReadError> {
self.read_utf_with_len(MAX_STRING_LENGTH.into())
}
fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, BufReadError> {
let length = self.read_varint()?;
fn read_utf_with_len(buf: &mut impl Read, max_length: u32) -> Result<String, BufReadError> {
let length = u32::var_read_from(buf)?;
// i don't know why it's multiplied by 4 but it's like that in mojang's code so
if length < 0 {
return Err(BufReadError::StringLengthLessThanZero);
}
if length as u32 > max_length * 4 {
return Err(BufReadError::StringLengthTooLong {
length,
@ -143,7 +42,7 @@ where
// this is probably quite inefficient, idk how to do it better
let mut string = String::new();
let mut buffer = vec![0; length as usize];
self.read_exact(&mut buffer)
buf.read_exact(&mut buffer)
.map_err(|_| BufReadError::InvalidUtf8)?;
string.push_str(std::str::from_utf8(&buffer).unwrap());
if string.len() > length as usize {
@ -151,40 +50,6 @@ where
}
Ok(string)
}
/// Read a single byte from the reader
fn read_byte(&mut self) -> Result<u8, BufReadError> {
Ok(self.read_u8()?)
}
fn read_int(&mut self) -> Result<i32, BufReadError> {
Ok(self.read_i32::<BE>()?)
}
fn read_boolean(&mut self) -> Result<bool, BufReadError> {
match self.read_byte()? {
0 => Ok(false),
1 => Ok(true),
_ => Err(BufReadError::InvalidBoolean),
}
}
fn read_long(&mut self) -> Result<i64, BufReadError> {
Ok(self.read_i64::<BE>()?)
}
fn read_short(&mut self) -> Result<i16, BufReadError> {
Ok(self.read_i16::<BE>()?)
}
fn read_float(&mut self) -> Result<f32, BufReadError> {
Ok(self.read_f32::<BE>()?)
}
fn read_double(&mut self) -> Result<f64, BufReadError> {
Ok(self.read_f64::<BE>()?)
}
}
// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
@ -223,13 +88,25 @@ where
impl McBufReadable for i32 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
Readable::read_int(buf)
Ok(buf.read_i32::<BE>()?)
}
}
impl McBufVarReadable for i32 {
// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
/// Read a single varint from the reader and return the value
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_varint()
let mut buffer = [0];
let mut ans = 0;
for i in 0..5 {
buf.read_exact(&mut buffer)
.map_err(|_| BufReadError::InvalidVarInt)?;
ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i);
if buffer[0] & 0b1000_0000 == 0 {
break;
}
}
Ok(ans)
}
}
@ -257,13 +134,17 @@ impl McBufVarReadable for u64 {
impl McBufReadable for UnsizedByteArray {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
Ok(buf.read_bytes()?.into())
// read to end of the buffer
let mut bytes = vec![];
buf.read_to_end(&mut bytes)
.map_err(|_| BufReadError::CouldNotReadBytes)?;
Ok(bytes.into())
}
}
impl<T: McBufReadable + Send> McBufReadable for Vec<T> {
default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let length = buf.read_varint()? as usize;
let length = u32::var_read_from(buf)? as usize;
let mut contents = Vec::with_capacity(length);
for _ in 0..length {
contents.push(T::read_from(buf)?);
@ -274,7 +155,7 @@ impl<T: McBufReadable + Send> McBufReadable for Vec<T> {
impl<K: McBufReadable + Send + Eq + Hash, V: McBufReadable + Send> McBufReadable for HashMap<K, V> {
default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let length = buf.read_varint()? as usize;
let length = i32::var_read_from(buf)? as usize;
let mut contents = HashMap::with_capacity(length);
for _ in 0..length {
contents.insert(K::read_from(buf)?, V::read_from(buf)?);
@ -287,7 +168,7 @@ impl<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarRe
for HashMap<K, V>
{
default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let length = buf.read_varint()? as usize;
let length = i32::var_read_from(buf)? as usize;
let mut contents = HashMap::with_capacity(length);
for _ in 0..length {
contents.insert(K::read_from(buf)?, V::var_read_from(buf)?);
@ -298,49 +179,53 @@ impl<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarRe
impl McBufReadable for Vec<u8> {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_byte_array()
let length = i32::var_read_from(buf)? as usize;
let mut buffer = vec![0; length];
buf.read_exact(&mut buffer)
.map_err(|_| BufReadError::CouldNotReadBytes)?;
Ok(buffer)
}
}
impl McBufReadable for String {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_utf()
read_utf_with_len(buf, MAX_STRING_LENGTH.into())
}
}
impl McBufReadable for u32 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
Readable::read_int(buf).map(|i| i as u32)
Ok(i32::read_from(buf)? as u32)
}
}
impl McBufVarReadable for u32 {
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_varint().map(|i| i as u32)
Ok(i32::var_read_from(buf)? as u32)
}
}
impl McBufReadable for u16 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_short().map(|i| i as u16)
i32::read_from(buf).map(|i| i as u16)
}
}
impl McBufReadable for i16 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_short()
Ok(buf.read_i16::<BE>()?)
}
}
impl McBufVarReadable for u16 {
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_varint().map(|i| i as u16)
Ok(i32::var_read_from(buf)? as u16)
}
}
impl<T: McBufVarReadable> McBufVarReadable for Vec<T> {
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let length = buf.read_varint()? as usize;
let length = i32::var_read_from(buf)? as usize;
let mut contents = Vec::with_capacity(length);
for _ in 0..length {
contents.push(T::var_read_from(buf)?);
@ -351,7 +236,7 @@ impl<T: McBufVarReadable> McBufVarReadable for Vec<T> {
impl McBufReadable for i64 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_long()
Ok(buf.read_i64::<BE>()?)
}
}
@ -363,37 +248,37 @@ impl McBufReadable for u64 {
impl McBufReadable for bool {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_boolean()
Ok(u8::read_from(buf)? != 0)
}
}
impl McBufReadable for u8 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_byte()
Ok(buf.read_u8()?)
}
}
impl McBufReadable for i8 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_byte().map(|i| i as i8)
u8::read_from(buf).map(|i| i as i8)
}
}
impl McBufReadable for f32 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_float()
Ok(buf.read_f32::<BE>()?)
}
}
impl McBufReadable for f64 {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_double()
Ok(buf.read_f64::<BE>()?)
}
}
impl<T: McBufReadable> McBufReadable for Option<T> {
default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let present = buf.read_boolean()?;
let present = bool::read_from(buf)?;
Ok(if present {
Some(T::read_from(buf)?)
} else {
@ -404,7 +289,7 @@ impl<T: McBufReadable> McBufReadable for Option<T> {
impl<T: McBufVarReadable> McBufVarReadable for Option<T> {
default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let present = buf.read_boolean()?;
let present = bool::read_from(buf)?;
Ok(if present {
Some(T::var_read_from(buf)?)
} else {

View file

@ -1,4 +1,4 @@
use crate::{read::BufReadError, McBufReadable, McBufWritable, Readable};
use crate::{read::BufReadError, McBufReadable, McBufWritable};
use std::io::{Read, Write};
use uuid::Uuid;
@ -35,10 +35,10 @@ impl SerializableUuid for Uuid {
impl McBufReadable for Uuid {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
Ok(Uuid::from_int_array([
Readable::read_int(buf)? as u32,
Readable::read_int(buf)? as u32,
Readable::read_int(buf)? as u32,
Readable::read_int(buf)? as u32,
u32::read_from(buf)?,
u32::read_from(buf)?,
u32::read_from(buf)?,
u32::read_from(buf)?,
]))
}
}
@ -54,7 +54,6 @@ impl McBufWritable for Uuid {
}
}
// TODO: add a test for Uuid in McBuf
#[cfg(test)]
mod tests {
use super::*;

View file

@ -2,68 +2,11 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH};
use byteorder::{BigEndian, WriteBytesExt};
use std::{collections::HashMap, io::Write};
// TODO: get rid of Writable and use McBufWritable everywhere
pub trait Writable: Write {
fn write_list<F, T>(&mut self, list: &[T], writer: F) -> Result<(), std::io::Error>
where
F: FnOnce(&mut Self, &T) -> Result<(), std::io::Error> + Copy,
{
self.write_varint(list.len() as i32)?;
for item in list {
writer(self, item)?;
}
Ok(())
}
fn write_int_id_list(&mut self, list: &[i32]) -> Result<(), std::io::Error> {
self.write_list(list, |buf, n| buf.write_varint(*n))
}
fn write_map<KF, VF, KT, VT>(
&mut self,
map: Vec<(KT, VT)>,
key_writer: KF,
value_writer: VF,
) -> Result<(), std::io::Error>
where
KF: Fn(&mut Self, KT) -> Result<(), std::io::Error> + Copy,
VF: Fn(&mut Self, VT) -> Result<(), std::io::Error> + Copy,
{
self.write_varint(map.len() as i32)?;
for (key, value) in map {
key_writer(self, key)?;
value_writer(self, value)?;
}
Ok(())
}
fn write_byte(&mut self, n: u8) -> Result<(), std::io::Error> {
WriteBytesExt::write_u8(self, n)
}
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
self.write_all(bytes)?;
Ok(())
}
fn write_varint(&mut self, mut value: i32) -> Result<(), std::io::Error> {
let mut buffer = [0];
if value == 0 {
self.write_all(&buffer).unwrap();
}
while value != 0 {
buffer[0] = (value & 0b0111_1111) as u8;
value = (value >> 7) & (i32::max_value() >> 6);
if value != 0 {
buffer[0] |= 0b1000_0000;
}
self.write_all(&buffer)?;
}
Ok(())
}
fn write_utf_with_len(&mut self, string: &str, len: usize) -> Result<(), std::io::Error> {
fn write_utf_with_len(
buf: &mut impl Write,
string: &str,
len: usize,
) -> Result<(), std::io::Error> {
if string.len() > len {
panic!(
"String too big (was {} bytes encoded, max {})",
@ -71,46 +14,10 @@ pub trait Writable: Write {
len
);
}
self.write_varint(string.len() as i32)?;
self.write_bytes(string.as_bytes())
}
fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error> {
self.write_utf_with_len(string, MAX_STRING_LENGTH.into())
}
fn write_short(&mut self, n: i16) -> Result<(), std::io::Error> {
WriteBytesExt::write_i16::<BigEndian>(self, n)
}
fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
self.write_varint(bytes.len() as i32)?;
self.write_bytes(bytes)
}
fn write_int(&mut self, n: i32) -> Result<(), std::io::Error> {
WriteBytesExt::write_i32::<BigEndian>(self, n)
}
fn write_boolean(&mut self, b: bool) -> Result<(), std::io::Error> {
self.write_byte(if b { 1 } else { 0 })
}
fn write_long(&mut self, n: i64) -> Result<(), std::io::Error> {
WriteBytesExt::write_i64::<BigEndian>(self, n)
}
fn write_float(&mut self, n: f32) -> Result<(), std::io::Error> {
WriteBytesExt::write_f32::<BigEndian>(self, n)
}
fn write_double(&mut self, n: f64) -> Result<(), std::io::Error> {
WriteBytesExt::write_f64::<BigEndian>(self, n)
}
string.as_bytes().to_vec().write_into(buf)?;
Ok(())
}
impl<W: Write + ?Sized> Writable for W {}
pub trait McBufWritable {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
}
@ -121,25 +28,48 @@ pub trait McBufVarWritable {
impl McBufWritable for i32 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
Writable::write_int(buf, *self)
WriteBytesExt::write_i32::<BigEndian>(buf, *self)
}
}
impl McBufVarWritable for i32 {
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_varint(*self)
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_value() >> 6);
if value != 0 {
buffer[0] |= 0b1000_0000;
}
buf.write_all(&buffer)?;
}
Ok(())
}
}
impl McBufWritable for UnsizedByteArray {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_bytes(self)
buf.write_all(self)
}
}
impl<T: McBufWritable> McBufWritable for Vec<T> {
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_list(self, |buf, i| T::write_into(i, buf))
self[..].write_into(buf)
}
}
impl<T: McBufWritable> McBufWritable for [T] {
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
(self.len() as u32).var_write_into(buf)?;
for item in self {
T::write_into(item, buf)?;
}
Ok(())
}
}
@ -169,13 +99,14 @@ impl<K: McBufWritable, V: McBufVarWritable> McBufVarWritable for HashMap<K, V> {
impl McBufWritable for Vec<u8> {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte_array(self)
(self.len() as u32).var_write_into(buf)?;
buf.write_all(self)
}
}
impl McBufWritable for String {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_utf(self)
write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
}
}
@ -239,19 +170,19 @@ impl<T: McBufVarWritable> McBufVarWritable for Vec<T> {
impl McBufWritable for u8 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte(*self)
WriteBytesExt::write_u8(buf, *self)
}
}
impl McBufWritable for i16 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
Writable::write_short(buf, *self)
WriteBytesExt::write_i16::<BigEndian>(buf, *self)
}
}
impl McBufWritable for i64 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
Writable::write_long(buf, *self)
WriteBytesExt::write_i64::<BigEndian>(buf, *self)
}
}
@ -263,35 +194,36 @@ impl McBufWritable for u64 {
impl McBufWritable for bool {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_boolean(*self)
let byte: u8 = if *self { 1 } else { 0 };
byte.write_into(buf)
}
}
impl McBufWritable for i8 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte(*self as u8)
(*self as u8).write_into(buf)
}
}
impl McBufWritable for f32 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_float(*self)
WriteBytesExt::write_f32::<BigEndian>(buf, *self)
}
}
impl McBufWritable for f64 {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_double(*self)
WriteBytesExt::write_f64::<BigEndian>(buf, *self)
}
}
impl<T: McBufWritable> McBufWritable for Option<T> {
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
if let Some(s) = self {
buf.write_boolean(true)?;
true.write_into(buf)?;
s.write_into(buf)?;
} else {
buf.write_boolean(false)?;
false.write_into(buf)?;
};
Ok(())
}
@ -300,10 +232,10 @@ impl<T: McBufWritable> McBufWritable for Option<T> {
impl<T: McBufVarWritable> McBufVarWritable for Option<T> {
default fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
if let Some(s) = self {
buf.write_boolean(true)?;
true.write_into(buf)?;
s.var_write_into(buf)?;
} else {
buf.write_boolean(false)?;
false.write_into(buf)?;
};
Ok(())
}

View file

@ -282,7 +282,7 @@ impl McBufWritable for Component {
// where
// R: AsyncRead + std::marker::Unpin + std::marker::Send,
// {
// let string = buf.read_utf().await?;
// let string = String::read_from(buf).await?;
// let json: serde_json::Value = serde_json::from_str(string.as_str())
// .map_err(|e| "Component isn't valid JSON".to_string())?;
// let component = Component::deserialize(json).map_err(|e| e.to_string())?;

View file

@ -146,7 +146,7 @@ impl MovableEntity for EntityMut<'_> {
// TODO: minecraft checks for a "minor" horizontal collision here
let block_pos_below = { self.on_pos_legacy() };
let _block_pos_below = self.on_pos_legacy();
// let _block_state_below = self
// .dimension
// .get_block_state(&block_pos_below)

View file

@ -1,7 +1,7 @@
use azalea_buf::BufReadError;
use azalea_buf::McBuf;
use azalea_buf::McBufVarReadable;
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
use azalea_buf::{McBufReadable, McBufWritable};
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
use std::{
@ -26,7 +26,7 @@ pub struct BrigadierNumber<T> {
}
impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let flags = buf.read_byte()?;
let flags = u8::read_from(buf)?;
let min = if flags & 0x01 != 0 {
Some(T::read_from(buf)?)
} else {
@ -42,14 +42,14 @@ impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
}
impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
let mut flags = 0;
let mut flags: u8 = 0;
if self.min.is_some() {
flags |= 0x01;
}
if self.max.is_some() {
flags |= 0x02;
}
buf.write_byte(flags)?;
flags.write_into(buf)?;
if let Some(min) = &self.min {
min.write_into(buf)?;
}
@ -135,7 +135,7 @@ impl McBufReadable for BrigadierParser {
4 => Ok(BrigadierParser::Long(BrigadierNumber::read_from(buf)?)),
5 => Ok(BrigadierParser::String(BrigadierString::read_from(buf)?)),
6 => {
let flags = buf.read_byte()?;
let flags = u8::read_from(buf)?;
Ok(BrigadierParser::Entity {
single: flags & 0x01 != 0,
players_only: flags & 0x02 != 0,
@ -164,7 +164,7 @@ impl McBufReadable for BrigadierParser {
27 => Ok(BrigadierParser::Rotation),
28 => Ok(BrigadierParser::ScoreboardSlot),
29 => {
let flags = buf.read_byte()?;
let flags = u8::read_from(buf)?;
Ok(BrigadierParser::ScoreHolder {
allows_multiple: flags & 0x01 != 0,
})
@ -213,12 +213,16 @@ impl McBufReadable for BrigadierNodeStub {
let has_redirect = flags & 0x08 != 0;
let has_suggestions_type = flags & 0x10 != 0;
let _children = buf.read_int_id_list()?;
let _redirect_node = if has_redirect { buf.read_varint()? } else { 0 };
let _children = Vec::<i32>::var_read_from(buf)?;
let _redirect_node = if has_redirect {
i32::var_read_from(buf)?
} else {
0
};
// argument node
if node_type == 2 {
let _name = buf.read_utf()?;
let _name = String::read_from(buf)?;
let _parser = BrigadierParser::read_from(buf)?;
let _suggestions_type = if has_suggestions_type {
Some(ResourceLocation::read_from(buf)?)
@ -229,7 +233,7 @@ impl McBufReadable for BrigadierNodeStub {
}
// literal node
if node_type == 1 {
let _name = buf.read_utf()?;
let _name = String::read_from(buf)?;
return Ok(BrigadierNodeStub {});
}
Ok(BrigadierNodeStub {})

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable, Readable};
use azalea_buf::{McBufReadable, McBufWritable};
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
@ -21,7 +21,7 @@ pub struct PlayerAbilitiesFlags {
impl McBufReadable for PlayerAbilitiesFlags {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let byte = buf.read_byte()?;
let byte = u8::read_from(buf)?;
Ok(PlayerAbilitiesFlags {
invulnerable: byte & 1 != 0,
flying: byte & 2 != 0,

View file

@ -1,6 +1,6 @@
use crate::packets::login::serverbound_hello_packet::ProfilePublicKeyData;
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
use azalea_buf::{McBufReadable, McBufWritable};
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
@ -66,7 +66,7 @@ pub struct RemovePlayer {
impl McBufReadable for Action {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let id = buf.read_byte()?;
let id = u8::read_from(buf)?;
Ok(match id {
0 => Action::AddPlayer(Vec::<AddPlayer>::read_from(buf)?),
1 => Action::UpdateGameMode(Vec::<UpdateGameMode>::read_from(buf)?),
@ -79,13 +79,14 @@ impl McBufReadable for Action {
}
impl McBufWritable for Action {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte(match self {
let id: u8 = match self {
Action::AddPlayer(_) => 0,
Action::UpdateGameMode(_) => 1,
Action::UpdateLatency(_) => 2,
Action::UpdateDisplayName(_) => 3,
Action::RemovePlayer(_) => 4,
})?;
};
id.write_into(buf)?;
match self {
Action::AddPlayer(players) => players.write_into(buf)?,
Action::UpdateGameMode(players) => players.write_into(buf)?,

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable, Readable};
use azalea_buf::{McBufReadable, McBufWritable};
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
@ -29,7 +29,7 @@ pub struct RelativeArguments {
impl McBufReadable for RelativeArguments {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let byte = buf.read_byte()?;
let byte = u8::read_from(buf)?;
Ok(RelativeArguments {
x: byte & 0b1 != 0,
y: byte & 0b10 != 0,

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
use azalea_buf::{McBufReadable, McBufWritable};
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
@ -35,7 +35,7 @@ enum Operation {
impl McBufReadable for Operation {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
match buf.read_byte()? {
match u8::read_from(buf)? {
0 => Ok(Operation::Addition),
1 => Ok(Operation::MultiplyBase),
2 => Ok(Operation::MultiplyTotal),
@ -46,7 +46,7 @@ impl McBufReadable for Operation {
impl McBufWritable for Operation {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte(*self as u8)?;
(*self as u8).write_into(buf)?;
Ok(())
}
}

View file

@ -1,10 +1,9 @@
use std::io::{Read, Write};
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
};
use azalea_core::{ResourceLocation, Slot};
use packet_macros::ClientboundGamePacket;
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
use std::io::{Read, Write};
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundUpdateRecipesPacket {
@ -37,9 +36,9 @@ pub struct ShapedRecipe {
impl McBufWritable for ShapedRecipe {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_varint(self.width.try_into().unwrap())?;
buf.write_varint(self.height.try_into().unwrap())?;
buf.write_utf(&self.group)?;
(self.width as u32).var_write_into(buf)?;
(self.height as u32).var_write_into(buf)?;
self.group.write_into(buf)?;
for ingredient in &self.ingredients {
ingredient.write_into(buf)?;
}
@ -50,9 +49,9 @@ impl McBufWritable for ShapedRecipe {
}
impl McBufReadable for ShapedRecipe {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let width = buf.read_varint()?.try_into().unwrap();
let height = buf.read_varint()?.try_into().unwrap();
let group = buf.read_utf()?;
let width = u32::var_read_from(buf)?.try_into().unwrap();
let height = u32::var_read_from(buf)?.try_into().unwrap();
let group = String::read_from(buf)?;
let mut ingredients = Vec::with_capacity(width * height);
for _ in 0..width * height {
ingredients.push(Ingredient::read_from(buf)?);

View file

@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
use azalea_buf::{BufReadError, McBuf, McBufVarReadable, McBufVarWritable};
use azalea_buf::{McBufReadable, McBufWritable};
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
use std::ops::Deref;
@ -24,11 +24,11 @@ pub struct TagMap(HashMap<ResourceLocation, Vec<Tags>>);
impl McBufReadable for TagMap {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let length = buf.read_varint()? as usize;
let length = u32::var_read_from(buf)? as usize;
let mut data = HashMap::with_capacity(length);
for _ in 0..length {
let tag_type = ResourceLocation::read_from(buf)?;
let tags_count = buf.read_varint()? as usize;
let tags_count = i32::var_read_from(buf)? as usize;
let mut tags_vec = Vec::with_capacity(tags_count);
for _ in 0..tags_count {
let tags = Tags::read_from(buf)?;
@ -42,7 +42,7 @@ impl McBufReadable for TagMap {
impl McBufWritable for TagMap {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_varint(self.len() as i32)?;
(self.len() as u32).write_into(buf)?;
for (k, v) in &self.0 {
k.write_into(buf)?;
v.write_into(buf)?;
@ -53,7 +53,7 @@ impl McBufWritable for TagMap {
impl McBufReadable for Tags {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let name = ResourceLocation::read_from(buf)?;
let elements = buf.read_int_id_list()?;
let elements = Vec::<i32>::var_read_from(buf)?;
Ok(Tags { name, elements })
}
}
@ -61,7 +61,7 @@ impl McBufReadable for Tags {
impl McBufWritable for Tags {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
self.name.write_into(buf)?;
buf.write_int_id_list(&self.elements)?;
self.elements.var_write_into(buf)?;
Ok(())
}
}

View file

@ -1,12 +1,10 @@
use super::ClientboundLoginPacket;
use azalea_buf::{BufReadError, McBufVarReadable, McBufVarWritable};
use std::{
hash::Hash,
io::{Read, Write},
};
use azalea_buf::{BufReadError, Readable, Writable};
use super::ClientboundLoginPacket;
#[derive(Hash, Clone, Debug)]
pub struct ClientboundLoginCompressionPacket {
pub compression_threshold: i32,
@ -18,12 +16,12 @@ impl ClientboundLoginCompressionPacket {
}
pub fn write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_varint(self.compression_threshold).unwrap();
self.compression_threshold.var_write_into(buf)?;
Ok(())
}
pub fn read(buf: &mut impl Read) -> Result<ClientboundLoginPacket, BufReadError> {
let compression_threshold = buf.read_varint()?;
let compression_threshold = i32::var_read_from(buf)?;
Ok(ClientboundLoginCompressionPacket {
compression_threshold,

View file

@ -4,7 +4,7 @@ pub mod login;
pub mod status;
use crate::read::ReadPacketError;
use azalea_buf::{BufReadError, McBufWritable, Readable, Writable};
use azalea_buf::{BufReadError, McBufVarReadable, McBufVarWritable, McBufWritable};
use std::io::{Read, Write};
pub const PROTOCOL_VERSION: u32 = 760;
@ -44,13 +44,13 @@ where
impl azalea_buf::McBufReadable for ConnectionProtocol {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let id = buf.read_varint()?;
let id = i32::var_read_from(buf)?;
ConnectionProtocol::from_i32(id).ok_or(BufReadError::UnexpectedEnumVariant { id })
}
}
impl McBufWritable for ConnectionProtocol {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_varint(*self as i32)
(*self as i32).var_write_into(buf)
}
}

View file

@ -1,5 +1,5 @@
use super::ClientboundStatusPacket;
use azalea_buf::{BufReadError, Readable};
use azalea_buf::{BufReadError, McBufReadable};
use azalea_chat::component::Component;
use serde::Deserialize;
use serde_json::Value;
@ -44,7 +44,7 @@ impl ClientboundStatusResponsePacket {
}
pub fn read(buf: &mut impl Read) -> Result<ClientboundStatusPacket, BufReadError> {
let status_string = buf.read_utf()?;
let status_string = String::read_from(buf)?;
let status_json: Value = serde_json::from_str(status_string.as_str())?;
let packet = ClientboundStatusResponsePacket::deserialize(status_json)?.get();

View file

@ -1,6 +1,6 @@
use crate::packets::ProtocolPacket;
use azalea_buf::McBufVarReadable;
use azalea_buf::{read_varint_async, BufReadError, Readable};
use azalea_buf::{read_varint_async, BufReadError};
use azalea_crypto::Aes128CfbDec;
use flate2::read::ZlibDecoder;
use std::{
@ -78,9 +78,8 @@ where
fn packet_decoder<P: ProtocolPacket>(stream: &mut impl Read) -> Result<P, ReadPacketError> {
// Packet ID
let packet_id = stream
.read_varint()
.map_err(|e| ReadPacketError::ReadPacketId { source: e })?;
let packet_id =
u32::var_read_from(stream).map_err(|e| ReadPacketError::ReadPacketId { source: e })?;
P::read(packet_id.try_into().unwrap(), stream)
}

View file

@ -1,6 +1,6 @@
use crate::{packets::ProtocolPacket, read::MAXIMUM_UNCOMPRESSED_LENGTH};
use async_compression::tokio::bufread::ZlibEncoder;
use azalea_buf::Writable;
use azalea_buf::McBufVarWritable;
use azalea_crypto::Aes128CfbEnc;
use std::fmt::Debug;
use thiserror::Error;
@ -8,7 +8,7 @@ use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
fn frame_prepender(data: &mut Vec<u8>) -> Result<Vec<u8>, std::io::Error> {
let mut buf = Vec::new();
buf.write_varint(data.len() as i32)?;
(data.len() as u32).var_write_into(&mut buf)?;
buf.append(data);
Ok(buf)
}
@ -29,7 +29,7 @@ fn packet_encoder<P: ProtocolPacket + std::fmt::Debug>(
packet: &P,
) -> Result<Vec<u8>, PacketEncodeError> {
let mut buf = Vec::new();
buf.write_varint(packet.id() as i32)?;
(packet.id() as u32).var_write_into(&mut buf)?;
packet.write(&mut buf)?;
if buf.len() > MAXIMUM_UNCOMPRESSED_LENGTH as usize {
return Err(PacketEncodeError::TooBig {
@ -55,7 +55,7 @@ async fn compression_encoder(
// if it's less than the compression threshold, don't compress
if n < compression_threshold as usize {
let mut buf = Vec::new();
buf.write_varint(0)?;
0.var_write_into(&mut buf)?;
buf.write_all(data).await?;
Ok(buf)
} else {

View file

@ -1,6 +1,4 @@
use azalea_buf::{
BufReadError, McBufReadable, McBufVarReadable, McBufWritable, Readable, Writable,
};
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufWritable};
use std::io::{Read, Write};
use crate::BitStorage;
@ -38,7 +36,7 @@ impl PalettedContainer {
buf: &mut impl Read,
container_type: &'static PalettedContainerType,
) -> Result<Self, BufReadError> {
let bits_per_entry = buf.read_byte()?;
let bits_per_entry = u8::read_from(buf)?;
let palette_type = PaletteType::from_bits_and_type(bits_per_entry, container_type);
let palette = palette_type.read(buf)?;
let size = container_type.size();
@ -181,7 +179,7 @@ impl PalettedContainer {
impl McBufWritable for PalettedContainer {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte(self.bits_per_entry)?;
self.bits_per_entry.write_into(buf)?;
self.palette.write_into(buf)?;
self.storage.data.write_into(buf)?;
Ok(())