Pumpkin/pumpkin-protocol/src/bytebuf/mod.rs
Alexander Medvedev 466d4380cf Some Refactors
2025-02-01 17:53:41 +01:00

427 lines
12 KiB
Rust

use core::str;
use crate::{
codec::{
bit_set::BitSet, identifier::Identifier, var_int::VarInt, var_long::VarLong, Codec,
DecodeError,
},
FixedBitSet,
};
use bytes::{Buf, BufMut};
mod deserializer;
use thiserror::Error;
pub mod packet;
mod serializer;
use std::mem::size_of;
#[derive(Debug, Error)]
pub enum ReadingError {
/// End-of-File
#[error("EOF, Tried to read {0} but No bytes left to consume")]
EOF(String),
#[error("{0} is Incomplete")]
Incomplete(String),
#[error("{0} is too Large")]
TooLarge(String),
#[error("{0}")]
Message(String),
}
pub trait ByteBuf: Buf {
fn try_get_bool(&mut self) -> Result<bool, ReadingError>;
fn try_get_u8(&mut self) -> Result<u8, ReadingError>;
fn try_get_i8(&mut self) -> Result<i8, ReadingError>;
fn try_get_u16(&mut self) -> Result<u16, ReadingError>;
fn try_get_i16(&mut self) -> Result<i16, ReadingError>;
fn try_get_u32(&mut self) -> Result<u32, ReadingError>;
fn try_get_i32(&mut self) -> Result<i32, ReadingError>;
fn try_get_u64(&mut self) -> Result<u64, ReadingError>;
fn try_get_i64(&mut self) -> Result<i64, ReadingError>;
fn try_get_f32(&mut self) -> Result<f32, ReadingError>;
fn try_get_f64(&mut self) -> Result<f64, ReadingError>;
fn try_copy_to_bytes(&mut self, len: usize) -> Result<bytes::Bytes, ReadingError>;
fn try_copy_to_bytes_len(
&mut self,
len: usize,
max_length: usize,
) -> Result<bytes::Bytes, ReadingError>;
fn try_copy_to_slice(&mut self, dst: &mut [u8]) -> Result<(), ReadingError>;
fn try_get_var_int(&mut self) -> Result<VarInt, ReadingError>;
fn try_get_var_long(&mut self) -> Result<VarLong, ReadingError>;
fn try_get_identifer(&mut self) -> Result<Identifier, ReadingError>;
fn try_get_string(&mut self) -> Result<String, ReadingError>;
fn try_get_string_len(&mut self, max_size: usize) -> Result<String, ReadingError>;
/// Reads a boolean. If true, the closure is called, and the returned value is
/// wrapped in Some. Otherwise, this returns None.
fn try_get_option<G>(
&mut self,
val: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
) -> Result<Option<G>, ReadingError>;
fn get_list<G>(
&mut self,
val: impl Fn(&mut Self) -> Result<G, ReadingError>,
) -> Result<Vec<G>, ReadingError>;
fn try_get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError>;
fn try_get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError>;
}
impl<T: Buf> ByteBuf for T {
fn try_get_bool(&mut self) -> Result<bool, ReadingError> {
Ok(self.try_get_u8()? != 0)
}
fn try_get_u8(&mut self) -> Result<u8, ReadingError> {
if size_of::<u8>() <= self.remaining() {
Ok(self.get_u8())
} else {
Err(ReadingError::EOF("u8".to_string()))
}
}
fn try_get_i8(&mut self) -> Result<i8, ReadingError> {
if size_of::<i8>() <= self.remaining() {
Ok(self.get_i8())
} else {
Err(ReadingError::EOF("i8".to_string()))
}
}
fn try_get_u16(&mut self) -> Result<u16, ReadingError> {
if size_of::<u16>() <= self.remaining() {
Ok(self.get_u16())
} else {
Err(ReadingError::EOF("u16".to_string()))
}
}
fn try_get_i16(&mut self) -> Result<i16, ReadingError> {
if size_of::<i16>() <= self.remaining() {
Ok(self.get_i16())
} else {
Err(ReadingError::EOF("i16".to_string()))
}
}
fn try_get_u32(&mut self) -> Result<u32, ReadingError> {
if size_of::<u32>() <= self.remaining() {
Ok(self.get_u32())
} else {
Err(ReadingError::EOF("u32".to_string()))
}
}
fn try_get_i32(&mut self) -> Result<i32, ReadingError> {
if size_of::<i32>() <= self.remaining() {
Ok(self.get_i32())
} else {
Err(ReadingError::EOF("i32".to_string()))
}
}
fn try_get_u64(&mut self) -> Result<u64, ReadingError> {
if size_of::<u64>() <= self.remaining() {
Ok(self.get_u64())
} else {
Err(ReadingError::EOF("u64".to_string()))
}
}
fn try_get_i64(&mut self) -> Result<i64, ReadingError> {
if size_of::<i64>() <= self.remaining() {
Ok(self.get_i64())
} else {
Err(ReadingError::EOF("i64".to_string()))
}
}
fn try_get_f32(&mut self) -> Result<f32, ReadingError> {
if size_of::<f32>() <= self.remaining() {
Ok(self.get_f32())
} else {
Err(ReadingError::EOF("f32".to_string()))
}
}
fn try_get_f64(&mut self) -> Result<f64, ReadingError> {
if size_of::<f64>() <= self.remaining() {
Ok(self.get_f64())
} else {
Err(ReadingError::EOF("f64".to_string()))
}
}
fn try_copy_to_bytes(&mut self, len: usize) -> Result<bytes::Bytes, ReadingError> {
if self.remaining() >= len {
Ok(self.copy_to_bytes(len))
} else {
Err(ReadingError::Message("Unable to copy bytes".to_string()))
}
}
fn try_copy_to_bytes_len(
&mut self,
len: usize,
max_size: usize,
) -> Result<bytes::Bytes, ReadingError> {
if len > max_size {
return Err(ReadingError::Message(
"Tried to copy bytes but length exceeds maximum length".to_string(),
));
}
if self.remaining() >= len {
Ok(self.copy_to_bytes(len))
} else {
Err(ReadingError::Message("Unable to copy bytes".to_string()))
}
}
fn try_copy_to_slice(&mut self, dst: &mut [u8]) -> Result<(), ReadingError> {
if self.remaining() >= dst.len() {
self.copy_to_slice(dst);
Ok(())
} else {
Err(ReadingError::Message("Unable to copy slice".to_string()))
}
}
fn try_get_var_int(&mut self) -> Result<VarInt, ReadingError> {
match VarInt::decode(self) {
Ok(var_int) => Ok(var_int),
Err(error) => match error {
DecodeError::Incomplete => Err(ReadingError::Incomplete("varint".to_string())),
DecodeError::TooLarge => Err(ReadingError::TooLarge("varint".to_string())),
},
}
}
fn try_get_var_long(&mut self) -> Result<VarLong, ReadingError> {
match VarLong::decode(self) {
Ok(var_long) => Ok(var_long),
Err(error) => match error {
DecodeError::Incomplete => Err(ReadingError::Incomplete("varint".to_string())),
DecodeError::TooLarge => Err(ReadingError::TooLarge("varlong".to_string())),
},
}
}
fn try_get_string(&mut self) -> Result<String, ReadingError> {
self.try_get_string_len(i16::MAX as usize)
}
fn try_get_string_len(&mut self, max_size: usize) -> Result<String, ReadingError> {
let size = self.try_get_var_int()?.0;
if size as usize > max_size {
return Err(ReadingError::TooLarge("string".to_string()));
}
let data = self.try_copy_to_bytes(size as usize)?;
if data.len() > max_size {
return Err(ReadingError::TooLarge("string".to_string()));
}
String::from_utf8(data.to_vec()).map_err(|e| ReadingError::Message(e.to_string()))
}
fn try_get_option<G>(
&mut self,
val: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
) -> Result<Option<G>, ReadingError> {
if self.try_get_bool()? {
Ok(Some(val(self)?))
} else {
Ok(None)
}
}
fn get_list<G>(
&mut self,
val: impl Fn(&mut Self) -> Result<G, ReadingError>,
) -> Result<Vec<G>, ReadingError> {
let len = self.try_get_var_int()?.0 as usize;
let mut list = Vec::with_capacity(len);
for _ in 0..len {
list.push(val(self)?);
}
Ok(list)
}
fn try_get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError> {
let mut bytes = [0u8; 16];
self.try_copy_to_slice(&mut bytes)?;
Ok(uuid::Uuid::from_slice(&bytes).expect("Failed to parse UUID"))
}
fn try_get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError> {
self.try_copy_to_bytes(bits.div_ceil(8))
}
fn try_get_identifer(&mut self) -> Result<Identifier, ReadingError> {
match Identifier::decode(self) {
Ok(identifer) => Ok(identifer),
Err(error) => match error {
DecodeError::Incomplete => Err(ReadingError::Incomplete("identifer".to_string())),
DecodeError::TooLarge => Err(ReadingError::TooLarge("identifer".to_string())),
},
}
}
}
pub trait ByteBufMut {
fn put_bool(&mut self, v: bool);
fn put_uuid(&mut self, v: &uuid::Uuid);
fn put_string(&mut self, val: &str);
fn put_string_len(&mut self, val: &str, max_size: usize);
fn put_string_array(&mut self, array: &[&str]);
fn put_bit_set(&mut self, set: &BitSet);
/// Writes `true` if the option is Some, or `false` if None. If the option is
/// some, then it also calls the `write` closure.
fn put_option<G>(&mut self, val: &Option<G>, write: impl FnOnce(&mut Self, &G));
fn put_list<G>(&mut self, list: &[G], write: impl Fn(&mut Self, &G));
fn put_identifier(&mut self, val: &Identifier);
fn put_var_int(&mut self, value: &VarInt);
fn put_varint_arr(&mut self, v: &[i32]);
}
impl<T: BufMut> ByteBufMut for T {
fn put_bool(&mut self, v: bool) {
if v {
self.put_u8(1);
} else {
self.put_u8(0);
}
}
fn put_uuid(&mut self, v: &uuid::Uuid) {
// thats the vanilla way
let pair = v.as_u64_pair();
self.put_u64(pair.0);
self.put_u64(pair.1);
}
fn put_string(&mut self, val: &str) {
self.put_string_len(val, i16::MAX as usize);
}
fn put_string_len(&mut self, val: &str, max_size: usize) {
if val.len() > max_size {
// Should be panic?, I mean its our fault
panic!("String is too big");
}
self.put_var_int(&val.len().into());
self.put(val.as_bytes());
}
fn put_string_array(&mut self, array: &[&str]) {
for string in array {
self.put_string(string)
}
}
fn put_var_int(&mut self, var_int: &VarInt) {
var_int.encode(self);
}
fn put_bit_set(&mut self, bit_set: &BitSet) {
bit_set.encode(self);
}
fn put_option<G>(&mut self, val: &Option<G>, write: impl FnOnce(&mut Self, &G)) {
self.put_bool(val.is_some());
if let Some(v) = val {
write(self, v)
}
}
fn put_list<G>(&mut self, list: &[G], write: impl Fn(&mut Self, &G)) {
self.put_var_int(&list.len().into());
for v in list {
write(self, v);
}
}
fn put_varint_arr(&mut self, v: &[i32]) {
self.put_list(v, |p, &v| p.put_var_int(&v.into()))
}
fn put_identifier(&mut self, val: &Identifier) {
val.encode(self);
}
}
#[cfg(test)]
mod test {
use bytes::{Bytes, BytesMut};
use serde::{Deserialize, Serialize};
use crate::{
bytebuf::{deserializer, serializer},
VarInt,
};
#[test]
fn test_i32_reserialize() {
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug)]
struct Foo {
bar: i32,
}
let foo = Foo { bar: 69 };
let mut bytes = BytesMut::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
foo.serialize(&mut serializer).unwrap();
let deserialized: Foo =
Foo::deserialize(deserializer::Deserializer::new(&mut Bytes::from(bytes))).unwrap();
assert_eq!(foo, deserialized);
}
#[test]
fn test_varint_reserialize() {
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug)]
struct Foo {
bar: VarInt,
}
let foo = Foo { bar: 69.into() };
let mut bytes = BytesMut::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
foo.serialize(&mut serializer).unwrap();
let deserialized: Foo =
Foo::deserialize(deserializer::Deserializer::new(&mut Bytes::from(bytes))).unwrap();
assert_eq!(foo, deserialized);
}
}