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:
parent
32458d743f
commit
cfb190d00c
21 changed files with 232 additions and 442 deletions
|
@ -1,3 +1,5 @@
|
||||||
# Azalea Buf
|
# Azalea Buf
|
||||||
|
|
||||||
An implementation of Minecraft's FriendlyByteBuf. This is used frequently in the game for serialization and deserialization of data.
|
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.
|
||||||
|
|
|
@ -145,7 +145,7 @@ fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt
|
||||||
quote! {
|
quote! {
|
||||||
impl azalea_buf::McBufWritable for #ident {
|
impl azalea_buf::McBufWritable for #ident {
|
||||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@ mod write;
|
||||||
|
|
||||||
pub use azalea_buf_macros::*;
|
pub use azalea_buf_macros::*;
|
||||||
pub use definitions::*;
|
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 serializable_uuid::*;
|
||||||
pub use write::{McBufVarWritable, McBufWritable, Writable};
|
pub use write::{McBufVarWritable, McBufWritable};
|
||||||
|
|
||||||
// const DEFAULT_NBT_QUOTA: u32 = 2097152;
|
// const DEFAULT_NBT_QUOTA: u32 = 2097152;
|
||||||
const MAX_STRING_LENGTH: u16 = 32767;
|
const MAX_STRING_LENGTH: u16 = 32767;
|
||||||
|
@ -20,173 +20,146 @@ const MAX_STRING_LENGTH: u16 = 32767;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::io::Cursor;
|
use std::{collections::HashMap, io::Cursor};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_varint() {
|
fn test_write_varint() {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(0).unwrap();
|
0.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![0]);
|
assert_eq!(buf, vec![0]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(1).unwrap();
|
1.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![1]);
|
assert_eq!(buf, vec![1]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(2).unwrap();
|
2.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![2]);
|
assert_eq!(buf, vec![2]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(127).unwrap();
|
127.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![127]);
|
assert_eq!(buf, vec![127]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(128).unwrap();
|
128.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![128, 1]);
|
assert_eq!(buf, vec![128, 1]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(255).unwrap();
|
255.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![255, 1]);
|
assert_eq!(buf, vec![255, 1]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(25565).unwrap();
|
25565.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![221, 199, 1]);
|
assert_eq!(buf, vec![221, 199, 1]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(2097151).unwrap();
|
2097151.var_write_into(&mut buf).unwrap();
|
||||||
assert_eq!(buf, vec![255, 255, 127]);
|
assert_eq!(buf, vec![255, 255, 127]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
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]);
|
assert_eq!(buf, vec![255, 255, 255, 255, 7]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
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]);
|
assert_eq!(buf, vec![255, 255, 255, 255, 15]);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
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]);
|
assert_eq!(buf, vec![128, 128, 128, 128, 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read_varint() {
|
fn test_read_varint() {
|
||||||
let mut buf = Cursor::new(vec![0]);
|
let mut buf = Cursor::new(vec![0]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 0);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 0);
|
||||||
assert_eq!(buf.get_varint_size(0), 1);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![1]);
|
let mut buf = Cursor::new(vec![1]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 1);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 1);
|
||||||
assert_eq!(buf.get_varint_size(1), 1);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![2]);
|
let mut buf = Cursor::new(vec![2]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 2);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2);
|
||||||
assert_eq!(buf.get_varint_size(2), 1);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![127]);
|
let mut buf = Cursor::new(vec![127]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 127);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 127);
|
||||||
assert_eq!(buf.get_varint_size(127), 1);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![128, 1]);
|
let mut buf = Cursor::new(vec![128, 1]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 128);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 128);
|
||||||
assert_eq!(buf.get_varint_size(128), 2);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![255, 1]);
|
let mut buf = Cursor::new(vec![255, 1]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 255);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 255);
|
||||||
assert_eq!(buf.get_varint_size(255), 2);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![221, 199, 1]);
|
let mut buf = Cursor::new(vec![221, 199, 1]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 25565);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 25565);
|
||||||
assert_eq!(buf.get_varint_size(25565), 3);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![255, 255, 127]);
|
let mut buf = Cursor::new(vec![255, 255, 127]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 2097151);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2097151);
|
||||||
assert_eq!(buf.get_varint_size(2097151), 3);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![255, 255, 255, 255, 7]);
|
let mut buf = Cursor::new(vec![255, 255, 255, 255, 7]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), 2147483647);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2147483647);
|
||||||
assert_eq!(buf.get_varint_size(2147483647), 5);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![255, 255, 255, 255, 15]);
|
let mut buf = Cursor::new(vec![255, 255, 255, 255, 15]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), -1);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), -1);
|
||||||
assert_eq!(buf.get_varint_size(-1), 5);
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(vec![128, 128, 128, 128, 8]);
|
let mut buf = Cursor::new(vec![128, 128, 128, 128, 8]);
|
||||||
assert_eq!(buf.read_varint().unwrap(), -2147483648);
|
assert_eq!(i32::var_read_from(&mut buf).unwrap(), -2147483648);
|
||||||
assert_eq!(buf.get_varint_size(-2147483648), 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read_varint_longer() {
|
fn test_read_varint_longer() {
|
||||||
let mut buf = Cursor::new(vec![138, 56, 0, 135, 56, 123]);
|
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]
|
#[test]
|
||||||
fn test_list() {
|
fn test_list() {
|
||||||
|
let original_vec = vec!["a".to_string(), "bc".to_string(), "def".to_string()];
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_list(&vec!["a", "bc", "def"], |buf, s| buf.write_utf(s))
|
original_vec.write_into(&mut buf).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
dbg!(&buf);
|
||||||
|
|
||||||
// there's no read_list because idk how to do it in rust
|
|
||||||
let mut buf = Cursor::new(buf);
|
let mut buf = Cursor::new(buf);
|
||||||
|
let result = Vec::<String>::read_from(&mut buf).unwrap();
|
||||||
let mut result = Vec::new();
|
assert_eq!(result, original_vec);
|
||||||
let length = buf.read_varint().unwrap();
|
|
||||||
for _ in 0..length {
|
|
||||||
result.push(buf.read_utf().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(result, vec!["a", "bc", "def"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_int_id_list() {
|
fn test_int_id_list() {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_list(&vec![1, 2, 3], |buf, i| buf.write_varint(*i))
|
vec![1, 2, 3].var_write_into(&mut buf).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(buf);
|
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]);
|
assert_eq!(result, vec![1, 2, 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_map() {
|
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();
|
let mut buf = Vec::new();
|
||||||
buf.write_map(
|
original_map.var_write_into(&mut buf).unwrap();
|
||||||
vec![("a", 1), ("bc", 23), ("def", 456)],
|
|
||||||
Vec::write_utf,
|
|
||||||
Vec::write_varint,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut buf = Cursor::new(buf);
|
let mut buf = Cursor::new(buf);
|
||||||
|
|
||||||
let mut result = Vec::new();
|
let result = HashMap::<String, i32>::var_read_from(&mut buf).unwrap();
|
||||||
let length = buf.read_varint().unwrap();
|
|
||||||
for _ in 0..length {
|
|
||||||
result.push((buf.read_utf().unwrap(), buf.read_varint().unwrap()));
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(result, original_map);
|
||||||
result,
|
|
||||||
vec![
|
|
||||||
("a".to_string(), 1),
|
|
||||||
("bc".to_string(), 23),
|
|
||||||
("def".to_string(), 456)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_long() {
|
fn test_long() {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_long(123456).unwrap();
|
123456u64.write_into(&mut buf).unwrap();
|
||||||
|
|
||||||
let mut buf = Cursor::new(buf);
|
let mut buf = Cursor::new(buf);
|
||||||
|
|
||||||
assert_eq!(buf.read_long().unwrap(), 123456);
|
assert_eq!(u64::read_from(&mut buf).unwrap(), 123456);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,10 @@ pub enum BufReadError {
|
||||||
InvalidVarLong,
|
InvalidVarLong,
|
||||||
#[error("Error reading bytes")]
|
#[error("Error reading bytes")]
|
||||||
CouldNotReadBytes,
|
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})")]
|
#[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}")]
|
#[error("{0}")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error("Boolean value is not 0 or 1")]
|
|
||||||
InvalidBoolean,
|
|
||||||
#[error("Invalid UTF-8")]
|
#[error("Invalid UTF-8")]
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
#[error("Unexpected enum variant {id}")]
|
#[error("Unexpected enum variant {id}")]
|
||||||
|
@ -33,158 +29,27 @@ pub enum BufReadError {
|
||||||
Deserialization(#[from] serde_json::Error),
|
Deserialization(#[from] serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: get rid of Readable and use McBufReadable everywhere
|
fn read_utf_with_len(buf: &mut impl Read, max_length: u32) -> Result<String, BufReadError> {
|
||||||
|
let length = u32::var_read_from(buf)?;
|
||||||
pub trait Readable {
|
// i don't know why it's multiplied by 4 but it's like that in mojang's code so
|
||||||
fn read_int_id_list(&mut self) -> Result<Vec<i32>, BufReadError>;
|
if length as u32 > max_length * 4 {
|
||||||
fn read_varint(&mut self) -> Result<i32, BufReadError>;
|
return Err(BufReadError::StringLengthTooLong {
|
||||||
fn get_varint_size(&mut self, value: i32) -> u8;
|
length,
|
||||||
fn get_varlong_size(&mut self, value: i32) -> u8;
|
max_length: max_length * 4,
|
||||||
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
|
// this is probably quite inefficient, idk how to do it better
|
||||||
/// Read a single varint from the reader and return the value
|
let mut string = String::new();
|
||||||
fn read_varint(&mut self) -> Result<i32, BufReadError> {
|
let mut buffer = vec![0; length as usize];
|
||||||
let mut buffer = [0];
|
buf.read_exact(&mut buffer)
|
||||||
let mut ans = 0;
|
.map_err(|_| BufReadError::InvalidUtf8)?;
|
||||||
for i in 0..5 {
|
string.push_str(std::str::from_utf8(&buffer).unwrap());
|
||||||
self.read_exact(&mut buffer)
|
if string.len() > length as usize {
|
||||||
.map_err(|_| BufReadError::InvalidVarInt)?;
|
return Err(BufReadError::StringLengthTooLong { length, max_length });
|
||||||
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 {
|
Ok(string)
|
||||||
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()?;
|
|
||||||
// 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,
|
|
||||||
max_length: max_length * 4,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
.map_err(|_| BufReadError::InvalidUtf8)?;
|
|
||||||
string.push_str(std::str::from_utf8(&buffer).unwrap());
|
|
||||||
if string.len() > length as usize {
|
|
||||||
return Err(BufReadError::StringLengthTooLong { length, max_length });
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
// 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 {
|
impl McBufReadable for i32 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
Readable::read_int(buf)
|
Ok(buf.read_i32::<BE>()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl McBufVarReadable for i32 {
|
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> {
|
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 {
|
impl McBufReadable for UnsizedByteArray {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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> {
|
impl<T: McBufReadable + Send> McBufReadable for Vec<T> {
|
||||||
default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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);
|
let mut contents = Vec::with_capacity(length);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
contents.push(T::read_from(buf)?);
|
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> {
|
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> {
|
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);
|
let mut contents = HashMap::with_capacity(length);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
contents.insert(K::read_from(buf)?, V::read_from(buf)?);
|
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>
|
for HashMap<K, V>
|
||||||
{
|
{
|
||||||
default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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);
|
let mut contents = HashMap::with_capacity(length);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
contents.insert(K::read_from(buf)?, V::var_read_from(buf)?);
|
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> {
|
impl McBufReadable for Vec<u8> {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufReadable for String {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufReadable for u32 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufVarReadable for u32 {
|
||||||
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufReadable for u16 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufReadable for i16 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
buf.read_short()
|
Ok(buf.read_i16::<BE>()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl McBufVarReadable for u16 {
|
impl McBufVarReadable for u16 {
|
||||||
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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> {
|
impl<T: McBufVarReadable> McBufVarReadable for Vec<T> {
|
||||||
fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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);
|
let mut contents = Vec::with_capacity(length);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
contents.push(T::var_read_from(buf)?);
|
contents.push(T::var_read_from(buf)?);
|
||||||
|
@ -351,7 +236,7 @@ impl<T: McBufVarReadable> McBufVarReadable for Vec<T> {
|
||||||
|
|
||||||
impl McBufReadable for i64 {
|
impl McBufReadable for i64 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufReadable for bool {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
buf.read_boolean()
|
Ok(u8::read_from(buf)? != 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl McBufReadable for u8 {
|
impl McBufReadable for u8 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
buf.read_byte()
|
Ok(buf.read_u8()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl McBufReadable for i8 {
|
impl McBufReadable for i8 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
impl McBufReadable for f32 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
buf.read_float()
|
Ok(buf.read_f32::<BE>()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl McBufReadable for f64 {
|
impl McBufReadable for f64 {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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> {
|
impl<T: McBufReadable> McBufReadable for Option<T> {
|
||||||
default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
Ok(if present {
|
||||||
Some(T::read_from(buf)?)
|
Some(T::read_from(buf)?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -404,7 +289,7 @@ impl<T: McBufReadable> McBufReadable for Option<T> {
|
||||||
|
|
||||||
impl<T: McBufVarReadable> McBufVarReadable for Option<T> {
|
impl<T: McBufVarReadable> McBufVarReadable for Option<T> {
|
||||||
default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
Ok(if present {
|
||||||
Some(T::var_read_from(buf)?)
|
Some(T::var_read_from(buf)?)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{read::BufReadError, McBufReadable, McBufWritable, Readable};
|
use crate::{read::BufReadError, McBufReadable, McBufWritable};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ impl SerializableUuid for Uuid {
|
||||||
impl McBufReadable for Uuid {
|
impl McBufReadable for Uuid {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
Ok(Uuid::from_int_array([
|
Ok(Uuid::from_int_array([
|
||||||
Readable::read_int(buf)? as u32,
|
u32::read_from(buf)?,
|
||||||
Readable::read_int(buf)? as u32,
|
u32::read_from(buf)?,
|
||||||
Readable::read_int(buf)? as u32,
|
u32::read_from(buf)?,
|
||||||
Readable::read_int(buf)? as u32,
|
u32::read_from(buf)?,
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@ impl McBufWritable for Uuid {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add a test for Uuid in McBuf
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -2,115 +2,22 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH};
|
||||||
use byteorder::{BigEndian, WriteBytesExt};
|
use byteorder::{BigEndian, WriteBytesExt};
|
||||||
use std::{collections::HashMap, io::Write};
|
use std::{collections::HashMap, io::Write};
|
||||||
|
|
||||||
// TODO: get rid of Writable and use McBufWritable everywhere
|
fn write_utf_with_len(
|
||||||
|
buf: &mut impl Write,
|
||||||
pub trait Writable: Write {
|
string: &str,
|
||||||
fn write_list<F, T>(&mut self, list: &[T], writer: F) -> Result<(), std::io::Error>
|
len: usize,
|
||||||
where
|
) -> Result<(), std::io::Error> {
|
||||||
F: FnOnce(&mut Self, &T) -> Result<(), std::io::Error> + Copy,
|
if string.len() > len {
|
||||||
{
|
panic!(
|
||||||
self.write_varint(list.len() as i32)?;
|
"String too big (was {} bytes encoded, max {})",
|
||||||
for item in list {
|
string.len(),
|
||||||
writer(self, item)?;
|
len
|
||||||
}
|
);
|
||||||
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> {
|
|
||||||
if string.len() > len {
|
|
||||||
panic!(
|
|
||||||
"String too big (was {} bytes encoded, max {})",
|
|
||||||
string.len(),
|
|
||||||
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 {
|
pub trait McBufWritable {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
|
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
|
||||||
}
|
}
|
||||||
|
@ -121,25 +28,48 @@ pub trait McBufVarWritable {
|
||||||
|
|
||||||
impl McBufWritable for i32 {
|
impl McBufWritable for i32 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufVarWritable for i32 {
|
||||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for UnsizedByteArray {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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> {
|
impl<T: McBufWritable> McBufWritable for Vec<T> {
|
||||||
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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> {
|
impl McBufWritable for Vec<u8> {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for String {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for u8 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for i16 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for i64 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for bool {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for i8 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for f32 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
impl McBufWritable for f64 {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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> {
|
impl<T: McBufWritable> McBufWritable for Option<T> {
|
||||||
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||||
if let Some(s) = self {
|
if let Some(s) = self {
|
||||||
buf.write_boolean(true)?;
|
true.write_into(buf)?;
|
||||||
s.write_into(buf)?;
|
s.write_into(buf)?;
|
||||||
} else {
|
} else {
|
||||||
buf.write_boolean(false)?;
|
false.write_into(buf)?;
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -300,10 +232,10 @@ impl<T: McBufWritable> McBufWritable for Option<T> {
|
||||||
impl<T: McBufVarWritable> McBufVarWritable for Option<T> {
|
impl<T: McBufVarWritable> McBufVarWritable for Option<T> {
|
||||||
default fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
default fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||||
if let Some(s) = self {
|
if let Some(s) = self {
|
||||||
buf.write_boolean(true)?;
|
true.write_into(buf)?;
|
||||||
s.var_write_into(buf)?;
|
s.var_write_into(buf)?;
|
||||||
} else {
|
} else {
|
||||||
buf.write_boolean(false)?;
|
false.write_into(buf)?;
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl McBufWritable for Component {
|
||||||
// where
|
// where
|
||||||
// R: AsyncRead + std::marker::Unpin + std::marker::Send,
|
// 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())
|
// let json: serde_json::Value = serde_json::from_str(string.as_str())
|
||||||
// .map_err(|e| "Component isn't valid JSON".to_string())?;
|
// .map_err(|e| "Component isn't valid JSON".to_string())?;
|
||||||
// let component = Component::deserialize(json).map_err(|e| e.to_string())?;
|
// let component = Component::deserialize(json).map_err(|e| e.to_string())?;
|
||||||
|
|
|
@ -146,7 +146,7 @@ impl MovableEntity for EntityMut<'_> {
|
||||||
|
|
||||||
// TODO: minecraft checks for a "minor" horizontal collision here
|
// 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
|
// let _block_state_below = self
|
||||||
// .dimension
|
// .dimension
|
||||||
// .get_block_state(&block_pos_below)
|
// .get_block_state(&block_pos_below)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use azalea_buf::BufReadError;
|
use azalea_buf::BufReadError;
|
||||||
use azalea_buf::McBuf;
|
use azalea_buf::McBuf;
|
||||||
use azalea_buf::McBufVarReadable;
|
use azalea_buf::McBufVarReadable;
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
use azalea_buf::{McBufReadable, McBufWritable};
|
||||||
use azalea_core::ResourceLocation;
|
use azalea_core::ResourceLocation;
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -26,7 +26,7 @@ pub struct BrigadierNumber<T> {
|
||||||
}
|
}
|
||||||
impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
|
impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 {
|
let min = if flags & 0x01 != 0 {
|
||||||
Some(T::read_from(buf)?)
|
Some(T::read_from(buf)?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,14 +42,14 @@ impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
|
||||||
}
|
}
|
||||||
impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
|
impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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() {
|
if self.min.is_some() {
|
||||||
flags |= 0x01;
|
flags |= 0x01;
|
||||||
}
|
}
|
||||||
if self.max.is_some() {
|
if self.max.is_some() {
|
||||||
flags |= 0x02;
|
flags |= 0x02;
|
||||||
}
|
}
|
||||||
buf.write_byte(flags)?;
|
flags.write_into(buf)?;
|
||||||
if let Some(min) = &self.min {
|
if let Some(min) = &self.min {
|
||||||
min.write_into(buf)?;
|
min.write_into(buf)?;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ impl McBufReadable for BrigadierParser {
|
||||||
4 => Ok(BrigadierParser::Long(BrigadierNumber::read_from(buf)?)),
|
4 => Ok(BrigadierParser::Long(BrigadierNumber::read_from(buf)?)),
|
||||||
5 => Ok(BrigadierParser::String(BrigadierString::read_from(buf)?)),
|
5 => Ok(BrigadierParser::String(BrigadierString::read_from(buf)?)),
|
||||||
6 => {
|
6 => {
|
||||||
let flags = buf.read_byte()?;
|
let flags = u8::read_from(buf)?;
|
||||||
Ok(BrigadierParser::Entity {
|
Ok(BrigadierParser::Entity {
|
||||||
single: flags & 0x01 != 0,
|
single: flags & 0x01 != 0,
|
||||||
players_only: flags & 0x02 != 0,
|
players_only: flags & 0x02 != 0,
|
||||||
|
@ -164,7 +164,7 @@ impl McBufReadable for BrigadierParser {
|
||||||
27 => Ok(BrigadierParser::Rotation),
|
27 => Ok(BrigadierParser::Rotation),
|
||||||
28 => Ok(BrigadierParser::ScoreboardSlot),
|
28 => Ok(BrigadierParser::ScoreboardSlot),
|
||||||
29 => {
|
29 => {
|
||||||
let flags = buf.read_byte()?;
|
let flags = u8::read_from(buf)?;
|
||||||
Ok(BrigadierParser::ScoreHolder {
|
Ok(BrigadierParser::ScoreHolder {
|
||||||
allows_multiple: flags & 0x01 != 0,
|
allows_multiple: flags & 0x01 != 0,
|
||||||
})
|
})
|
||||||
|
@ -213,12 +213,16 @@ impl McBufReadable for BrigadierNodeStub {
|
||||||
let has_redirect = flags & 0x08 != 0;
|
let has_redirect = flags & 0x08 != 0;
|
||||||
let has_suggestions_type = flags & 0x10 != 0;
|
let has_suggestions_type = flags & 0x10 != 0;
|
||||||
|
|
||||||
let _children = buf.read_int_id_list()?;
|
let _children = Vec::<i32>::var_read_from(buf)?;
|
||||||
let _redirect_node = if has_redirect { buf.read_varint()? } else { 0 };
|
let _redirect_node = if has_redirect {
|
||||||
|
i32::var_read_from(buf)?
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
// argument node
|
// argument node
|
||||||
if node_type == 2 {
|
if node_type == 2 {
|
||||||
let _name = buf.read_utf()?;
|
let _name = String::read_from(buf)?;
|
||||||
let _parser = BrigadierParser::read_from(buf)?;
|
let _parser = BrigadierParser::read_from(buf)?;
|
||||||
let _suggestions_type = if has_suggestions_type {
|
let _suggestions_type = if has_suggestions_type {
|
||||||
Some(ResourceLocation::read_from(buf)?)
|
Some(ResourceLocation::read_from(buf)?)
|
||||||
|
@ -229,7 +233,7 @@ impl McBufReadable for BrigadierNodeStub {
|
||||||
}
|
}
|
||||||
// literal node
|
// literal node
|
||||||
if node_type == 1 {
|
if node_type == 1 {
|
||||||
let _name = buf.read_utf()?;
|
let _name = String::read_from(buf)?;
|
||||||
return Ok(BrigadierNodeStub {});
|
return Ok(BrigadierNodeStub {});
|
||||||
}
|
}
|
||||||
Ok(BrigadierNodeStub {})
|
Ok(BrigadierNodeStub {})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use azalea_buf::{BufReadError, McBuf};
|
use azalea_buf::{BufReadError, McBuf};
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable};
|
use azalea_buf::{McBufReadable, McBufWritable};
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ pub struct PlayerAbilitiesFlags {
|
||||||
|
|
||||||
impl McBufReadable for PlayerAbilitiesFlags {
|
impl McBufReadable for PlayerAbilitiesFlags {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
let byte = buf.read_byte()?;
|
let byte = u8::read_from(buf)?;
|
||||||
Ok(PlayerAbilitiesFlags {
|
Ok(PlayerAbilitiesFlags {
|
||||||
invulnerable: byte & 1 != 0,
|
invulnerable: byte & 1 != 0,
|
||||||
flying: byte & 2 != 0,
|
flying: byte & 2 != 0,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::packets::login::serverbound_hello_packet::ProfilePublicKeyData;
|
use crate::packets::login::serverbound_hello_packet::ProfilePublicKeyData;
|
||||||
use azalea_buf::{BufReadError, McBuf};
|
use azalea_buf::{BufReadError, McBuf};
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
use azalea_buf::{McBufReadable, McBufWritable};
|
||||||
use azalea_chat::component::Component;
|
use azalea_chat::component::Component;
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
@ -66,7 +66,7 @@ pub struct RemovePlayer {
|
||||||
|
|
||||||
impl McBufReadable for Action {
|
impl McBufReadable for Action {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
let id = buf.read_byte()?;
|
let id = u8::read_from(buf)?;
|
||||||
Ok(match id {
|
Ok(match id {
|
||||||
0 => Action::AddPlayer(Vec::<AddPlayer>::read_from(buf)?),
|
0 => Action::AddPlayer(Vec::<AddPlayer>::read_from(buf)?),
|
||||||
1 => Action::UpdateGameMode(Vec::<UpdateGameMode>::read_from(buf)?),
|
1 => Action::UpdateGameMode(Vec::<UpdateGameMode>::read_from(buf)?),
|
||||||
|
@ -79,13 +79,14 @@ impl McBufReadable for Action {
|
||||||
}
|
}
|
||||||
impl McBufWritable for Action {
|
impl McBufWritable for Action {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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::AddPlayer(_) => 0,
|
||||||
Action::UpdateGameMode(_) => 1,
|
Action::UpdateGameMode(_) => 1,
|
||||||
Action::UpdateLatency(_) => 2,
|
Action::UpdateLatency(_) => 2,
|
||||||
Action::UpdateDisplayName(_) => 3,
|
Action::UpdateDisplayName(_) => 3,
|
||||||
Action::RemovePlayer(_) => 4,
|
Action::RemovePlayer(_) => 4,
|
||||||
})?;
|
};
|
||||||
|
id.write_into(buf)?;
|
||||||
match self {
|
match self {
|
||||||
Action::AddPlayer(players) => players.write_into(buf)?,
|
Action::AddPlayer(players) => players.write_into(buf)?,
|
||||||
Action::UpdateGameMode(players) => players.write_into(buf)?,
|
Action::UpdateGameMode(players) => players.write_into(buf)?,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use azalea_buf::{BufReadError, McBuf};
|
use azalea_buf::{BufReadError, McBuf};
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable};
|
use azalea_buf::{McBufReadable, McBufWritable};
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ pub struct RelativeArguments {
|
||||||
|
|
||||||
impl McBufReadable for RelativeArguments {
|
impl McBufReadable for RelativeArguments {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
let byte = buf.read_byte()?;
|
let byte = u8::read_from(buf)?;
|
||||||
Ok(RelativeArguments {
|
Ok(RelativeArguments {
|
||||||
x: byte & 0b1 != 0,
|
x: byte & 0b1 != 0,
|
||||||
y: byte & 0b10 != 0,
|
y: byte & 0b10 != 0,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use azalea_buf::{BufReadError, McBuf};
|
use azalea_buf::{BufReadError, McBuf};
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
use azalea_buf::{McBufReadable, McBufWritable};
|
||||||
use azalea_core::ResourceLocation;
|
use azalea_core::ResourceLocation;
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
@ -35,7 +35,7 @@ enum Operation {
|
||||||
|
|
||||||
impl McBufReadable for Operation {
|
impl McBufReadable for Operation {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
match buf.read_byte()? {
|
match u8::read_from(buf)? {
|
||||||
0 => Ok(Operation::Addition),
|
0 => Ok(Operation::Addition),
|
||||||
1 => Ok(Operation::MultiplyBase),
|
1 => Ok(Operation::MultiplyBase),
|
||||||
2 => Ok(Operation::MultiplyTotal),
|
2 => Ok(Operation::MultiplyTotal),
|
||||||
|
@ -46,7 +46,7 @@ impl McBufReadable for Operation {
|
||||||
|
|
||||||
impl McBufWritable for Operation {
|
impl McBufWritable for Operation {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use std::io::{Read, Write};
|
use azalea_buf::{
|
||||||
|
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
|
||||||
use azalea_buf::{BufReadError, McBuf};
|
};
|
||||||
use azalea_core::{ResourceLocation, Slot};
|
use azalea_core::{ResourceLocation, Slot};
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
|
use std::io::{Read, Write};
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||||
pub struct ClientboundUpdateRecipesPacket {
|
pub struct ClientboundUpdateRecipesPacket {
|
||||||
|
@ -37,9 +36,9 @@ pub struct ShapedRecipe {
|
||||||
|
|
||||||
impl McBufWritable for ShapedRecipe {
|
impl McBufWritable for ShapedRecipe {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||||
buf.write_varint(self.width.try_into().unwrap())?;
|
(self.width as u32).var_write_into(buf)?;
|
||||||
buf.write_varint(self.height.try_into().unwrap())?;
|
(self.height as u32).var_write_into(buf)?;
|
||||||
buf.write_utf(&self.group)?;
|
self.group.write_into(buf)?;
|
||||||
for ingredient in &self.ingredients {
|
for ingredient in &self.ingredients {
|
||||||
ingredient.write_into(buf)?;
|
ingredient.write_into(buf)?;
|
||||||
}
|
}
|
||||||
|
@ -50,9 +49,9 @@ impl McBufWritable for ShapedRecipe {
|
||||||
}
|
}
|
||||||
impl McBufReadable for ShapedRecipe {
|
impl McBufReadable for ShapedRecipe {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
let width = buf.read_varint()?.try_into().unwrap();
|
let width = u32::var_read_from(buf)?.try_into().unwrap();
|
||||||
let height = buf.read_varint()?.try_into().unwrap();
|
let height = u32::var_read_from(buf)?.try_into().unwrap();
|
||||||
let group = buf.read_utf()?;
|
let group = String::read_from(buf)?;
|
||||||
let mut ingredients = Vec::with_capacity(width * height);
|
let mut ingredients = Vec::with_capacity(width * height);
|
||||||
for _ in 0..width * height {
|
for _ in 0..width * height {
|
||||||
ingredients.push(Ingredient::read_from(buf)?);
|
ingredients.push(Ingredient::read_from(buf)?);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use azalea_buf::{BufReadError, McBuf};
|
use azalea_buf::{BufReadError, McBuf, McBufVarReadable, McBufVarWritable};
|
||||||
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
use azalea_buf::{McBufReadable, McBufWritable};
|
||||||
use azalea_core::ResourceLocation;
|
use azalea_core::ResourceLocation;
|
||||||
use packet_macros::ClientboundGamePacket;
|
use packet_macros::ClientboundGamePacket;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -24,11 +24,11 @@ pub struct TagMap(HashMap<ResourceLocation, Vec<Tags>>);
|
||||||
|
|
||||||
impl McBufReadable for TagMap {
|
impl McBufReadable for TagMap {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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);
|
let mut data = HashMap::with_capacity(length);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
let tag_type = ResourceLocation::read_from(buf)?;
|
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);
|
let mut tags_vec = Vec::with_capacity(tags_count);
|
||||||
for _ in 0..tags_count {
|
for _ in 0..tags_count {
|
||||||
let tags = Tags::read_from(buf)?;
|
let tags = Tags::read_from(buf)?;
|
||||||
|
@ -42,7 +42,7 @@ impl McBufReadable for TagMap {
|
||||||
|
|
||||||
impl McBufWritable for TagMap {
|
impl McBufWritable for TagMap {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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 {
|
for (k, v) in &self.0 {
|
||||||
k.write_into(buf)?;
|
k.write_into(buf)?;
|
||||||
v.write_into(buf)?;
|
v.write_into(buf)?;
|
||||||
|
@ -53,7 +53,7 @@ impl McBufWritable for TagMap {
|
||||||
impl McBufReadable for Tags {
|
impl McBufReadable for Tags {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||||
let name = ResourceLocation::read_from(buf)?;
|
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 })
|
Ok(Tags { name, elements })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ impl McBufReadable for Tags {
|
||||||
impl McBufWritable for Tags {
|
impl McBufWritable for Tags {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||||
self.name.write_into(buf)?;
|
self.name.write_into(buf)?;
|
||||||
buf.write_int_id_list(&self.elements)?;
|
self.elements.var_write_into(buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
|
use super::ClientboundLoginPacket;
|
||||||
|
use azalea_buf::{BufReadError, McBufVarReadable, McBufVarWritable};
|
||||||
use std::{
|
use std::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
use azalea_buf::{BufReadError, Readable, Writable};
|
|
||||||
|
|
||||||
use super::ClientboundLoginPacket;
|
|
||||||
|
|
||||||
#[derive(Hash, Clone, Debug)]
|
#[derive(Hash, Clone, Debug)]
|
||||||
pub struct ClientboundLoginCompressionPacket {
|
pub struct ClientboundLoginCompressionPacket {
|
||||||
pub compression_threshold: i32,
|
pub compression_threshold: i32,
|
||||||
|
@ -18,12 +16,12 @@ impl ClientboundLoginCompressionPacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(buf: &mut impl Read) -> Result<ClientboundLoginPacket, BufReadError> {
|
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 {
|
Ok(ClientboundLoginCompressionPacket {
|
||||||
compression_threshold,
|
compression_threshold,
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub mod login;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
|
||||||
use crate::read::ReadPacketError;
|
use crate::read::ReadPacketError;
|
||||||
use azalea_buf::{BufReadError, McBufWritable, Readable, Writable};
|
use azalea_buf::{BufReadError, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
pub const PROTOCOL_VERSION: u32 = 760;
|
pub const PROTOCOL_VERSION: u32 = 760;
|
||||||
|
@ -44,13 +44,13 @@ where
|
||||||
|
|
||||||
impl azalea_buf::McBufReadable for ConnectionProtocol {
|
impl azalea_buf::McBufReadable for ConnectionProtocol {
|
||||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
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 })
|
ConnectionProtocol::from_i32(id).ok_or(BufReadError::UnexpectedEnumVariant { id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl McBufWritable for ConnectionProtocol {
|
impl McBufWritable for ConnectionProtocol {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::ClientboundStatusPacket;
|
use super::ClientboundStatusPacket;
|
||||||
use azalea_buf::{BufReadError, Readable};
|
use azalea_buf::{BufReadError, McBufReadable};
|
||||||
use azalea_chat::component::Component;
|
use azalea_chat::component::Component;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -44,7 +44,7 @@ impl ClientboundStatusResponsePacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(buf: &mut impl Read) -> Result<ClientboundStatusPacket, BufReadError> {
|
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 status_json: Value = serde_json::from_str(status_string.as_str())?;
|
||||||
|
|
||||||
let packet = ClientboundStatusResponsePacket::deserialize(status_json)?.get();
|
let packet = ClientboundStatusResponsePacket::deserialize(status_json)?.get();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::packets::ProtocolPacket;
|
use crate::packets::ProtocolPacket;
|
||||||
use azalea_buf::McBufVarReadable;
|
use azalea_buf::McBufVarReadable;
|
||||||
use azalea_buf::{read_varint_async, BufReadError, Readable};
|
use azalea_buf::{read_varint_async, BufReadError};
|
||||||
use azalea_crypto::Aes128CfbDec;
|
use azalea_crypto::Aes128CfbDec;
|
||||||
use flate2::read::ZlibDecoder;
|
use flate2::read::ZlibDecoder;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -78,9 +78,8 @@ where
|
||||||
|
|
||||||
fn packet_decoder<P: ProtocolPacket>(stream: &mut impl Read) -> Result<P, ReadPacketError> {
|
fn packet_decoder<P: ProtocolPacket>(stream: &mut impl Read) -> Result<P, ReadPacketError> {
|
||||||
// Packet ID
|
// Packet ID
|
||||||
let packet_id = stream
|
let packet_id =
|
||||||
.read_varint()
|
u32::var_read_from(stream).map_err(|e| ReadPacketError::ReadPacketId { source: e })?;
|
||||||
.map_err(|e| ReadPacketError::ReadPacketId { source: e })?;
|
|
||||||
P::read(packet_id.try_into().unwrap(), stream)
|
P::read(packet_id.try_into().unwrap(), stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{packets::ProtocolPacket, read::MAXIMUM_UNCOMPRESSED_LENGTH};
|
use crate::{packets::ProtocolPacket, read::MAXIMUM_UNCOMPRESSED_LENGTH};
|
||||||
use async_compression::tokio::bufread::ZlibEncoder;
|
use async_compression::tokio::bufread::ZlibEncoder;
|
||||||
use azalea_buf::Writable;
|
use azalea_buf::McBufVarWritable;
|
||||||
use azalea_crypto::Aes128CfbEnc;
|
use azalea_crypto::Aes128CfbEnc;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use thiserror::Error;
|
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> {
|
fn frame_prepender(data: &mut Vec<u8>) -> Result<Vec<u8>, std::io::Error> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(data.len() as i32)?;
|
(data.len() as u32).var_write_into(&mut buf)?;
|
||||||
buf.append(data);
|
buf.append(data);
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ fn packet_encoder<P: ProtocolPacket + std::fmt::Debug>(
|
||||||
packet: &P,
|
packet: &P,
|
||||||
) -> Result<Vec<u8>, PacketEncodeError> {
|
) -> Result<Vec<u8>, PacketEncodeError> {
|
||||||
let mut buf = Vec::new();
|
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)?;
|
packet.write(&mut buf)?;
|
||||||
if buf.len() > MAXIMUM_UNCOMPRESSED_LENGTH as usize {
|
if buf.len() > MAXIMUM_UNCOMPRESSED_LENGTH as usize {
|
||||||
return Err(PacketEncodeError::TooBig {
|
return Err(PacketEncodeError::TooBig {
|
||||||
|
@ -55,7 +55,7 @@ async fn compression_encoder(
|
||||||
// if it's less than the compression threshold, don't compress
|
// if it's less than the compression threshold, don't compress
|
||||||
if n < compression_threshold as usize {
|
if n < compression_threshold as usize {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.write_varint(0)?;
|
0.var_write_into(&mut buf)?;
|
||||||
buf.write_all(data).await?;
|
buf.write_all(data).await?;
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use azalea_buf::{
|
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufWritable};
|
||||||
BufReadError, McBufReadable, McBufVarReadable, McBufWritable, Readable, Writable,
|
|
||||||
};
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
use crate::BitStorage;
|
use crate::BitStorage;
|
||||||
|
@ -38,7 +36,7 @@ impl PalettedContainer {
|
||||||
buf: &mut impl Read,
|
buf: &mut impl Read,
|
||||||
container_type: &'static PalettedContainerType,
|
container_type: &'static PalettedContainerType,
|
||||||
) -> Result<Self, BufReadError> {
|
) -> 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_type = PaletteType::from_bits_and_type(bits_per_entry, container_type);
|
||||||
let palette = palette_type.read(buf)?;
|
let palette = palette_type.read(buf)?;
|
||||||
let size = container_type.size();
|
let size = container_type.size();
|
||||||
|
@ -181,7 +179,7 @@ impl PalettedContainer {
|
||||||
|
|
||||||
impl McBufWritable for PalettedContainer {
|
impl McBufWritable for PalettedContainer {
|
||||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
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.palette.write_into(buf)?;
|
||||||
self.storage.data.write_into(buf)?;
|
self.storage.data.write_into(buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Reference in a new issue