use crate::ser::{Error, Readable, Reader, Writeable, Writer};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct VarInt(pub u64);
impl VarInt {
#[inline]
pub fn len(&self) -> usize {
match self.0 {
0..=0xFC => 1,
0xFD..=0xFFFF => 3,
0x10000..=0xFFFFFFFF => 5,
_ => 9,
}
}
#[inline]
pub fn as_u64(&self) -> u64 {
self.0
}
}
impl Readable for VarInt {
fn read(reader: &mut dyn Reader) -> Result<VarInt, Error> {
let n = reader.read_u8()?;
match n {
0xFF => {
let x = reader.read_u64()?;
if x < 0x100000000 {
Err(Error::InvalidVarInt)
} else {
Ok(VarInt(x))
}
}
0xFE => {
let x = reader.read_u32()?;
if x < 0x10000 {
Err(Error::InvalidVarInt)
} else {
Ok(VarInt(x as u64))
}
}
0xFD => {
let x = reader.read_u16()?;
if x < 0xFD {
Err(Error::InvalidVarInt)
} else {
Ok(VarInt(x as u64))
}
}
n => Ok(VarInt(n as u64)),
}
}
}
impl Writeable for VarInt {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
match self.0 {
0..=0xFC => {
writer.write_u8(self.0 as u8)?;
Ok(())
}
0xFD..=0xFFFF => {
writer.write_u8(0xFD)?;
writer.write_u16(self.0 as u16)?;
Ok(())
}
0x10000..=0xFFFFFFFF => {
writer.write_u8(0xFE)?;
writer.write_u32(self.0 as u32)?;
Ok(())
}
_ => {
writer.write_u8(0xFF)?;
writer.write_u64(self.0 as u64)?;
Ok(())
}
}
}
}
#[test]
fn serialize_varint_test() {
use crate::ser::{ser_vec, ProtocolVersion};
assert_eq!(
ser_vec(&VarInt(10), ProtocolVersion::local()).unwrap(),
vec![10u8]
);
assert_eq!(
ser_vec(&VarInt(0xFC), ProtocolVersion::local()).unwrap(),
vec![0xFCu8]
);
assert_eq!(
ser_vec(&VarInt(0xFD), ProtocolVersion::local()).unwrap(),
vec![0xFDu8, 0xFD, 0]
);
assert_eq!(
ser_vec(&VarInt(0xFFF), ProtocolVersion::local()).unwrap(),
vec![0xFDu8, 0xFF, 0xF]
);
assert_eq!(
ser_vec(&VarInt(0xF0F0F0F), ProtocolVersion::local()).unwrap(),
vec![0xFEu8, 0xF, 0xF, 0xF, 0xF]
);
assert_eq!(
ser_vec(&VarInt(0xF0F0F0F0F0E0), ProtocolVersion::local()).unwrap(),
vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0]
);
}