use std::{ io::{Read, Write}, num::NonZeroUsize, ops::Deref, }; use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError}; use super::Codec; use bytes::BufMut; use serde::{ Deserialize, Deserializer, Serialize, Serializer, de::{self, SeqAccess, Visitor}, }; pub type VarLongType = i64; /** * A variable-length long type used by the Minecraft network protocol. */ #[derive(Debug, Clone, PartialEq, Eq)] pub struct VarLong(pub VarLongType); impl Codec for VarLong { /// The maximum number of bytes a `VarLong` can occupy. const MAX_SIZE: NonZeroUsize = NonZeroUsize::new(10).unwrap(); /// Returns the exact number of bytes this VarLong 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 Write) -> Result<(), WritingError> { let mut x = self.0; for _ in 0..Self::MAX_SIZE.get() { let byte = (x & 0x7F) as u8; x >>= 7; if x == 0 { write.write_u8_be(byte)?; break; } write.write_u8_be(byte | 0x80)?; } Ok(()) } fn decode(read: &mut impl Read) -> Result { let mut val = 0; for i in 0..Self::MAX_SIZE.get() { let byte = read.get_u8_be()?; val |= (i64::from(byte) & 0b01111111) << (i * 7); if byte & 0b10000000 == 0 { return Ok(VarLong(val)); } } Err(ReadingError::TooLarge("VarLong".to_string())) } } impl From for VarLong { fn from(value: i64) -> Self { VarLong(value) } } impl From for VarLong { fn from(value: u32) -> Self { VarLong(value as i64) } } impl From for VarLong { fn from(value: u8) -> Self { VarLong(value as i64) } } impl From for VarLong { fn from(value: usize) -> Self { VarLong(value as i64) } } impl From for i64 { fn from(value: VarLong) -> Self { value.0 } } impl AsRef for VarLong { fn as_ref(&self) -> &i64 { &self.0 } } impl Deref for VarLong { type Target = i64; fn deref(&self) -> &Self::Target { &self.0 } } impl Serialize for VarLong { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut value = self.0 as u64; 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 VarLong { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct VarLongVisitor; impl<'de> Visitor<'de> for VarLongVisitor { type Value = VarLong; 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..VarLong::MAX_SIZE.get() { if let Some(byte) = seq.next_element::()? { val |= (i64::from(byte) & 0b01111111) << (i * 7); if byte & 0b10000000 == 0 { return Ok(VarLong(val)); } } else { break; } } Err(de::Error::custom("VarInt was too large")) } } deserializer.deserialize_seq(VarLongVisitor) } }