use std::{num::NonZeroUsize, ops::Deref}; use super::{Codec, DecodeError}; use bytes::{Buf, BufMut}; use serde::{ Deserialize, Deserializer, Serialize, Serializer, de::{SeqAccess, Visitor}, }; pub type VarIntType = i32; /** * A variable-length integer type used by the Minecraft network protocol. */ #[derive(Debug, Clone, PartialEq, Eq)] pub struct VarInt(pub VarIntType); impl Codec for VarInt { /// The maximum number of bytes a `VarInt` can occupy. const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(5) }; /// Returns the exact number of bytes this varint will write when /// [`Encode::encode`] is called, assuming no error occurs. fn written_size(&self) -> usize { match self.0 { 0 => 1, n => (31 - n.leading_zeros() as usize) / 7 + 1, } } fn encode(&self, write: &mut impl BufMut) { let mut val = self.0; for _ in 0..Self::MAX_SIZE.get() { let b: u8 = val as u8 & 0b01111111; val >>= 7; write.put_u8(if val == 0 { b } else { b | 0b10000000 }); if val == 0 { break; } } } fn decode(read: &mut impl Buf) -> Result { let mut val = 0; for i in 0..Self::MAX_SIZE.get() { if !read.has_remaining() { return Err(DecodeError::Incomplete); } let byte = read.get_u8(); val |= (i32::from(byte) & 0x7F) << (i * 7); if byte & 0x80 == 0 { return Ok(VarInt(val)); } } Err(DecodeError::TooLarge) } } impl From for VarInt { fn from(value: i32) -> Self { VarInt(value) } } impl From for VarInt { fn from(value: u32) -> Self { VarInt(value as i32) } } impl From for VarInt { fn from(value: u8) -> Self { VarInt(value as i32) } } impl From for VarInt { fn from(value: usize) -> Self { VarInt(value as i32) } } impl From for i32 { fn from(value: VarInt) -> Self { value.0 } } impl AsRef for VarInt { fn as_ref(&self) -> &i32 { &self.0 } } impl Deref for VarInt { type Target = i32; fn deref(&self) -> &Self::Target { &self.0 } } impl Serialize for VarInt { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut value = self.0 as u32; let mut buf = Vec::new(); while value > 0x7F { buf.put_u8(value as u8 | 0x80); value >>= 7; } buf.put_u8(value as u8); serializer.serialize_bytes(&buf) } } impl<'de> Deserialize<'de> for VarInt { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct VarIntVisitor; impl<'de> Visitor<'de> for VarIntVisitor { type Value = VarInt; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("a valid VarInt encoded in a byte sequence") } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let mut val = 0; for i in 0..VarInt::MAX_SIZE.get() { if let Some(byte) = seq.next_element::()? { val |= (i32::from(byte) & 0b01111111) << (i * 7); if byte & 0b10000000 == 0 { return Ok(VarInt(val)); } } else { break; } } Err(serde::de::Error::custom("VarInt was too large")) } } deserializer.deserialize_seq(VarIntVisitor) } }