fix varint
This commit is contained in:
parent
9fecfadf17
commit
ba2f89b4c4
26
.gitea/workflows/rust.yml
Normal file
26
.gitea/workflows/rust.yml
Normal file
@ -0,0 +1,26 @@
|
||||
on: [push, pull_request]
|
||||
|
||||
name: Rust
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- run: cargo check
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- run: cargo build
|
||||
test:
|
||||
name: Test Suite
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- run: cargo test
|
@ -1,7 +1,6 @@
|
||||
//! `DataReader` and `DataWriter` traits for reading and writing primitive types in the Minecraft protocol
|
||||
|
||||
pub mod reader;
|
||||
pub mod varint;
|
||||
pub mod writer;
|
||||
|
||||
pub use reader::*;
|
||||
|
@ -1,8 +1,4 @@
|
||||
use crate::{
|
||||
data::varint::{read_varint, size_varint},
|
||||
zigzag::Zigzag,
|
||||
ProtocolError,
|
||||
};
|
||||
use crate::ProtocolError;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use uuid::Uuid;
|
||||
|
||||
@ -79,122 +75,242 @@ pub trait DataReader {
|
||||
}}
|
||||
}
|
||||
|
||||
/// Read VarInt as usize with size in bytes (varint, size)
|
||||
fn read_usize_varint_size(&mut self) -> impl Future<Output = Result<(usize, usize), ProtocolError>> {
|
||||
async {size_varint!(usize, self)}
|
||||
}
|
||||
/// Read VarInt as u8 with size in bytes (varint, size)
|
||||
fn read_u8_varint_size(&mut self) -> impl Future<Output = Result<(u8, usize), ProtocolError>> {
|
||||
async {size_varint!(u8, self)}
|
||||
}
|
||||
/// Read VarInt as u16 with size in bytes (varint, size)
|
||||
fn read_u16_varint_size(&mut self) -> impl Future<Output = Result<(u16, usize), ProtocolError>> {
|
||||
async {size_varint!(u16, self)}
|
||||
}
|
||||
/// Read VarInt as u32 with size in bytes (varint, size)
|
||||
fn read_u32_varint_size(&mut self) -> impl Future<Output = Result<(u32, usize), ProtocolError>> {
|
||||
async {size_varint!(u32, self)}
|
||||
}
|
||||
/// Read VarInt as u64 with size in bytes (varint, size)
|
||||
fn read_u64_varint_size(&mut self) -> impl Future<Output = Result<(u64, usize), ProtocolError>> {
|
||||
async {size_varint!(u64, self)}
|
||||
}
|
||||
/// Read VarInt as u128 with size in bytes (varint, size)
|
||||
fn read_u128_varint_size(&mut self) -> impl Future<Output = Result<(u128, usize), ProtocolError>> {
|
||||
async {size_varint!(u128, self)}
|
||||
}
|
||||
|
||||
/// Read VarInt as isize with size in bytes (varint, size)
|
||||
fn read_isize_varint_size(&mut self) -> impl Future<Output = Result<(isize, usize), ProtocolError>> {
|
||||
async {Ok({
|
||||
let i = self.read_usize_varint_size().await?;
|
||||
(i.0.zigzag(), i.1)
|
||||
})}
|
||||
}
|
||||
/// Read VarInt as i8 with size in bytes (varint, size)
|
||||
fn read_i8_varint_size(&mut self) -> impl Future<Output = Result<(i8, usize), ProtocolError>> {
|
||||
async {Ok({
|
||||
let i = self.read_u8_varint_size().await?;
|
||||
(i.0.zigzag(), i.1)
|
||||
})}
|
||||
}
|
||||
/// Read VarInt as i16 with size in bytes (varint, size)
|
||||
fn read_i16_varint_size(&mut self) -> impl Future<Output = Result<(i16, usize), ProtocolError>> {
|
||||
async {Ok({
|
||||
let i = self.read_u16_varint_size().await?;
|
||||
(i.0.zigzag(), i.1)
|
||||
})}
|
||||
}
|
||||
/// Read VarInt as i32 with size in bytes (varint, size)
|
||||
fn read_i32_varint_size(&mut self) -> impl Future<Output = Result<(i32, usize), ProtocolError>> {
|
||||
async {Ok({
|
||||
let i = self.read_u32_varint_size().await?;
|
||||
(i.0.zigzag(), i.1)
|
||||
})}
|
||||
}
|
||||
/// Read VarInt as i64 with size in bytes (varint, size)
|
||||
fn read_i64_varint_size(&mut self) -> impl Future<Output = Result<(i64, usize), ProtocolError>> {
|
||||
async {Ok({
|
||||
let i = self.read_u64_varint_size().await?;
|
||||
(i.0.zigzag(), i.1)
|
||||
})}
|
||||
}
|
||||
/// Read VarInt as i128 with size in bytes (varint, size)
|
||||
fn read_i128_varint_size(&mut self) -> impl Future<Output = Result<(i128, usize), ProtocolError>> {
|
||||
async {Ok({
|
||||
let i = self.read_u128_varint_size().await?;
|
||||
(i.0.zigzag(), i.1)
|
||||
})}
|
||||
}
|
||||
|
||||
/// Read VarInt as usize
|
||||
fn read_usize_varint(&mut self) -> impl Future<Output = Result<usize, ProtocolError>> {
|
||||
async {read_varint!(usize, self)}
|
||||
}
|
||||
/// Read VarInt as u8
|
||||
fn read_u8_varint(&mut self) -> impl Future<Output = Result<u8, ProtocolError>> {
|
||||
async {read_varint!(u8, self)}
|
||||
}
|
||||
/// Read VarInt as u16
|
||||
fn read_u16_varint(&mut self) -> impl Future<Output = Result<u16, ProtocolError>> {
|
||||
async {read_varint!(u16, self)}
|
||||
}
|
||||
/// Read VarInt as u32
|
||||
fn read_u32_varint(&mut self) -> impl Future<Output = Result<u32, ProtocolError>> {
|
||||
async {read_varint!(u32, self)}
|
||||
///
|
||||
/// Returns error if the value is greater than i32::MAX
|
||||
async fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> {
|
||||
let val = self.read_varint().await?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
TryInto::<u32>::try_into(val).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarInt as u64
|
||||
fn read_u64_varint(&mut self) -> impl Future<Output = Result<u64, ProtocolError>> {
|
||||
async {read_varint!(u64, self)}
|
||||
}
|
||||
/// Read VarInt as u128
|
||||
fn read_u128_varint(&mut self) -> impl Future<Output = Result<u128, ProtocolError>> {
|
||||
async {read_varint!(u128, self)}
|
||||
}
|
||||
|
||||
/// Read VarInt as isize
|
||||
fn read_isize_varint(&mut self) -> impl Future<Output = Result<isize, ProtocolError>> {
|
||||
async {Ok(self.read_usize_varint().await?.zigzag())}
|
||||
/// Read VarInt as usize
|
||||
async fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> {
|
||||
Ok(TryInto::<usize>::try_into(self.read_varint().await?).map_err(|_| ProtocolError::VarIntError)?)
|
||||
}
|
||||
/// Read VarInt as i8
|
||||
fn read_i8_varint(&mut self) -> impl Future<Output = Result<i8, ProtocolError>> {
|
||||
async {Ok(self.read_u8_varint().await?.zigzag())}
|
||||
async fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> {
|
||||
TryInto::<i8>::try_into(self.read_varint().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarInt as i16
|
||||
fn read_i16_varint(&mut self) -> impl Future<Output = Result<i16, ProtocolError>> {
|
||||
async {Ok(self.read_u16_varint().await?.zigzag())}
|
||||
async fn read_i16_varint(&mut self,) -> Result<i16, ProtocolError> {
|
||||
TryInto::<i16>::try_into(self.read_varint().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarInt as i32
|
||||
fn read_i32_varint(&mut self) -> impl Future<Output = Result<i32, ProtocolError>> {
|
||||
async {Ok(self.read_u32_varint().await?.zigzag())}
|
||||
///
|
||||
/// *Use [read_varint](DataReader::read_varint) instead*
|
||||
async fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> {
|
||||
self.read_varint().await
|
||||
}
|
||||
/// Read VarInt as i64
|
||||
fn read_i64_varint(&mut self) -> impl Future<Output = Result<i64, ProtocolError>> {
|
||||
async {Ok(self.read_u64_varint().await?.zigzag())}
|
||||
/// Read VarInt as isize
|
||||
async fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> {
|
||||
Ok(TryInto::<isize>::try_into(self.read_varint().await?).map_err(|_| ProtocolError::VarIntError)?)
|
||||
}
|
||||
/// Read VarInt as i128
|
||||
fn read_i128_varint(&mut self) -> impl Future<Output = Result<i128, ProtocolError>> {
|
||||
async {Ok(self.read_u128_varint().await?.zigzag())}
|
||||
|
||||
/// Read VarLong as u8
|
||||
async fn read_u8_varlong(&mut self) -> Result<u8, ProtocolError> {
|
||||
TryInto::<u8>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as u16
|
||||
async fn read_u16_varlong(&mut self) -> Result<u16, ProtocolError> {
|
||||
TryInto::<u16>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as u32
|
||||
async fn read_u32_varlong(&mut self) -> Result<u32, ProtocolError> {
|
||||
TryInto::<u32>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as usize
|
||||
///
|
||||
/// Returns error if the value is greater than i64::MAX
|
||||
async fn read_usize_varlong(&mut self) -> Result<usize, ProtocolError> {
|
||||
let val = TryInto::<usize>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)?;
|
||||
if val as u64 > i64::MAX as u64 { return Err(ProtocolError::VarIntError); }
|
||||
Ok(val)
|
||||
}
|
||||
/// Read VarLong as u64
|
||||
///
|
||||
/// Returns error if the value is greater than i64::MAX
|
||||
async fn read_u64_varlong(&mut self) -> Result<u64, ProtocolError> {
|
||||
let val = self.read_varlong().await?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
TryInto::<u64>::try_into(val).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as i8
|
||||
async fn read_i8_varlong(&mut self) -> Result<i8, ProtocolError> {
|
||||
TryInto::<i8>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as i16
|
||||
async fn read_i16_varlong(&mut self) -> Result<i16, ProtocolError> {
|
||||
TryInto::<i16>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as i32
|
||||
async fn read_i32_varlong(&mut self) -> Result<i32, ProtocolError> {
|
||||
TryInto::<i32>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)
|
||||
}
|
||||
/// Read VarLong as isize
|
||||
async fn read_isize_varlong(&mut self) -> Result<isize, ProtocolError> {
|
||||
Ok(TryInto::<isize>::try_into(self.read_varlong().await?).map_err(|_| ProtocolError::VarIntError)?)
|
||||
}
|
||||
/// Read VarLong as i64
|
||||
///
|
||||
/// *Use [read_varlong](DataReader::read_varlong) instead*
|
||||
async fn read_i64_varlong(&mut self) -> Result<i64, ProtocolError> {
|
||||
self.read_varlong().await
|
||||
}
|
||||
|
||||
/// Read VarInt as u8 with size in bytes (value, size)
|
||||
async fn read_u8_varint_size(&mut self) -> Result<(u8, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
Ok((TryInto::<u8>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarInt as u16 with size in bytes (value, size)
|
||||
async fn read_u16_varint_size(&mut self) -> Result<(u16, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
Ok((TryInto::<u16>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarInt as u32 with size in bytes (value, size)
|
||||
///
|
||||
/// Returns error if the value is greater than i32::MAX
|
||||
async fn read_u32_varint_size(&mut self) -> Result<(u32, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
Ok((TryInto::<u32>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarInt as usize with size in bytes (value, size)
|
||||
async fn read_usize_varint_size(&mut self) -> Result<(usize, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
Ok((TryInto::<usize>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarInt as i8 with size in bytes (value, size)
|
||||
async fn read_i8_varint_size(&mut self) -> Result<(i8, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
Ok((TryInto::<i8>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarInt as i16 with size in bytes (value, size)
|
||||
async fn read_i16_varint_size(&mut self,) -> Result<(i16, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
Ok((TryInto::<i16>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarInt as i32 with size in bytes (value, size)
|
||||
///
|
||||
/// *Use [read_varint_size](DataReader::read_varint_size) instead*
|
||||
async fn read_i32_varint_size(&mut self) -> Result<(i32, usize), ProtocolError> {
|
||||
self.read_varint_size().await
|
||||
}
|
||||
/// Read VarInt as isize with size in bytes (value, size)
|
||||
async fn read_isize_varint_size(&mut self) -> Result<(isize, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varint_size().await?;
|
||||
Ok((TryInto::<isize>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
|
||||
/// Read VarLong as u8 with size in bytes (value, size)
|
||||
async fn read_u8_varlong_size(&mut self) -> Result<(u8, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<u8>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as u16 with size in bytes (value, size)
|
||||
async fn read_u16_varlong_size(&mut self) -> Result<(u16, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<u16>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as u32 with size in bytes (value, size)
|
||||
async fn read_u32_varlong_size(&mut self) -> Result<(u32, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<u32>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as usize with size in bytes (value, size)
|
||||
///
|
||||
/// Returns error if the value is greater than i64::MAX
|
||||
async fn read_usize_varlong_size(&mut self) -> Result<(usize, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
let val = TryInto::<usize>::try_into(val).map_err(|_| ProtocolError::VarIntError)?;
|
||||
if val as u64 > i64::MAX as u64 { return Err(ProtocolError::VarIntError); }
|
||||
Ok((val, size))
|
||||
}
|
||||
/// Read VarLong as u64 with size in bytes (value, size)
|
||||
///
|
||||
/// Returns error if the value is greater than i64::MAX
|
||||
async fn read_u64_varlong_size(&mut self) -> Result<(u64, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
Ok((TryInto::<u64>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as i8 with size in bytes (value, size)
|
||||
async fn read_i8_varlong_size(&mut self) -> Result<(i8, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<i8>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as i16 with size in bytes (value, size)
|
||||
async fn read_i16_varlong_size(&mut self) -> Result<(i16, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<i16>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as i32 with size in bytes (value, size)
|
||||
async fn read_i32_varlong_size(&mut self) -> Result<(i32, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<i32>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as isize with size in bytes (value, size)
|
||||
async fn read_isize_varlong_size(&mut self) -> Result<(isize, usize), ProtocolError> {
|
||||
let (val, size) = self.read_varlong_size().await?;
|
||||
Ok((TryInto::<isize>::try_into(val).map_err(|_| ProtocolError::VarIntError)?, size))
|
||||
}
|
||||
/// Read VarLong as i64 with size in bytes (value, size)
|
||||
///
|
||||
/// *Use [read_varlong_size](DataReader::read_varlong_size) instead*
|
||||
async fn read_i64_varlong_size(&mut self) -> Result<(i64, usize), ProtocolError> {
|
||||
self.read_varlong_size().await
|
||||
}
|
||||
|
||||
/// Read VarInt as i32 with size in bytes (value, size)
|
||||
async fn read_varint_size(&mut self) -> Result<(i32, usize), ProtocolError> {
|
||||
let mut value: u32 = 0;
|
||||
let mut position: u32 = 0;
|
||||
let mut size = 0;
|
||||
|
||||
loop {
|
||||
let byte = self.read_byte().await?;
|
||||
value |= TryInto::<u32>::try_into(byte & 0x7F).map_err(|_| ProtocolError::VarIntError)? << position;
|
||||
|
||||
size += 1;
|
||||
|
||||
if (byte & 0x80) == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
position += 7;
|
||||
}
|
||||
|
||||
Ok((value as i32, size))
|
||||
}
|
||||
/// Read VarLong as i64 with size in bytes (value, size)
|
||||
async fn read_varlong_size(&mut self) -> Result<(i64, usize), ProtocolError> {
|
||||
let mut value: u64 = 0;
|
||||
let mut position: u32 = 0;
|
||||
let mut size = 0;
|
||||
|
||||
loop {
|
||||
let byte = self.read_byte().await?;
|
||||
value |= TryInto::<u64>::try_into(byte & 0x7F).map_err(|_| ProtocolError::VarIntError)? << position;
|
||||
|
||||
size += 1;
|
||||
|
||||
if (byte & 0x80) == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
position += 7;
|
||||
}
|
||||
|
||||
Ok((value as i64, size))
|
||||
}
|
||||
|
||||
/// Read VarInt as i32
|
||||
async fn read_varint(&mut self) -> Result<i32, ProtocolError> {
|
||||
self.read_varint_size().await.map(|o| o.0)
|
||||
}
|
||||
/// Read VarLong as i64
|
||||
async fn read_varlong(&mut self) -> Result<i64, ProtocolError> {
|
||||
self.read_varlong_size().await.map(|o| o.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,70 +0,0 @@
|
||||
macro_rules! size_varint {
|
||||
($type:ty, $self:expr) => {{
|
||||
let mut shift: $type = 0;
|
||||
let mut decoded: $type = 0;
|
||||
let mut size: usize = 0;
|
||||
|
||||
loop {
|
||||
let next = DataReader::read_byte($self).await?;
|
||||
size += 1;
|
||||
|
||||
if shift >= (std::mem::size_of::<$type>() * 8) as $type {
|
||||
return Err(ProtocolError::VarIntError);
|
||||
}
|
||||
|
||||
decoded |= ((next & 0b01111111) as $type) << shift;
|
||||
|
||||
if next & 0b10000000 == 0b10000000 {
|
||||
shift += 7;
|
||||
} else {
|
||||
return Ok((decoded, size));
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! read_varint {
|
||||
($type:ty, $self:expr) => {{
|
||||
let mut shift: $type = 0;
|
||||
let mut decoded: $type = 0;
|
||||
|
||||
loop {
|
||||
let next = DataReader::read_byte($self).await?;
|
||||
|
||||
if shift >= (std::mem::size_of::<$type>() * 8) as $type {
|
||||
return Err(ProtocolError::VarIntError);
|
||||
}
|
||||
|
||||
decoded |= ((next & 0b01111111) as $type) << shift;
|
||||
|
||||
if next & 0b10000000 == 0b10000000 {
|
||||
shift += 7;
|
||||
} else {
|
||||
return Ok(decoded);
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! write_varint {
|
||||
($type:ty, $self:expr, $value:expr) => {{
|
||||
let mut value: $type = $value;
|
||||
|
||||
if value == 0 {
|
||||
DataWriter::write_byte($self, 0).await
|
||||
} else {
|
||||
while value >= 0b10000000 {
|
||||
let next: u8 = ((value & 0b01111111) as u8) | 0b10000000;
|
||||
value >>= 7;
|
||||
|
||||
DataWriter::write_byte($self, next).await?;
|
||||
}
|
||||
|
||||
DataWriter::write_byte($self, (value & 0b01111111) as u8).await
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub(crate) use read_varint;
|
||||
pub(crate) use size_varint;
|
||||
pub(crate) use write_varint;
|
@ -1,4 +1,4 @@
|
||||
use crate::{data::varint::write_varint, zigzag::Zigzag, ProtocolError};
|
||||
use crate::ProtocolError;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use uuid::Uuid;
|
||||
|
||||
@ -25,81 +25,156 @@ pub trait DataWriter {
|
||||
}
|
||||
/// Write Unsigned Short as u16
|
||||
fn write_unsigned_short(&mut self, val: u16) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await }
|
||||
}
|
||||
/// Write Boolean
|
||||
fn write_boolean(&mut self, val: bool) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_byte(if val { 0x01 } else { 0x00 }).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_byte(if val { 0x01 } else { 0x00 }).await }
|
||||
}
|
||||
/// Write Short as i16
|
||||
fn write_short(&mut self, val: i16) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await }
|
||||
}
|
||||
/// Write Long as i64
|
||||
fn write_long(&mut self, val: i64) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await }
|
||||
}
|
||||
/// Write Float as f32
|
||||
fn write_float(&mut self, val: f32) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await }
|
||||
}
|
||||
/// Write Double as f64
|
||||
fn write_double(&mut self, val: f64) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await }
|
||||
}
|
||||
/// Write Int as i32
|
||||
fn write_int(&mut self, val: i32) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await.map_err(|_| ProtocolError::UnsignedShortError) }
|
||||
async move { self.write_bytes(&val.to_be_bytes()).await }
|
||||
}
|
||||
|
||||
/// Write VarInt as usize
|
||||
fn write_usize_varint(&mut self, val: usize) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { write_varint!(usize, self, val) }
|
||||
}
|
||||
/// Write VarInt as u8
|
||||
fn write_u8_varint(&mut self, val: u8) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { write_varint!(u8, self, val) }
|
||||
/// Write VarInt as u8
|
||||
async fn write_u8_varint(&mut self, val: u8) -> Result<(), ProtocolError> {
|
||||
self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarInt as u16
|
||||
fn write_u16_varint(&mut self, val: u16) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { write_varint!(u16, self, val) }
|
||||
async fn write_u16_varint(&mut self, val: u16) -> Result<(), ProtocolError> {
|
||||
self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarInt as usize
|
||||
///
|
||||
/// Returns error if the value is greater than i32::MAX
|
||||
async fn write_usize_varint(&mut self, val: usize) -> Result<(), ProtocolError> {
|
||||
let val = val.try_into().map_err(|_| ProtocolError::VarIntError)?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
self.write_varint(val).await
|
||||
}
|
||||
/// Write VarInt as u32
|
||||
fn write_u32_varint(&mut self, val: u32) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { write_varint!(u32, self, val) }
|
||||
}
|
||||
/// Write VarInt as u64
|
||||
fn write_u64_varint(&mut self, val: u64) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { write_varint!(u64, self, val) }
|
||||
}
|
||||
/// Write VarInt as u128
|
||||
fn write_u128_varint(&mut self, val: u128) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { write_varint!(u128, self, val) }
|
||||
}
|
||||
|
||||
/// Write VarInt as isize
|
||||
fn write_isize_varint(&mut self, val: isize) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_usize_varint(val.zigzag()).await }
|
||||
///
|
||||
/// Returns error if the value is greater than i32::MAX
|
||||
async fn write_u32_varint(&mut self, val: u32) -> Result<(), ProtocolError> {
|
||||
let val = val.try_into().map_err(|_| ProtocolError::VarIntError)?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
self.write_varint(val).await
|
||||
}
|
||||
/// Write VarInt as i8
|
||||
fn write_i8_varint(&mut self, val: i8) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_u8_varint(val.zigzag()).await }
|
||||
async fn write_i8_varint(&mut self, val: i8) -> Result<(), ProtocolError> {
|
||||
self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarInt as i16
|
||||
fn write_i16_varint(&mut self, val: i16) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_u16_varint(val.zigzag()).await }
|
||||
async fn write_i16_varint(&mut self, val: i16) -> Result<(), ProtocolError> {
|
||||
self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarInt as isize
|
||||
async fn write_isize_varint(&mut self, val: isize) -> Result<(), ProtocolError> {
|
||||
self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarInt as i32
|
||||
fn write_i32_varint(&mut self, val: i32) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_u32_varint(val.zigzag()).await }
|
||||
///
|
||||
/// *Use [write_varint](DataWriter::write_varint) instead*
|
||||
async fn write_i32_varint(&mut self, val: i32) -> Result<(), ProtocolError> {
|
||||
self.write_varint(val).await
|
||||
}
|
||||
/// Write VarInt as i64
|
||||
fn write_i64_varint(&mut self, val: i64) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_u64_varint(val.zigzag()).await }
|
||||
|
||||
/// Write VarLong as u8
|
||||
async fn write_u8_varlong(&mut self, val: u8) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarInt as i128
|
||||
fn write_i128_varint(&mut self, val: i128) -> impl Future<Output = Result<(), ProtocolError>> {
|
||||
async move { self.write_u128_varint(val.zigzag()).await }
|
||||
/// Write VarLong as u16
|
||||
async fn write_u16_varlong(&mut self, val: u16) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarLong as u32
|
||||
async fn write_u32_varlong(&mut self, val: u32) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarLong as u64
|
||||
///
|
||||
/// Returns error if the value is greater than i64::MAX
|
||||
async fn write_u64_varlong(&mut self, val: u64) -> Result<(), ProtocolError> {
|
||||
let val = val.try_into().map_err(|_| ProtocolError::VarIntError)?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
self.write_varlong(val).await
|
||||
}
|
||||
/// Write VarLong as usize
|
||||
///
|
||||
/// Returns error if the value is greater than i64::MAX
|
||||
async fn write_usize_varlong(&mut self, val: u64) -> Result<(), ProtocolError> {
|
||||
let val = val.try_into().map_err(|_| ProtocolError::VarIntError)?;
|
||||
if val < 0 { return Err(ProtocolError::VarIntError); }
|
||||
self.write_varlong(val).await
|
||||
}
|
||||
/// Write VarLong as i8
|
||||
async fn write_i8_varlong(&mut self, val: i8) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarLong as i16
|
||||
async fn write_i16_varlong(&mut self, val: i16) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarLong as i32
|
||||
async fn write_i32_varlong(&mut self, val: i32) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?).await
|
||||
}
|
||||
/// Write VarLong as i64
|
||||
///
|
||||
/// *Use [write_varlong](DataWriter::write_varlong) instead*
|
||||
async fn write_i64_varlong(&mut self, val: i64) -> Result<(), ProtocolError> {
|
||||
self.write_varlong(val).await
|
||||
}
|
||||
|
||||
/// Write VarInt as i32
|
||||
async fn write_varint(&mut self, val: i32) -> Result<(), ProtocolError> {
|
||||
let mut value = val as u32;
|
||||
|
||||
loop {
|
||||
if value & !0x7F == 0 {
|
||||
self.write_byte(TryInto::<u8>::try_into(value).map_err(|_| ProtocolError::VarIntError)?).await?;
|
||||
break;
|
||||
}
|
||||
|
||||
self.write_byte(TryInto::<u8>::try_into((value & 0x7F) | 0x80).map_err(|_| ProtocolError::VarIntError)?).await?;
|
||||
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
/// Write VarLong as i64
|
||||
async fn write_varlong(&mut self, val: i64) -> Result<(), ProtocolError> {
|
||||
let mut value = val as u64;
|
||||
|
||||
loop {
|
||||
if value & !0x7F == 0 {
|
||||
self.write_byte(TryInto::<u8>::try_into(value).map_err(|_| ProtocolError::VarIntError)?).await?;
|
||||
break;
|
||||
}
|
||||
|
||||
self.write_byte(TryInto::<u8>::try_into((value & 0x7F) | 0x80).map_err(|_| ProtocolError::VarIntError)?).await?;
|
||||
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
32
src/lib.rs
32
src/lib.rs
@ -3,7 +3,6 @@ mod tests;
|
||||
|
||||
pub mod data;
|
||||
pub mod packet;
|
||||
pub mod zigzag;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{DataReader, DataWriter};
|
||||
@ -31,7 +30,6 @@ pub enum ProtocolError {
|
||||
ReadError,
|
||||
WriteError,
|
||||
ZlibError,
|
||||
UnsignedShortError,
|
||||
CloneError,
|
||||
ConnectionClosedError
|
||||
}
|
||||
@ -48,8 +46,7 @@ impl Error for ProtocolError {}
|
||||
pub struct MinecraftConnection<T: AsyncReadExt + AsyncWriteExt + Unpin> {
|
||||
stream: T,
|
||||
compression: Option<usize>,
|
||||
compression_type: u32,
|
||||
is_alive: bool,
|
||||
compression_type: u32
|
||||
}
|
||||
|
||||
impl MinecraftConnection<TcpStream> {
|
||||
@ -69,7 +66,6 @@ impl MinecraftConnection<TcpStream> {
|
||||
Ok(MinecraftConnection {
|
||||
stream,
|
||||
compression: None,
|
||||
is_alive: true,
|
||||
compression_type: 1,
|
||||
})
|
||||
}
|
||||
@ -77,7 +73,6 @@ impl MinecraftConnection<TcpStream> {
|
||||
/// Close TcpStream
|
||||
pub async fn close(&mut self) {
|
||||
let _ = self.stream.shutdown().await;
|
||||
self.is_alive = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,22 +98,11 @@ impl<T: AsyncReadExt + AsyncWriteExt + Unpin> MinecraftConnection<T> {
|
||||
MinecraftConnection {
|
||||
stream,
|
||||
compression: None,
|
||||
is_alive: true,
|
||||
compression_type: 1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set alive state
|
||||
fn set_alive(&mut self, state: bool) {
|
||||
self.is_alive = state;
|
||||
}
|
||||
|
||||
/// Is connection alive
|
||||
pub fn is_alive(&self) -> bool {
|
||||
self.is_alive
|
||||
}
|
||||
|
||||
/// Set compression threshold
|
||||
/// Set compression threshold
|
||||
pub fn set_compression(&mut self, threshold: Option<usize>) {
|
||||
self.compression = threshold;
|
||||
}
|
||||
@ -158,13 +142,8 @@ impl<T: AsyncReadExt + AsyncWriteExt + Unpin> MinecraftConnection<T> {
|
||||
|
||||
/// Read [`Packet`](Packet) from connection
|
||||
pub async fn read_packet(&mut self) -> Result<Packet, ProtocolError> {
|
||||
if !self.is_alive() {
|
||||
return Err(ProtocolError::ConnectionClosedError);
|
||||
}
|
||||
|
||||
match read_packet(&mut self.stream, self.compression).await {
|
||||
Err(ProtocolError::ConnectionClosedError) => {
|
||||
self.set_alive(false);
|
||||
Err(ProtocolError::ConnectionClosedError)
|
||||
},
|
||||
i => i
|
||||
@ -173,10 +152,6 @@ impl<T: AsyncReadExt + AsyncWriteExt + Unpin> MinecraftConnection<T> {
|
||||
|
||||
/// Write [`Packet`](Packet) to connection
|
||||
pub async fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> {
|
||||
if !self.is_alive() {
|
||||
return Err(ProtocolError::ConnectionClosedError);
|
||||
}
|
||||
|
||||
write_packet(&mut self.stream, self.compression, self.compression_type, packet).await
|
||||
}
|
||||
}
|
||||
@ -186,8 +161,7 @@ impl<T: AsyncReadExt + AsyncWriteExt + Unpin + Clone> MinecraftConnection<T> {
|
||||
pub fn clone(&mut self) -> MinecraftConnection<T> {
|
||||
MinecraftConnection {
|
||||
stream: self.stream.clone(),
|
||||
compression: self.compression.clone(),
|
||||
is_alive: self.is_alive.clone(),
|
||||
compression: self.compression,
|
||||
compression_type: self.compression_type,
|
||||
}
|
||||
}
|
||||
|
45
src/tests.rs
45
src/tests.rs
@ -4,6 +4,51 @@ use std::io::Cursor;
|
||||
|
||||
use crate::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_varint() -> Result<(), ProtocolError> {
|
||||
let mut src = Packet::empty(0x00);
|
||||
|
||||
src.write_u8_varint(0).await?; // 0x00
|
||||
src.write_u8_varint(1).await?; // 0x01
|
||||
src.write_u8_varint(2).await?; // 0x02
|
||||
src.write_u8_varint(127).await?; // 0x7f
|
||||
src.write_u8_varint(128).await?; // 0x80 0x01
|
||||
src.write_u16_varint(255).await?; // 0xff 0x01
|
||||
src.write_u16_varint(25565).await?; // 0xdd 0xc7 0x01
|
||||
src.write_u32_varint(2097151).await?; // 0xff 0xff 0x7f
|
||||
src.write_u32_varint(2147483647).await?; // 0xff 0xff 0xff 0xff 0x07
|
||||
src.write_i8_varint(-1).await?; // 0xff 0xff 0xff 0xff 0x0f
|
||||
src.write_i32_varint(-2147483648).await?; // 0x80 0x80 0x80 0x80 0x08
|
||||
|
||||
let mut packet = Packet::from_bytes(0x00, src.get_bytes());
|
||||
assert_eq!(packet.read_u8_varint().await?, 0);
|
||||
assert_eq!(packet.read_u8_varint().await?, 1);
|
||||
assert_eq!(packet.read_u8_varint().await?, 2);
|
||||
assert_eq!(packet.read_u8_varint().await?, 127);
|
||||
assert_eq!(packet.read_u8_varint().await?, 128);
|
||||
assert_eq!(packet.read_u16_varint().await?, 255);
|
||||
assert_eq!(packet.read_u16_varint().await?, 25565);
|
||||
assert_eq!(packet.read_u32_varint().await?, 2097151);
|
||||
assert_eq!(packet.read_u32_varint().await?, 2147483647);
|
||||
assert_eq!(packet.read_i8_varint().await?, -1);
|
||||
assert_eq!(packet.read_i32_varint().await?, -2147483648);
|
||||
|
||||
let mut packet = Packet::from_bytes(0x00, src.get_bytes());
|
||||
assert_eq!(packet.read_bytes(1).await?, vec![0x00]); // 0
|
||||
assert_eq!(packet.read_bytes(1).await?, vec![0x01]); // 1
|
||||
assert_eq!(packet.read_bytes(1).await?, vec![0x02]); // 2
|
||||
assert_eq!(packet.read_bytes(1).await?, vec![0x7f]); // 127
|
||||
assert_eq!(packet.read_bytes(2).await?, vec![0x80, 0x01]); // 128
|
||||
assert_eq!(packet.read_bytes(2).await?, vec![0xff, 0x01]); // 255
|
||||
assert_eq!(packet.read_bytes(3).await?, vec![0xdd, 0xc7, 0x01]); // 25565
|
||||
assert_eq!(packet.read_bytes(3).await?, vec![0xff, 0xff, 0x7f]); // 2097151
|
||||
assert_eq!(packet.read_bytes(5).await?, vec![0xff, 0xff, 0xff, 0xff, 0x07]); // 2147483647
|
||||
assert_eq!(packet.read_bytes(5).await?, vec![0xff, 0xff, 0xff, 0xff, 0x0f]); // -1
|
||||
assert_eq!(packet.read_bytes(5).await?, vec![0x80, 0x80, 0x80, 0x80, 0x08]); // -2147483648
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_data_transfer() -> Result<(), ProtocolError> {
|
||||
|
||||
|
@ -1,65 +0,0 @@
|
||||
//! VarInt reading helper
|
||||
|
||||
pub trait Zigzag<T> {
|
||||
fn zigzag(&self) -> T;
|
||||
}
|
||||
impl Zigzag<u8> for i8 {
|
||||
fn zigzag(&self) -> u8 {
|
||||
((self << 1) ^ (self >> 7)) as u8
|
||||
}
|
||||
}
|
||||
impl Zigzag<i8> for u8 {
|
||||
fn zigzag(&self) -> i8 {
|
||||
((self >> 1) as i8) ^ (-((self & 1) as i8))
|
||||
}
|
||||
}
|
||||
impl Zigzag<u16> for i16 {
|
||||
fn zigzag(&self) -> u16 {
|
||||
((self << 1) ^ (self >> 15)) as u16
|
||||
}
|
||||
}
|
||||
impl Zigzag<i16> for u16 {
|
||||
fn zigzag(&self) -> i16 {
|
||||
((self >> 1) as i16) ^ (-((self & 1) as i16))
|
||||
}
|
||||
}
|
||||
impl Zigzag<u32> for i32 {
|
||||
fn zigzag(&self) -> u32 {
|
||||
((self << 1) ^ (self >> 31)) as u32
|
||||
}
|
||||
}
|
||||
impl Zigzag<i32> for u32 {
|
||||
fn zigzag(&self) -> i32 {
|
||||
((self >> 1) as i32) ^ (-((self & 1) as i32))
|
||||
}
|
||||
}
|
||||
impl Zigzag<u64> for i64 {
|
||||
fn zigzag(&self) -> u64 {
|
||||
((self << 1) ^ (self >> 63)) as u64
|
||||
}
|
||||
}
|
||||
impl Zigzag<i64> for u64 {
|
||||
fn zigzag(&self) -> i64 {
|
||||
((self >> 1) as i64) ^ (-((self & 1) as i64))
|
||||
}
|
||||
}
|
||||
impl Zigzag<u128> for i128 {
|
||||
fn zigzag(&self) -> u128 {
|
||||
((self << 1) ^ (self >> 127)) as u128
|
||||
}
|
||||
}
|
||||
impl Zigzag<i128> for u128 {
|
||||
fn zigzag(&self) -> i128 {
|
||||
((self >> 1) as i128) ^ (-((self & 1) as i128))
|
||||
}
|
||||
}
|
||||
impl Zigzag<usize> for isize {
|
||||
fn zigzag(&self) -> usize {
|
||||
((self << 1) ^ (self >> std::mem::size_of::<usize>() - 1)) as usize
|
||||
}
|
||||
}
|
||||
impl Zigzag<isize> for usize {
|
||||
fn zigzag(&self) -> isize {
|
||||
((self >> 1) as isize) ^ (-((self & 1) as isize))
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user