use crate::ProtocolError; use std::io::Write; use uuid::Uuid; /// Packet data writer trait pub trait DataWriter { /// Write bytes fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError>; /// Write byte fn write_byte(&mut self, byte: u8) -> Result<(), ProtocolError> { self.write_bytes(&[byte]) } /// Write String fn write_string(&mut self, val: &str) -> Result<(), ProtocolError> { self.write_usize_varint(val.len())?; self.write_bytes(val.as_bytes()) } /// Write UUID fn write_uuid(&mut self, val: &Uuid) -> Result<(), ProtocolError> { self.write_bytes(val.as_bytes()) } /// Write Signed byte as i8 fn write_signed_byte(&mut self, val: i8) -> Result<(), ProtocolError> { self.write_byte(val as u8) } /// Write Unsigned Short as u16 fn write_unsigned_short(&mut self, val: u16) -> Result<(), ProtocolError> { self.write_bytes(&val.to_be_bytes()) } /// Write Boolean fn write_boolean(&mut self, val: bool) -> Result<(), ProtocolError> { self.write_byte(if val { 0x01 } else { 0x00 }) } /// Write Short as i16 fn write_short(&mut self, val: i16) -> Result<(), ProtocolError> { self.write_bytes(&val.to_be_bytes()) } /// Write Long as i64 fn write_long(&mut self, val: i64) -> Result<(), ProtocolError> { self.write_bytes(&val.to_be_bytes()) } /// Write Float as f32 fn write_float(&mut self, val: f32) -> Result<(), ProtocolError> { self.write_bytes(&val.to_be_bytes()) } /// Write Double as f64 fn write_double(&mut self, val: f64) -> Result<(), ProtocolError> { self.write_bytes(&val.to_be_bytes()) } /// Write Int as i32 fn write_int(&mut self, val: i32) -> Result<(), ProtocolError> { self.write_bytes(&val.to_be_bytes()) } /// Write VarInt as u8 fn write_u8_varint(&mut self, val: u8) -> Result<(), ProtocolError> { self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarInt as u16 fn write_u16_varint(&mut self, val: u16) -> Result<(), ProtocolError> { self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarInt as usize /// /// Returns error if the value is greater than i32::MAX 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) } /// Write VarInt as u32 /// /// Returns error if the value is greater than i32::MAX 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) } /// Write VarInt as i8 fn write_i8_varint(&mut self, val: i8) -> Result<(), ProtocolError> { self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarInt as i16 fn write_i16_varint(&mut self, val: i16) -> Result<(), ProtocolError> { self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarInt as isize fn write_isize_varint(&mut self, val: isize) -> Result<(), ProtocolError> { self.write_varint(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarInt as i32 /// /// *Use [write_varint](DataWriter::write_varint) instead* fn write_i32_varint(&mut self, val: i32) -> Result<(), ProtocolError> { self.write_varint(val) } /// Write VarLong as u8 fn write_u8_varlong(&mut self, val: u8) -> Result<(), ProtocolError> { self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarLong as u16 fn write_u16_varlong(&mut self, val: u16) -> Result<(), ProtocolError> { self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarLong as u32 fn write_u32_varlong(&mut self, val: u32) -> Result<(), ProtocolError> { self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarLong as u64 /// /// Returns error if the value is greater than i64::MAX 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) } /// Write VarLong as usize /// /// Returns error if the value is greater than i64::MAX 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) } /// Write VarLong as i8 fn write_i8_varlong(&mut self, val: i8) -> Result<(), ProtocolError> { self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarLong as i16 fn write_i16_varlong(&mut self, val: i16) -> Result<(), ProtocolError> { self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarLong as i32 fn write_i32_varlong(&mut self, val: i32) -> Result<(), ProtocolError> { self.write_varlong(val.try_into().map_err(|_| ProtocolError::VarIntError)?) } /// Write VarLong as i64 /// /// *Use [write_varlong](DataWriter::write_varlong) instead* fn write_i64_varlong(&mut self, val: i64) -> Result<(), ProtocolError> { self.write_varlong(val) } /// Write VarInt as i32 fn write_varint(&mut self, val: i32) -> Result<(), ProtocolError> { let mut value = val as u32; loop { if value & !0x7F == 0 { self.write_byte(TryInto::::try_into(value).map_err(|_| ProtocolError::VarIntError)?)?; break; } self.write_byte(TryInto::::try_into((value & 0x7F) | 0x80).map_err(|_| ProtocolError::VarIntError)?)?; value >>= 7; } Ok(()) } /// Write VarLong as i64 fn write_varlong(&mut self, val: i64) -> Result<(), ProtocolError> { let mut value = val as u64; loop { if value & !0x7F == 0 { self.write_byte(TryInto::::try_into(value).map_err(|_| ProtocolError::VarIntError)?)?; break; } self.write_byte(TryInto::::try_into((value & 0x7F) | 0x80).map_err(|_| ProtocolError::VarIntError)?)?; value >>= 7; } Ok(()) } } impl DataWriter for W { fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError> { self.write_all(bytes).map_err(|_| ProtocolError::WriteError) } }