remove zigzag add varint test replace read_varint macro with size_varint some rewrite varint reading
This commit is contained in:
parent
3a381d3504
commit
f8196d036c
@ -12,8 +12,4 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flate2 = "1.1.1"
|
flate2 = "1.1.1"
|
||||||
uuid = "1.16.0"
|
uuid = "1.16.0"
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["atomic_clone"]
|
|
||||||
atomic_clone = []
|
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
data::varint::{read_varint, size_varint},
|
data::varint::read_varint,
|
||||||
zigzag::Zigzag,
|
|
||||||
ProtocolError,
|
ProtocolError,
|
||||||
};
|
};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
@ -25,174 +24,149 @@ pub trait DataReader {
|
|||||||
}
|
}
|
||||||
/// Read Unsigned Short as u16
|
/// Read Unsigned Short as u16
|
||||||
fn read_unsigned_short(&mut self) -> Result<u16, ProtocolError> {
|
fn read_unsigned_short(&mut self) -> Result<u16, ProtocolError> {
|
||||||
match self.read_bytes(2)?.try_into() {
|
self.read_bytes(2)
|
||||||
Ok(i) => Ok(u16::from_be_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| u16::from_be_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Read Boolean
|
/// Read Boolean
|
||||||
fn read_boolean(&mut self) -> Result<bool, ProtocolError> {
|
fn read_boolean(&mut self) -> Result<bool, ProtocolError> {
|
||||||
Ok(self.read_byte()? == 0x01)
|
self.read_byte().map(|o| o == 0x01)
|
||||||
}
|
}
|
||||||
/// Read Short as i16
|
/// Read Short as i16
|
||||||
fn read_short(&mut self) -> Result<i16, ProtocolError> {
|
fn read_short(&mut self) -> Result<i16, ProtocolError> {
|
||||||
match self.read_bytes(2)?.try_into() {
|
self.read_bytes(2)
|
||||||
Ok(i) => Ok(i16::from_be_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| i16::from_be_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Read Long as i64
|
/// Read Long as i64
|
||||||
fn read_long(&mut self) -> Result<i64, ProtocolError> {
|
fn read_long(&mut self) -> Result<i64, ProtocolError> {
|
||||||
match self.read_bytes(8)?.try_into() {
|
self.read_bytes(8)
|
||||||
Ok(i) => Ok(i64::from_be_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| i64::from_be_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Read Float as f32
|
/// Read Float as f32
|
||||||
fn read_float(&mut self) -> Result<f32, ProtocolError> {
|
fn read_float(&mut self) -> Result<f32, ProtocolError> {
|
||||||
match self.read_bytes(4)?.try_into() {
|
self.read_bytes(4)
|
||||||
Ok(i) => Ok(f32::from_be_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| f32::from_be_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Read Double as f64
|
/// Read Double as f64
|
||||||
fn read_double(&mut self) -> Result<f64, ProtocolError> {
|
fn read_double(&mut self) -> Result<f64, ProtocolError> {
|
||||||
match self.read_bytes(8)?.try_into() {
|
self.read_bytes(8)
|
||||||
Ok(i) => Ok(f64::from_be_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| f64::from_be_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Read Int as i32
|
/// Read Int as i32
|
||||||
fn read_int(&mut self) -> Result<i32, ProtocolError> {
|
fn read_int(&mut self) -> Result<i32, ProtocolError> {
|
||||||
match self.read_bytes(4)?.try_into() {
|
self.read_bytes(4)
|
||||||
Ok(i) => Ok(i32::from_be_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| i32::from_be_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Read UUID
|
/// Read UUID
|
||||||
fn read_uuid(&mut self) -> Result<Uuid, ProtocolError> {
|
fn read_uuid(&mut self) -> Result<Uuid, ProtocolError> {
|
||||||
match self.read_bytes(16)?.try_into() {
|
self.read_bytes(16)
|
||||||
Ok(i) => Ok(Uuid::from_bytes(i)),
|
.and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError))
|
||||||
Err(_) => Err(ProtocolError::ReadError),
|
.map(|o| Uuid::from_bytes(o))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read VarInt as usize with size in bytes (varint, size)
|
/// Read VarInt as usize with size in bytes (varint, size)
|
||||||
fn read_usize_varint_size(&mut self) -> Result<(usize, usize), ProtocolError> {
|
fn read_usize_varint_size(&mut self) -> Result<(usize, usize), ProtocolError> {
|
||||||
size_varint!(usize, self)
|
read_varint!(usize, self)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u8 with size in bytes (varint, size)
|
/// Read VarInt as u8 with size in bytes (varint, size)
|
||||||
fn read_u8_varint_size(&mut self) -> Result<(u8, usize), ProtocolError> {
|
fn read_u8_varint_size(&mut self) -> Result<(u8, usize), ProtocolError> {
|
||||||
size_varint!(u8, self)
|
read_varint!(u8, self)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u16 with size in bytes (varint, size)
|
/// Read VarInt as u16 with size in bytes (varint, size)
|
||||||
fn read_u16_varint_size(&mut self) -> Result<(u16, usize), ProtocolError> {
|
fn read_u16_varint_size(&mut self) -> Result<(u16, usize), ProtocolError> {
|
||||||
size_varint!(u16, self)
|
read_varint!(u16, self)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u32 with size in bytes (varint, size)
|
/// Read VarInt as u32 with size in bytes (varint, size)
|
||||||
fn read_u32_varint_size(&mut self) -> Result<(u32, usize), ProtocolError> {
|
fn read_u32_varint_size(&mut self) -> Result<(u32, usize), ProtocolError> {
|
||||||
size_varint!(u32, self)
|
read_varint!(u32, self)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u64 with size in bytes (varint, size)
|
/// Read VarInt as u64 with size in bytes (varint, size)
|
||||||
fn read_u64_varint_size(&mut self) -> Result<(u64, usize), ProtocolError> {
|
fn read_u64_varint_size(&mut self) -> Result<(u64, usize), ProtocolError> {
|
||||||
size_varint!(u64, self)
|
read_varint!(u64, self)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u128 with size in bytes (varint, size)
|
/// Read VarInt as u128 with size in bytes (varint, size)
|
||||||
fn read_u128_varint_size(&mut self) -> Result<(u128, usize), ProtocolError> {
|
fn read_u128_varint_size(&mut self) -> Result<(u128, usize), ProtocolError> {
|
||||||
size_varint!(u128, self)
|
read_varint!(u128, self)
|
||||||
}
|
|
||||||
|
|
||||||
/// Read VarInt as isize with size in bytes (varint, size)
|
|
||||||
fn read_isize_varint_size(&mut self) -> Result<(isize, usize), ProtocolError> {
|
|
||||||
Ok({
|
|
||||||
let i = self.read_usize_varint_size()?;
|
|
||||||
(i.0.zigzag(), i.1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/// Read VarInt as i8 with size in bytes (varint, size)
|
|
||||||
fn read_i8_varint_size(&mut self) -> Result<(i8, usize), ProtocolError> {
|
|
||||||
Ok({
|
|
||||||
let i = self.read_u8_varint_size()?;
|
|
||||||
(i.0.zigzag(), i.1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/// Read VarInt as i16 with size in bytes (varint, size)
|
|
||||||
fn read_i16_varint_size(&mut self) -> Result<(i16, usize), ProtocolError> {
|
|
||||||
Ok({
|
|
||||||
let i = self.read_u16_varint_size()?;
|
|
||||||
(i.0.zigzag(), i.1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/// Read VarInt as i32 with size in bytes (varint, size)
|
|
||||||
fn read_i32_varint_size(&mut self) -> Result<(i32, usize), ProtocolError> {
|
|
||||||
Ok({
|
|
||||||
let i = self.read_u32_varint_size()?;
|
|
||||||
(i.0.zigzag(), i.1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/// Read VarInt as i64 with size in bytes (varint, size)
|
|
||||||
fn read_i64_varint_size(&mut self) -> Result<(i64, usize), ProtocolError> {
|
|
||||||
Ok({
|
|
||||||
let i = self.read_u64_varint_size()?;
|
|
||||||
(i.0.zigzag(), i.1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/// Read VarInt as i128 with size in bytes (varint, size)
|
|
||||||
fn read_i128_varint_size(&mut self) -> Result<(i128, usize), ProtocolError> {
|
|
||||||
Ok({
|
|
||||||
let i = self.read_u128_varint_size()?;
|
|
||||||
(i.0.zigzag(), i.1)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read VarInt as usize
|
/// Read VarInt as usize
|
||||||
fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> {
|
fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> {
|
||||||
read_varint!(usize, self)
|
self.read_usize_varint_size().map(|o| o.0)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u8
|
/// Read VarInt as u8
|
||||||
fn read_u8_varint(&mut self) -> Result<u8, ProtocolError> {
|
fn read_u8_varint(&mut self) -> Result<u8, ProtocolError> {
|
||||||
read_varint!(u8, self)
|
self.read_u8_varint_size().map(|o| o.0)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u16
|
/// Read VarInt as u16
|
||||||
fn read_u16_varint(&mut self) -> Result<u16, ProtocolError> {
|
fn read_u16_varint(&mut self) -> Result<u16, ProtocolError> {
|
||||||
read_varint!(u16, self)
|
self.read_u16_varint_size().map(|o| o.0)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u32
|
/// Read VarInt as u32
|
||||||
fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> {
|
fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> {
|
||||||
read_varint!(u32, self)
|
self.read_u32_varint_size().map(|o| o.0)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u64
|
/// Read VarInt as u64
|
||||||
fn read_u64_varint(&mut self) -> Result<u64, ProtocolError> {
|
fn read_u64_varint(&mut self) -> Result<u64, ProtocolError> {
|
||||||
read_varint!(u64, self)
|
self.read_u64_varint_size().map(|o| o.0)
|
||||||
}
|
}
|
||||||
/// Read VarInt as u128
|
/// Read VarInt as u128
|
||||||
fn read_u128_varint(&mut self) -> Result<u128, ProtocolError> {
|
fn read_u128_varint(&mut self) -> Result<u128, ProtocolError> {
|
||||||
read_varint!(u128, self)
|
self.read_u128_varint_size().map(|o| o.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read VarInt as isize
|
/// Read VarInt as usize with zigzag
|
||||||
fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> {
|
fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> {
|
||||||
Ok(self.read_usize_varint()?.zigzag())
|
self.read_usize_varint().map(|o| o as isize)
|
||||||
}
|
}
|
||||||
/// Read VarInt as i8
|
/// Read VarInt as u8 with zigzag
|
||||||
fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> {
|
fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> {
|
||||||
Ok(self.read_u8_varint()?.zigzag())
|
self.read_u8_varint().map(|o| o as i8)
|
||||||
}
|
}
|
||||||
/// Read VarInt as i16
|
/// Read VarInt as u16 with zigzag
|
||||||
fn read_i16_varint(&mut self) -> Result<i16, ProtocolError> {
|
fn read_i16_varint(&mut self) -> Result<i16, ProtocolError> {
|
||||||
Ok(self.read_u16_varint()?.zigzag())
|
self.read_u16_varint().map(|o| o as i16)
|
||||||
}
|
}
|
||||||
/// Read VarInt as i32
|
/// Read VarInt as u32 with zigzag
|
||||||
fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> {
|
fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> {
|
||||||
Ok(self.read_u32_varint()?.zigzag())
|
self.read_u32_varint().map(|o| o as i32)
|
||||||
}
|
}
|
||||||
/// Read VarInt as i64
|
/// Read VarInt as u64 with zigzag
|
||||||
fn read_i64_varint(&mut self) -> Result<i64, ProtocolError> {
|
fn read_i64_varint(&mut self) -> Result<i64, ProtocolError> {
|
||||||
Ok(self.read_u64_varint()?.zigzag())
|
self.read_u64_varint().map(|o| o as i64)
|
||||||
}
|
}
|
||||||
/// Read VarInt as i128
|
/// Read VarInt as u128 with zigzag
|
||||||
fn read_i128_varint(&mut self) -> Result<i128, ProtocolError> {
|
fn read_i128_varint(&mut self) -> Result<i128, ProtocolError> {
|
||||||
Ok(self.read_u128_varint()?.zigzag())
|
self.read_u128_varint().map(|o| o as i128)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read VarInt as usize with zigzag with size in bytes (varint, size)
|
||||||
|
fn read_isize_varint_size(&mut self) -> Result<(isize, usize), ProtocolError> {
|
||||||
|
self.read_usize_varint_size().map(|o| (o.0 as isize, o.1))
|
||||||
|
}
|
||||||
|
/// Read VarInt as u8 with zigzag with size in bytes (varint, size)
|
||||||
|
fn read_i8_varint_size(&mut self) -> Result<(i8, usize), ProtocolError> {
|
||||||
|
self.read_u8_varint_size().map(|o| (o.0 as i8, o.1))
|
||||||
|
}
|
||||||
|
/// Read VarInt as u16 with zigzag with size in bytes (varint, size)
|
||||||
|
fn read_i16_varint_size(&mut self) -> Result<(i16, usize), ProtocolError> {
|
||||||
|
self.read_u16_varint_size().map(|o| (o.0 as i16, o.1))
|
||||||
|
}
|
||||||
|
/// Read VarInt as u32 with zigzag with size in bytes (varint, size)
|
||||||
|
fn read_i32_varint_size(&mut self) -> Result<(i32, usize), ProtocolError> {
|
||||||
|
self.read_u32_varint_size().map(|o| (o.0 as i32, o.1))
|
||||||
|
}
|
||||||
|
/// Read VarInt as u64 with zigzag with size in bytes (varint, size)
|
||||||
|
fn read_i64_varint_size(&mut self) -> Result<(i64, usize), ProtocolError> {
|
||||||
|
self.read_u64_varint_size().map(|o| (o.0 as i64, o.1))
|
||||||
|
}
|
||||||
|
/// Read VarInt as u128 with zigzag with size in bytes (varint, size)
|
||||||
|
fn read_i128_varint_size(&mut self) -> Result<(i128, usize), ProtocolError> {
|
||||||
|
self.read_u128_varint_size().map(|o| (o.0 as i128, o.1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
macro_rules! size_varint {
|
macro_rules! read_varint {
|
||||||
($type:ty, $self:expr) => {{
|
($type:ty, $self:expr) => {{
|
||||||
let mut shift: $type = 0;
|
let mut shift: $type = 0;
|
||||||
let mut decoded: $type = 0;
|
let mut decoded: $type = 0;
|
||||||
@ -12,9 +12,9 @@ macro_rules! size_varint {
|
|||||||
return Err(ProtocolError::VarIntError);
|
return Err(ProtocolError::VarIntError);
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded |= ((next & 0b01111111) as $type) << shift;
|
decoded |= ((next & 0x7F) as $type) << shift;
|
||||||
|
|
||||||
if next & 0b10000000 == 0b10000000 {
|
if next & 0x80 == 0x80 {
|
||||||
shift += 7;
|
shift += 7;
|
||||||
} else {
|
} else {
|
||||||
return Ok((decoded, size));
|
return Ok((decoded, size));
|
||||||
@ -23,29 +23,6 @@ macro_rules! size_varint {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
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)?;
|
|
||||||
|
|
||||||
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 {
|
macro_rules! write_varint {
|
||||||
($type:ty, $self:expr, $value:expr) => {{
|
($type:ty, $self:expr, $value:expr) => {{
|
||||||
let mut value: $type = $value;
|
let mut value: $type = $value;
|
||||||
@ -53,18 +30,15 @@ macro_rules! write_varint {
|
|||||||
if value == 0 {
|
if value == 0 {
|
||||||
DataWriter::write_byte($self, 0)
|
DataWriter::write_byte($self, 0)
|
||||||
} else {
|
} else {
|
||||||
while value >= 0b10000000 {
|
while value >= 0x80 {
|
||||||
let next: u8 = ((value & 0b01111111) as u8) | 0b10000000;
|
DataWriter::write_byte($self, ((value & 0x7F) as u8) | 0x80)?;
|
||||||
value >>= 7;
|
value >>= 7;
|
||||||
|
|
||||||
DataWriter::write_byte($self, next)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataWriter::write_byte($self, (value & 0b01111111) as u8)
|
DataWriter::write_byte($self, (value & 0x7F) as u8)
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use read_varint;
|
pub(crate) use read_varint;
|
||||||
pub(crate) use size_varint;
|
|
||||||
pub(crate) use write_varint;
|
pub(crate) use write_varint;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{data::varint::write_varint, zigzag::Zigzag, ProtocolError};
|
use crate::{data::varint::write_varint, ProtocolError};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@ -23,52 +23,31 @@ pub trait DataWriter {
|
|||||||
}
|
}
|
||||||
/// Write Unsigned Short as u16
|
/// Write Unsigned Short as u16
|
||||||
fn write_unsigned_short(&mut self, val: u16) -> Result<(), ProtocolError> {
|
fn write_unsigned_short(&mut self, val: u16) -> Result<(), ProtocolError> {
|
||||||
match self.write_bytes(&val.to_be_bytes()) {
|
self.write_bytes(&val.to_be_bytes())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Write Boolean
|
/// Write Boolean
|
||||||
fn write_boolean(&mut self, val: bool) -> Result<(), ProtocolError> {
|
fn write_boolean(&mut self, val: bool) -> Result<(), ProtocolError> {
|
||||||
match self.write_byte(if val { 0x01 } else { 0x00 }) {
|
self.write_byte(if val { 0x01 } else { 0x00 })
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Write Short as i16
|
/// Write Short as i16
|
||||||
fn write_short(&mut self, val: i16) -> Result<(), ProtocolError> {
|
fn write_short(&mut self, val: i16) -> Result<(), ProtocolError> {
|
||||||
match self.write_bytes(&val.to_be_bytes()) {
|
self.write_bytes(&val.to_be_bytes())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Write Long as i64
|
/// Write Long as i64
|
||||||
fn write_long(&mut self, val: i64) -> Result<(), ProtocolError> {
|
fn write_long(&mut self, val: i64) -> Result<(), ProtocolError> {
|
||||||
match self.write_bytes(&val.to_be_bytes()) {
|
self.write_bytes(&val.to_be_bytes())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Write Float as f32
|
/// Write Float as f32
|
||||||
fn write_float(&mut self, val: f32) -> Result<(), ProtocolError> {
|
fn write_float(&mut self, val: f32) -> Result<(), ProtocolError> {
|
||||||
match self.write_bytes(&val.to_be_bytes()) {
|
self.write_bytes(&val.to_be_bytes())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Write Double as f64
|
/// Write Double as f64
|
||||||
fn write_double(&mut self, val: f64) -> Result<(), ProtocolError> {
|
fn write_double(&mut self, val: f64) -> Result<(), ProtocolError> {
|
||||||
match self.write_bytes(&val.to_be_bytes()) {
|
self.write_bytes(&val.to_be_bytes())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Write Int as i32
|
/// Write Int as i32
|
||||||
fn write_int(&mut self, val: i32) -> Result<(), ProtocolError> {
|
fn write_int(&mut self, val: i32) -> Result<(), ProtocolError> {
|
||||||
match self.write_bytes(&val.to_be_bytes()) {
|
self.write_bytes(&val.to_be_bytes())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::UnsignedShortError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write VarInt as usize
|
/// Write VarInt as usize
|
||||||
@ -98,27 +77,27 @@ pub trait DataWriter {
|
|||||||
|
|
||||||
/// Write VarInt as isize
|
/// Write VarInt as isize
|
||||||
fn write_isize_varint(&mut self, val: isize) -> Result<(), ProtocolError> {
|
fn write_isize_varint(&mut self, val: isize) -> Result<(), ProtocolError> {
|
||||||
self.write_usize_varint(val.zigzag())
|
self.write_usize_varint(val as usize)
|
||||||
}
|
}
|
||||||
/// Write VarInt as i8
|
/// Write VarInt as i8
|
||||||
fn write_i8_varint(&mut self, val: i8) -> Result<(), ProtocolError> {
|
fn write_i8_varint(&mut self, val: i8) -> Result<(), ProtocolError> {
|
||||||
self.write_u8_varint(val.zigzag())
|
self.write_u8_varint(val as u8)
|
||||||
}
|
}
|
||||||
/// Write VarInt as i16
|
/// Write VarInt as i16
|
||||||
fn write_i16_varint(&mut self, val: i16) -> Result<(), ProtocolError> {
|
fn write_i16_varint(&mut self, val: i16) -> Result<(), ProtocolError> {
|
||||||
self.write_u16_varint(val.zigzag())
|
self.write_u16_varint(val as u16)
|
||||||
}
|
}
|
||||||
/// Write VarInt as i32
|
/// Write VarInt as i32
|
||||||
fn write_i32_varint(&mut self, val: i32) -> Result<(), ProtocolError> {
|
fn write_i32_varint(&mut self, val: i32) -> Result<(), ProtocolError> {
|
||||||
self.write_u32_varint(val.zigzag())
|
self.write_u32_varint(val as u32)
|
||||||
}
|
}
|
||||||
/// Write VarInt as i64
|
/// Write VarInt as i64
|
||||||
fn write_i64_varint(&mut self, val: i64) -> Result<(), ProtocolError> {
|
fn write_i64_varint(&mut self, val: i64) -> Result<(), ProtocolError> {
|
||||||
self.write_u64_varint(val.zigzag())
|
self.write_u64_varint(val as u64)
|
||||||
}
|
}
|
||||||
/// Write VarInt as i128
|
/// Write VarInt as i128
|
||||||
fn write_i128_varint(&mut self, val: i128) -> Result<(), ProtocolError> {
|
fn write_i128_varint(&mut self, val: i128) -> Result<(), ProtocolError> {
|
||||||
self.write_u128_varint(val.zigzag())
|
self.write_u128_varint(val as u128)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
276
src/lib.rs
276
src/lib.rs
@ -3,7 +3,6 @@ mod tests;
|
|||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod zigzag;
|
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{DataReader, DataWriter};
|
pub use crate::{DataReader, DataWriter};
|
||||||
@ -16,13 +15,7 @@ pub use crate::{
|
|||||||
|
|
||||||
use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
|
use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error, fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, sync::atomic::AtomicBool, usize
|
error::Error, fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, usize
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
use std::sync::{
|
|
||||||
atomic::{AtomicUsize, Ordering},
|
|
||||||
Arc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Minecraft protocol error
|
/// Minecraft protocol error
|
||||||
@ -36,7 +29,6 @@ pub enum ProtocolError {
|
|||||||
ReadError,
|
ReadError,
|
||||||
WriteError,
|
WriteError,
|
||||||
ZlibError,
|
ZlibError,
|
||||||
UnsignedShortError,
|
|
||||||
CloneError,
|
CloneError,
|
||||||
ConnectionClosedError
|
ConnectionClosedError
|
||||||
}
|
}
|
||||||
@ -52,73 +44,8 @@ impl Error for ProtocolError {}
|
|||||||
/// Minecraft connection, wrapper for stream with compression
|
/// Minecraft connection, wrapper for stream with compression
|
||||||
pub struct MinecraftConnection<T: Read + Write> {
|
pub struct MinecraftConnection<T: Read + Write> {
|
||||||
stream: T,
|
stream: T,
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
compression: Arc<AtomicUsize>,
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
compression: Option<usize>,
|
compression: Option<usize>,
|
||||||
compression_type: u32,
|
compression_type: u32
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
is_alive: Arc<AtomicBool>,
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
is_alive: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MinecraftConnection<TcpStream> {
|
|
||||||
/// Connect to Minecraft Server with TcpStream
|
|
||||||
pub fn connect(addr: &str) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
|
|
||||||
let addr = match addr.to_socket_addrs() {
|
|
||||||
Ok(mut i) => match i.next() {
|
|
||||||
Some(i) => i,
|
|
||||||
None => return Err(ProtocolError::AddressParseError),
|
|
||||||
},
|
|
||||||
Err(_) => return Err(ProtocolError::AddressParseError),
|
|
||||||
};
|
|
||||||
|
|
||||||
let stream: TcpStream = match TcpStream::connect(&addr) {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(_) => return Err(ProtocolError::StreamConnectError),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(MinecraftConnection {
|
|
||||||
stream,
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
compression: Arc::new(AtomicUsize::new(usize::MAX)),
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
compression: None,
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
is_alive: Arc::new(AtomicBool::new(true)),
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
is_alive: true,
|
|
||||||
compression_type: 1,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Close TcpStream
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
pub fn close(&mut self) {
|
|
||||||
let _ = self.stream.shutdown(std::net::Shutdown::Both);
|
|
||||||
self.is_alive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Close TcpStream
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
pub fn close(&self) {
|
|
||||||
let _ = self.stream.shutdown(std::net::Shutdown::Both);
|
|
||||||
self.is_alive.store(false, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try clone MinecraftConnection with compression and stream
|
|
||||||
pub fn try_clone(&self) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
|
|
||||||
match self.stream.try_clone() {
|
|
||||||
Ok(stream) => Ok(MinecraftConnection {
|
|
||||||
stream,
|
|
||||||
is_alive: self.is_alive.clone(),
|
|
||||||
compression: self.compression.clone(),
|
|
||||||
compression_type: self.compression_type,
|
|
||||||
}),
|
|
||||||
_ => Err(ProtocolError::CloneError),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Read + Write> DataReader for MinecraftConnection<T> {
|
impl<T: Read + Write> DataReader for MinecraftConnection<T> {
|
||||||
@ -133,10 +60,7 @@ impl<T: Read + Write> DataReader for MinecraftConnection<T> {
|
|||||||
|
|
||||||
impl<T: Read + Write> DataWriter for MinecraftConnection<T> {
|
impl<T: Read + Write> DataWriter for MinecraftConnection<T> {
|
||||||
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError> {
|
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError> {
|
||||||
match self.stream.write_all(bytes) {
|
self.stream.write_all(bytes).map_err(|_| ProtocolError::WriteError)
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(ProtocolError::WriteError),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,73 +69,19 @@ impl<T: Read + Write> MinecraftConnection<T> {
|
|||||||
pub fn new(stream: T) -> MinecraftConnection<T> {
|
pub fn new(stream: T) -> MinecraftConnection<T> {
|
||||||
MinecraftConnection {
|
MinecraftConnection {
|
||||||
stream,
|
stream,
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
compression: Arc::new(AtomicUsize::new(usize::MAX)),
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
compression: None,
|
compression: None,
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
is_alive: Arc::new(AtomicBool::new(true)),
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
is_alive: true,
|
|
||||||
compression_type: 1,
|
compression_type: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set alive state
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
fn set_alive(&mut self, state: bool) {
|
|
||||||
self.is_alive = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set alive state
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
fn set_alive(&self, state: bool) {
|
|
||||||
self.is_alive.store(state, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is connection alive
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
pub fn is_alive(&self) -> bool {
|
|
||||||
self.is_alive
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is connection alive
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
pub fn is_alive(&self) -> bool {
|
|
||||||
self.is_alive.load(Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set compression threshold
|
/// Set compression threshold
|
||||||
pub fn set_compression(&mut self, threshold: Option<usize>) {
|
pub fn set_compression(&mut self, threshold: Option<usize>) {
|
||||||
#[cfg(feature = "atomic_clone")]
|
self.compression = threshold;
|
||||||
self.compression.store(
|
|
||||||
match threshold {
|
|
||||||
Some(t) => t,
|
|
||||||
None => usize::MAX,
|
|
||||||
},
|
|
||||||
Ordering::Relaxed,
|
|
||||||
);
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
{
|
|
||||||
self.compression = threshold;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get compression threshold
|
/// Get compression threshold
|
||||||
pub fn compression(&self) -> Option<usize> {
|
pub fn compression(&self) -> Option<usize> {
|
||||||
#[cfg(feature = "atomic_clone")]
|
self.compression
|
||||||
{
|
|
||||||
let threshold = self.compression.load(Ordering::Relaxed);
|
|
||||||
if threshold == usize::MAX {
|
|
||||||
return None
|
|
||||||
} else {
|
|
||||||
return Some(threshold)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
{
|
|
||||||
self.compression
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set compression type
|
/// Set compression type
|
||||||
@ -244,56 +114,12 @@ impl<T: Read + Write> MinecraftConnection<T> {
|
|||||||
|
|
||||||
/// Read [`Packet`](Packet) from connection
|
/// Read [`Packet`](Packet) from connection
|
||||||
pub fn read_packet(&mut self) -> Result<Packet, ProtocolError> {
|
pub fn read_packet(&mut self) -> Result<Packet, ProtocolError> {
|
||||||
if !self.is_alive() {
|
read_packet(&mut self.stream, self.compression)
|
||||||
return Err(ProtocolError::ConnectionClosedError);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
{
|
|
||||||
return match read_packet_atomic(
|
|
||||||
&mut self.stream,
|
|
||||||
self.compression.clone(),
|
|
||||||
Ordering::Relaxed,
|
|
||||||
) {
|
|
||||||
Err(ProtocolError::ConnectionClosedError) => {
|
|
||||||
self.set_alive(false);
|
|
||||||
Err(ProtocolError::ConnectionClosedError)
|
|
||||||
},
|
|
||||||
i => i
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
match read_packet(&mut self.stream, self.compression) {
|
|
||||||
Err(ProtocolError::ConnectionClosedError) => {
|
|
||||||
self.set_alive(false);
|
|
||||||
Err(ProtocolError::ConnectionClosedError)
|
|
||||||
},
|
|
||||||
i => i
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write [`Packet`](Packet) to connection
|
/// Write [`Packet`](Packet) to connection
|
||||||
pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> {
|
pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> {
|
||||||
if !self.is_alive() {
|
write_packet(&mut self.stream, self.compression, self.compression_type, packet)
|
||||||
return Err(ProtocolError::ConnectionClosedError);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
{
|
|
||||||
return write_packet_atomic(
|
|
||||||
&mut self.stream,
|
|
||||||
self.compression.clone(),
|
|
||||||
Ordering::Relaxed,
|
|
||||||
self.compression_type,
|
|
||||||
packet,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "atomic_clone"))]
|
|
||||||
{
|
|
||||||
write_packet(&mut self.stream, self.compression, self.compression_type, packet)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,13 +128,53 @@ impl<T: Read + Write + Clone> MinecraftConnection<T> {
|
|||||||
pub fn clone(&mut self) -> MinecraftConnection<T> {
|
pub fn clone(&mut self) -> MinecraftConnection<T> {
|
||||||
MinecraftConnection {
|
MinecraftConnection {
|
||||||
stream: self.stream.clone(),
|
stream: self.stream.clone(),
|
||||||
compression: self.compression.clone(),
|
compression: self.compression,
|
||||||
is_alive: self.is_alive.clone(),
|
|
||||||
compression_type: self.compression_type,
|
compression_type: self.compression_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MinecraftConnection<TcpStream> {
|
||||||
|
/// Connect to Minecraft Server with TcpStream
|
||||||
|
pub fn connect(addr: &str) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
|
||||||
|
let addr = match addr.to_socket_addrs() {
|
||||||
|
Ok(mut i) => match i.next() {
|
||||||
|
Some(i) => i,
|
||||||
|
None => return Err(ProtocolError::AddressParseError),
|
||||||
|
},
|
||||||
|
Err(_) => return Err(ProtocolError::AddressParseError),
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream: TcpStream = match TcpStream::connect(&addr) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(_) => return Err(ProtocolError::StreamConnectError),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(MinecraftConnection {
|
||||||
|
stream,
|
||||||
|
compression: None,
|
||||||
|
compression_type: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close TcpStream
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
let _ = self.stream.shutdown(std::net::Shutdown::Both);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try clone MinecraftConnection with compression and stream
|
||||||
|
pub fn try_clone(&self) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
|
||||||
|
match self.stream.try_clone() {
|
||||||
|
Ok(stream) => Ok(MinecraftConnection {
|
||||||
|
stream,
|
||||||
|
compression: self.compression,
|
||||||
|
compression_type: self.compression_type,
|
||||||
|
}),
|
||||||
|
_ => Err(ProtocolError::CloneError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn compress_zlib(bytes: &[u8], compression: u32) -> Result<Vec<u8>, ProtocolError> {
|
fn compress_zlib(bytes: &[u8], compression: u32) -> Result<Vec<u8>, ProtocolError> {
|
||||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression));
|
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression));
|
||||||
encoder.write_all(bytes).or(Err(ProtocolError::ZlibError))?;
|
encoder.write_all(bytes).or(Err(ProtocolError::ZlibError))?;
|
||||||
@ -406,46 +272,4 @@ pub fn write_packet<T: Write>(
|
|||||||
stream.write_bytes(&buf)?;
|
stream.write_bytes(&buf)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read [`Packet`](Packet) from stream
|
|
||||||
///
|
|
||||||
/// `compression` here is atomic usize
|
|
||||||
/// usize::MAX means that compression is disabled
|
|
||||||
///
|
|
||||||
/// `ordering` is order how to load atomic
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
pub fn read_packet_atomic<T: Read>(
|
|
||||||
stream: &mut T,
|
|
||||||
compression: Arc<AtomicUsize>,
|
|
||||||
ordering: Ordering,
|
|
||||||
) -> Result<Packet, ProtocolError> {
|
|
||||||
read_packet(stream, match compression.load(ordering) {
|
|
||||||
usize::MAX => None,
|
|
||||||
i => Some(i),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write [`Packet`](Packet) to stream
|
|
||||||
///
|
|
||||||
/// `compression` here is atomic usize
|
|
||||||
/// usize::MAX means that compression is disabled
|
|
||||||
///
|
|
||||||
/// `ordering` is order how to load atomic
|
|
||||||
///
|
|
||||||
/// `compression_type` is integer from 0 (none) to 9 (longest)
|
|
||||||
/// 1 is fast compression
|
|
||||||
/// 6 is normal compression
|
|
||||||
#[cfg(feature = "atomic_clone")]
|
|
||||||
pub fn write_packet_atomic<T: Write>(
|
|
||||||
stream: &mut T,
|
|
||||||
compression: Arc<AtomicUsize>,
|
|
||||||
ordering: Ordering,
|
|
||||||
compression_type: u32,
|
|
||||||
packet: &Packet,
|
|
||||||
) -> Result<(), ProtocolError> {
|
|
||||||
write_packet(stream, match compression.load(ordering) {
|
|
||||||
usize::MAX => None,
|
|
||||||
i => Some(i),
|
|
||||||
}, compression_type, packet)
|
|
||||||
}
|
|
45
src/tests.rs
45
src/tests.rs
@ -3,6 +3,51 @@ use uuid::Uuid;
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::{io::Cursor, net::TcpListener, thread};
|
use std::{io::Cursor, net::TcpListener, thread};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_varint() -> Result<(), ProtocolError> {
|
||||||
|
let mut src = Packet::empty(0x00);
|
||||||
|
|
||||||
|
src.write_u8_varint(0)?; // 0x00
|
||||||
|
src.write_u8_varint(1)?; // 0x01
|
||||||
|
src.write_u8_varint(2)?; // 0x02
|
||||||
|
src.write_u8_varint(127)?; // 0x7f
|
||||||
|
src.write_u8_varint(128)?; // 0x80 0x01
|
||||||
|
src.write_u16_varint(255)?; // 0xff 0x01
|
||||||
|
src.write_u16_varint(25565)?; // 0xdd 0xc7 0x01
|
||||||
|
src.write_u32_varint(2097151)?; // 0xff 0xff 0x7f
|
||||||
|
src.write_u32_varint(2147483647)?; // 0xff 0xff 0xff 0xff 0x07
|
||||||
|
src.write_i8_varint(-1)?; // 0xff 0xff 0xff 0xff 0x0f
|
||||||
|
src.write_i32_varint(-2147483648)?; // 0x80 0x80 0x80 0x80 0x08
|
||||||
|
|
||||||
|
let mut packet = Packet::from_bytes(0x00, src.get_bytes());
|
||||||
|
assert_eq!(packet.read_u8_varint()?, 0);
|
||||||
|
assert_eq!(packet.read_u8_varint()?, 1);
|
||||||
|
assert_eq!(packet.read_u8_varint()?, 2);
|
||||||
|
assert_eq!(packet.read_u8_varint()?, 127);
|
||||||
|
assert_eq!(packet.read_u8_varint()?, 128);
|
||||||
|
assert_eq!(packet.read_u16_varint()?, 255);
|
||||||
|
assert_eq!(packet.read_u16_varint()?, 25565);
|
||||||
|
assert_eq!(packet.read_u32_varint()?, 2097151);
|
||||||
|
assert_eq!(packet.read_u32_varint()?, 2147483647);
|
||||||
|
assert_eq!(packet.read_i8_varint()?, -1);
|
||||||
|
assert_eq!(packet.read_i32_varint()?, -2147483648);
|
||||||
|
|
||||||
|
let mut packet = Packet::from_bytes(0x00, src.get_bytes());
|
||||||
|
assert_eq!(packet.read_bytes(1)?, vec![0x00]); // 0
|
||||||
|
assert_eq!(packet.read_bytes(1)?, vec![0x01]); // 1
|
||||||
|
assert_eq!(packet.read_bytes(1)?, vec![0x02]); // 2
|
||||||
|
assert_eq!(packet.read_bytes(1)?, vec![0x7f]); // 127
|
||||||
|
assert_eq!(packet.read_bytes(2)?, vec![0x80, 0x01]); // 128
|
||||||
|
assert_eq!(packet.read_bytes(2)?, vec![0xff, 0x01]); // 255
|
||||||
|
assert_eq!(packet.read_bytes(3)?, vec![0xdd, 0xc7, 0x01]); // 25565
|
||||||
|
assert_eq!(packet.read_bytes(3)?, vec![0xff, 0xff, 0x7f]); // 2097151
|
||||||
|
assert_eq!(packet.read_bytes(5)?, vec![0xff, 0xff, 0xff, 0xff, 0x07]); // 2147483647
|
||||||
|
assert_eq!(packet.read_bytes(5)?, vec![0xff, 0xff, 0xff, 0xff, 0x0f]); // -1
|
||||||
|
assert_eq!(packet.read_bytes(5)?, vec![0x80, 0x80, 0x80, 0x80, 0x08]); // -2147483648
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_data_transfer() -> Result<(), ProtocolError> {
|
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…
Reference in New Issue
Block a user