-
-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
496 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
Oops, something went wrong.