add codecs folder to git
This commit is contained in:
parent
0633197b62
commit
fd667901cd
53
pumpkin-protocol/src/codec/bit_set.rs
Normal file
53
pumpkin-protocol/src/codec/bit_set.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
|
use crate::bytebuf::ByteBuf;
|
||||||
|
use crate::bytebuf::ByteBufMut;
|
||||||
|
|
||||||
|
use super::{var_int::VarInt, Codec, DecodeError};
|
||||||
|
|
||||||
|
pub struct BitSet(pub VarInt, pub Vec<i64>);
|
||||||
|
|
||||||
|
impl Codec<BitSet> for BitSet {
|
||||||
|
/// The maximum size of the BitSet is `remaining / 8`.
|
||||||
|
const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(usize::MAX) };
|
||||||
|
|
||||||
|
fn written_size(&self) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, write: &mut impl BufMut) {
|
||||||
|
write.put_var_int(&self.0);
|
||||||
|
for b in &self.1 {
|
||||||
|
write.put_i64(*b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode(read: &mut impl Buf) -> Result<Self, DecodeError> {
|
||||||
|
// read length
|
||||||
|
let length = read
|
||||||
|
.try_get_var_int()
|
||||||
|
.map_err(|_| DecodeError::Incomplete)?;
|
||||||
|
// vanilla uses remaining / 8
|
||||||
|
if length.0 as usize >= read.remaining() / 8 {
|
||||||
|
return Err(DecodeError::TooLarge);
|
||||||
|
}
|
||||||
|
let mut array: Vec<i64> = Vec::with_capacity(size_of::<i64>() * length.0 as usize);
|
||||||
|
for _ in 0..length.0 {
|
||||||
|
let long = read.try_get_i64().map_err(|_| DecodeError::Incomplete)?;
|
||||||
|
array.push(long);
|
||||||
|
}
|
||||||
|
Ok(BitSet(length, array))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for BitSet {
|
||||||
|
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
101
pumpkin-protocol/src/codec/identifier.rs
Normal file
101
pumpkin-protocol/src/codec/identifier.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
|
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
use crate::bytebuf::{ByteBuf, ByteBufMut};
|
||||||
|
|
||||||
|
use super::{Codec, DecodeError};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Identifier {
|
||||||
|
pub namespace: String,
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Identifier {
|
||||||
|
pub fn vanilla(path: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
namespace: "minecraft".to_string(),
|
||||||
|
path: path.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Codec<Self> for Identifier {
|
||||||
|
/// The maximum number of bytes a `Identifer` is the same as for a normal String.
|
||||||
|
const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(i16::MAX as usize) };
|
||||||
|
|
||||||
|
fn written_size(&self) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, write: &mut impl BufMut) {
|
||||||
|
write.put_string_len(&self.to_string(), Self::MAX_SIZE.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode(read: &mut impl Buf) -> Result<Self, DecodeError> {
|
||||||
|
let identifer = read
|
||||||
|
.try_get_string_len(Self::MAX_SIZE.get())
|
||||||
|
.map_err(|_| DecodeError::Incomplete)?;
|
||||||
|
match identifer.split_once(":") {
|
||||||
|
Some((namespace, path)) => Ok(Identifier {
|
||||||
|
namespace: namespace.to_string(),
|
||||||
|
path: path.to_string(),
|
||||||
|
}),
|
||||||
|
None => Err(DecodeError::Incomplete),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Identifier {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Identifier {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct IdentifierVisitor;
|
||||||
|
|
||||||
|
impl Visitor<'_> for IdentifierVisitor {
|
||||||
|
type Value = Identifier;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a valid Identifier (namespace:path)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_str(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, identifer: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
match identifer.split_once(":") {
|
||||||
|
Some((namespace, path)) => Ok(Identifier {
|
||||||
|
namespace: namespace.to_string(),
|
||||||
|
path: path.to_string(),
|
||||||
|
}),
|
||||||
|
None => Err(serde::de::Error::custom("Identifier can't be split")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deserializer.deserialize_str(IdentifierVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Identifier {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}:{}", self.namespace, self.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
27
pumpkin-protocol/src/codec/mod.rs
Normal file
27
pumpkin-protocol/src/codec/mod.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub mod bit_set;
|
||||||
|
pub mod identifier;
|
||||||
|
pub mod var_int;
|
||||||
|
pub mod var_long;
|
||||||
|
|
||||||
|
pub trait Codec<T> {
|
||||||
|
const MAX_SIZE: NonZeroUsize;
|
||||||
|
|
||||||
|
fn written_size(&self) -> usize;
|
||||||
|
|
||||||
|
fn encode(&self, write: &mut impl BufMut);
|
||||||
|
|
||||||
|
fn decode(read: &mut impl Buf) -> Result<T, DecodeError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)]
|
||||||
|
pub enum DecodeError {
|
||||||
|
#[error("Incomplete VarInt decode")]
|
||||||
|
Incomplete,
|
||||||
|
#[error("VarInt is too large")]
|
||||||
|
TooLarge,
|
||||||
|
}
|
||||||
157
pumpkin-protocol/src/codec/var_int.rs
Normal file
157
pumpkin-protocol/src/codec/var_int.rs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
use std::{num::NonZeroUsize, ops::Deref};
|
||||||
|
|
||||||
|
use super::{Codec, DecodeError};
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
|
use serde::{
|
||||||
|
de::{SeqAccess, Visitor},
|
||||||
|
Deserialize, Deserializer, Serialize, Serializer,
|
||||||
|
};
|
||||||
|
|
||||||
|
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<Self> 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<Self, DecodeError> {
|
||||||
|
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<i32> for VarInt {
|
||||||
|
fn from(value: i32) -> Self {
|
||||||
|
VarInt(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for VarInt {
|
||||||
|
fn from(value: u32) -> Self {
|
||||||
|
VarInt(value as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for VarInt {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
VarInt(value as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<usize> for VarInt {
|
||||||
|
fn from(value: usize) -> Self {
|
||||||
|
VarInt(value as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VarInt> for i32 {
|
||||||
|
fn from(value: VarInt) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<i32> 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
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<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
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<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut val = 0;
|
||||||
|
for i in 0..VarInt::MAX_SIZE.get() {
|
||||||
|
if let Some(byte) = seq.next_element::<u8>()? {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
158
pumpkin-protocol/src/codec/var_long.rs
Normal file
158
pumpkin-protocol/src/codec/var_long.rs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
use std::{num::NonZeroUsize, ops::Deref};
|
||||||
|
|
||||||
|
use super::{Codec, DecodeError};
|
||||||
|
use bytes::{Buf, BufMut};
|
||||||
|
use serde::{
|
||||||
|
de::{self, SeqAccess, Visitor},
|
||||||
|
Deserialize, Deserializer, Serialize, Serializer,
|
||||||
|
};
|
||||||
|
|
||||||
|
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<Self> for VarLong {
|
||||||
|
/// The maximum number of bytes a `VarLong` can occupy.
|
||||||
|
const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(10) };
|
||||||
|
|
||||||
|
/// 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 BufMut) {
|
||||||
|
let mut x = self.0;
|
||||||
|
for _ in 0..Self::MAX_SIZE.get() {
|
||||||
|
let byte = (x & 0x7F) as u8;
|
||||||
|
x >>= 7;
|
||||||
|
if x == 0 {
|
||||||
|
write.put_slice(&[byte]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write.put_slice(&[byte | 0x80]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode(read: &mut impl Buf) -> Result<Self, DecodeError> {
|
||||||
|
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 |= (i64::from(byte) & 0b01111111) << (i * 7);
|
||||||
|
if byte & 0b10000000 == 0 {
|
||||||
|
return Ok(VarLong(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(DecodeError::TooLarge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for VarLong {
|
||||||
|
fn from(value: i64) -> Self {
|
||||||
|
VarLong(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for VarLong {
|
||||||
|
fn from(value: u32) -> Self {
|
||||||
|
VarLong(value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for VarLong {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
VarLong(value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<usize> for VarLong {
|
||||||
|
fn from(value: usize) -> Self {
|
||||||
|
VarLong(value as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VarLong> for i64 {
|
||||||
|
fn from(value: VarLong) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<i64> 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
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<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
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<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut val = 0;
|
||||||
|
for i in 0..VarLong::MAX_SIZE.get() {
|
||||||
|
if let Some(byte) = seq.next_element::<u8>()? {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user