From f8196d036ce51917f9d2437e94c658330aada744 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Thu, 1 May 2025 04:42:45 +0300 Subject: [PATCH] remove atomic_clone feature remove zigzag add varint test replace read_varint macro with size_varint some rewrite varint reading --- Cargo.toml | 6 +- src/data/reader.rs | 170 ++++++++++++---------------- src/data/varint.rs | 38 +------ src/data/writer.rs | 49 +++----- src/lib.rs | 276 ++++++++------------------------------------- src/tests.rs | 45 ++++++++ src/zigzag.rs | 65 ----------- 7 files changed, 188 insertions(+), 461 deletions(-) delete mode 100755 src/zigzag.rs diff --git a/Cargo.toml b/Cargo.toml index 1f3ab5d..04847b7 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,4 @@ edition = "2024" [dependencies] flate2 = "1.1.1" -uuid = "1.16.0" - -[features] -default = ["atomic_clone"] -atomic_clone = [] \ No newline at end of file +uuid = "1.16.0" \ No newline at end of file diff --git a/src/data/reader.rs b/src/data/reader.rs index 545a002..14330d0 100755 --- a/src/data/reader.rs +++ b/src/data/reader.rs @@ -1,6 +1,5 @@ use crate::{ - data::varint::{read_varint, size_varint}, - zigzag::Zigzag, + data::varint::read_varint, ProtocolError, }; use std::io::Read; @@ -25,174 +24,149 @@ pub trait DataReader { } /// Read Unsigned Short as u16 fn read_unsigned_short(&mut self) -> Result { - match self.read_bytes(2)?.try_into() { - Ok(i) => Ok(u16::from_be_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(2) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| u16::from_be_bytes(o)) } /// Read Boolean fn read_boolean(&mut self) -> Result { - Ok(self.read_byte()? == 0x01) + self.read_byte().map(|o| o == 0x01) } /// Read Short as i16 fn read_short(&mut self) -> Result { - match self.read_bytes(2)?.try_into() { - Ok(i) => Ok(i16::from_be_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(2) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| i16::from_be_bytes(o)) } /// Read Long as i64 fn read_long(&mut self) -> Result { - match self.read_bytes(8)?.try_into() { - Ok(i) => Ok(i64::from_be_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(8) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| i64::from_be_bytes(o)) } /// Read Float as f32 fn read_float(&mut self) -> Result { - match self.read_bytes(4)?.try_into() { - Ok(i) => Ok(f32::from_be_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(4) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| f32::from_be_bytes(o)) } /// Read Double as f64 fn read_double(&mut self) -> Result { - match self.read_bytes(8)?.try_into() { - Ok(i) => Ok(f64::from_be_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(8) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| f64::from_be_bytes(o)) } /// Read Int as i32 fn read_int(&mut self) -> Result { - match self.read_bytes(4)?.try_into() { - Ok(i) => Ok(i32::from_be_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(4) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| i32::from_be_bytes(o)) } /// Read UUID fn read_uuid(&mut self) -> Result { - match self.read_bytes(16)?.try_into() { - Ok(i) => Ok(Uuid::from_bytes(i)), - Err(_) => Err(ProtocolError::ReadError), - } + self.read_bytes(16) + .and_then(|o| o.try_into().map_err(|_| ProtocolError::ReadError)) + .map(|o| Uuid::from_bytes(o)) } /// Read VarInt as usize with size in bytes (varint, size) 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) 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) 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) 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) 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) fn read_u128_varint_size(&mut self) -> Result<(u128, usize), ProtocolError> { - size_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!(u128, self) } /// Read VarInt as usize fn read_usize_varint(&mut self) -> Result { - read_varint!(usize, self) + self.read_usize_varint_size().map(|o| o.0) } /// Read VarInt as u8 fn read_u8_varint(&mut self) -> Result { - read_varint!(u8, self) + self.read_u8_varint_size().map(|o| o.0) } /// Read VarInt as u16 fn read_u16_varint(&mut self) -> Result { - read_varint!(u16, self) + self.read_u16_varint_size().map(|o| o.0) } /// Read VarInt as u32 fn read_u32_varint(&mut self) -> Result { - read_varint!(u32, self) + self.read_u32_varint_size().map(|o| o.0) } /// Read VarInt as u64 fn read_u64_varint(&mut self) -> Result { - read_varint!(u64, self) + self.read_u64_varint_size().map(|o| o.0) } /// Read VarInt as u128 fn read_u128_varint(&mut self) -> Result { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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)) } } diff --git a/src/data/varint.rs b/src/data/varint.rs index dfd88ab..fdc2350 100755 --- a/src/data/varint.rs +++ b/src/data/varint.rs @@ -1,4 +1,4 @@ -macro_rules! size_varint { +macro_rules! read_varint { ($type:ty, $self:expr) => {{ let mut shift: $type = 0; let mut decoded: $type = 0; @@ -12,9 +12,9 @@ macro_rules! size_varint { 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; } else { 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 { ($type:ty, $self:expr, $value:expr) => {{ let mut value: $type = $value; @@ -53,18 +30,15 @@ macro_rules! write_varint { if value == 0 { DataWriter::write_byte($self, 0) } else { - while value >= 0b10000000 { - let next: u8 = ((value & 0b01111111) as u8) | 0b10000000; + while value >= 0x80 { + DataWriter::write_byte($self, ((value & 0x7F) as u8) | 0x80)?; 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 size_varint; pub(crate) use write_varint; diff --git a/src/data/writer.rs b/src/data/writer.rs index 4e985d3..54c02a4 100755 --- a/src/data/writer.rs +++ b/src/data/writer.rs @@ -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 uuid::Uuid; @@ -23,52 +23,31 @@ pub trait DataWriter { } /// Write Unsigned Short as u16 fn write_unsigned_short(&mut self, val: u16) -> Result<(), ProtocolError> { - match self.write_bytes(&val.to_be_bytes()) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_bytes(&val.to_be_bytes()) } /// Write Boolean fn write_boolean(&mut self, val: bool) -> Result<(), ProtocolError> { - match self.write_byte(if val { 0x01 } else { 0x00 }) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_byte(if val { 0x01 } else { 0x00 }) } /// Write Short as i16 fn write_short(&mut self, val: i16) -> Result<(), ProtocolError> { - match self.write_bytes(&val.to_be_bytes()) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_bytes(&val.to_be_bytes()) } /// Write Long as i64 fn write_long(&mut self, val: i64) -> Result<(), ProtocolError> { - match self.write_bytes(&val.to_be_bytes()) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_bytes(&val.to_be_bytes()) } /// Write Float as f32 fn write_float(&mut self, val: f32) -> Result<(), ProtocolError> { - match self.write_bytes(&val.to_be_bytes()) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_bytes(&val.to_be_bytes()) } /// Write Double as f64 fn write_double(&mut self, val: f64) -> Result<(), ProtocolError> { - match self.write_bytes(&val.to_be_bytes()) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_bytes(&val.to_be_bytes()) } /// Write Int as i32 fn write_int(&mut self, val: i32) -> Result<(), ProtocolError> { - match self.write_bytes(&val.to_be_bytes()) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::UnsignedShortError), - } + self.write_bytes(&val.to_be_bytes()) } /// Write VarInt as usize @@ -98,27 +77,27 @@ pub trait DataWriter { /// Write VarInt as isize 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 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 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 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 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 fn write_i128_varint(&mut self, val: i128) -> Result<(), ProtocolError> { - self.write_u128_varint(val.zigzag()) + self.write_u128_varint(val as u128) } } diff --git a/src/lib.rs b/src/lib.rs index 559ebfb..722a385 100755 --- a/src/lib.rs +++ b/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}; @@ -16,13 +15,7 @@ pub use crate::{ use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression}; use std::{ - error::Error, fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, sync::atomic::AtomicBool, usize -}; - -#[cfg(feature = "atomic_clone")] -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, + error::Error, fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, usize }; /// Minecraft protocol error @@ -36,7 +29,6 @@ pub enum ProtocolError { ReadError, WriteError, ZlibError, - UnsignedShortError, CloneError, ConnectionClosedError } @@ -52,73 +44,8 @@ impl Error for ProtocolError {} /// Minecraft connection, wrapper for stream with compression pub struct MinecraftConnection { stream: T, - #[cfg(feature = "atomic_clone")] - compression: Arc, - #[cfg(not(feature = "atomic_clone"))] compression: Option, - compression_type: u32, - #[cfg(feature = "atomic_clone")] - is_alive: Arc, - #[cfg(not(feature = "atomic_clone"))] - is_alive: bool, -} - -impl MinecraftConnection { - /// Connect to Minecraft Server with TcpStream - pub fn connect(addr: &str) -> Result, 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, 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), - } - } + compression_type: u32 } impl DataReader for MinecraftConnection { @@ -133,10 +60,7 @@ impl DataReader for MinecraftConnection { impl DataWriter for MinecraftConnection { fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError> { - match self.stream.write_all(bytes) { - Ok(_) => Ok(()), - Err(_) => Err(ProtocolError::WriteError), - } + self.stream.write_all(bytes).map_err(|_| ProtocolError::WriteError) } } @@ -145,73 +69,19 @@ impl MinecraftConnection { pub fn new(stream: T) -> MinecraftConnection { 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, } } - /// 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 pub fn set_compression(&mut self, threshold: Option) { - #[cfg(feature = "atomic_clone")] - self.compression.store( - match threshold { - Some(t) => t, - None => usize::MAX, - }, - Ordering::Relaxed, - ); - #[cfg(not(feature = "atomic_clone"))] - { - self.compression = threshold; - } + self.compression = threshold; } /// Get compression threshold pub fn compression(&self) -> Option { - #[cfg(feature = "atomic_clone")] - { - let threshold = self.compression.load(Ordering::Relaxed); - if threshold == usize::MAX { - return None - } else { - return Some(threshold) - } - } - #[cfg(not(feature = "atomic_clone"))] - { - self.compression - } + self.compression } /// Set compression type @@ -244,56 +114,12 @@ impl MinecraftConnection { /// Read [`Packet`](Packet) from connection pub fn read_packet(&mut self) -> Result { - if !self.is_alive() { - 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 - } + read_packet(&mut self.stream, self.compression) } /// Write [`Packet`](Packet) to connection pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> { - if !self.is_alive() { - 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) - } + write_packet(&mut self.stream, self.compression, self.compression_type, packet) } } @@ -302,13 +128,53 @@ impl MinecraftConnection { pub fn clone(&mut self) -> MinecraftConnection { MinecraftConnection { stream: self.stream.clone(), - compression: self.compression.clone(), - is_alive: self.is_alive.clone(), + compression: self.compression, compression_type: self.compression_type, } } } +impl MinecraftConnection { + /// Connect to Minecraft Server with TcpStream + pub fn connect(addr: &str) -> Result, 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, 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, ProtocolError> { let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression)); encoder.write_all(bytes).or(Err(ProtocolError::ZlibError))?; @@ -406,46 +272,4 @@ pub fn write_packet( stream.write_bytes(&buf)?; 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( - stream: &mut T, - compression: Arc, - ordering: Ordering, -) -> Result { - 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( - stream: &mut T, - compression: Arc, - 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) -} +} \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 3b2aa84..abc1f34 100755 --- a/src/tests.rs +++ b/src/tests.rs @@ -3,6 +3,51 @@ use uuid::Uuid; use super::*; 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] fn test_data_transfer() -> Result<(), ProtocolError> { diff --git a/src/zigzag.rs b/src/zigzag.rs deleted file mode 100755 index b41018d..0000000 --- a/src/zigzag.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! VarInt reading helper - -pub trait Zigzag { - fn zigzag(&self) -> T; -} -impl Zigzag for i8 { - fn zigzag(&self) -> u8 { - ((self << 1) ^ (self >> 7)) as u8 - } -} -impl Zigzag for u8 { - fn zigzag(&self) -> i8 { - ((self >> 1) as i8) ^ (-((self & 1) as i8)) - } -} -impl Zigzag for i16 { - fn zigzag(&self) -> u16 { - ((self << 1) ^ (self >> 15)) as u16 - } -} -impl Zigzag for u16 { - fn zigzag(&self) -> i16 { - ((self >> 1) as i16) ^ (-((self & 1) as i16)) - } -} -impl Zigzag for i32 { - fn zigzag(&self) -> u32 { - ((self << 1) ^ (self >> 31)) as u32 - } -} -impl Zigzag for u32 { - fn zigzag(&self) -> i32 { - ((self >> 1) as i32) ^ (-((self & 1) as i32)) - } -} -impl Zigzag for i64 { - fn zigzag(&self) -> u64 { - ((self << 1) ^ (self >> 63)) as u64 - } -} -impl Zigzag for u64 { - fn zigzag(&self) -> i64 { - ((self >> 1) as i64) ^ (-((self & 1) as i64)) - } -} -impl Zigzag for i128 { - fn zigzag(&self) -> u128 { - ((self << 1) ^ (self >> 127)) as u128 - } -} -impl Zigzag for u128 { - fn zigzag(&self) -> i128 { - ((self >> 1) as i128) ^ (-((self & 1) as i128)) - } -} -impl Zigzag for isize { - fn zigzag(&self) -> usize { - ((self << 1) ^ (self >> std::mem::size_of::() - 1)) as usize - } -} -impl Zigzag for usize { - fn zigzag(&self) -> isize { - ((self >> 1) as isize) ^ (-((self & 1) as isize)) - } -}