mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Add support for Slot data decoding (#25)
* Impl Seek for reader in Decode Trait * Add support for Slot data type * Update tests and rust fmt * Add tests for Slot Also fixed bugs I found while testing * Update slot signature * Resolved requested changes Updated decode trait signature and removed unnecessary getters/setters in `Slot`
This commit is contained in:
parent
20546e2fb8
commit
96f5614941
|
@ -3,7 +3,7 @@
|
|||
#![allow(clippy::all, missing_docs)]
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use anyhow::Context;
|
||||
|
@ -58,7 +58,7 @@ impl Encode for BlockState {
|
|||
}
|
||||
|
||||
impl Decode for BlockState {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let id = VarInt::decode(r)?.0;
|
||||
let errmsg = "invalid block state ID";
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::bail;
|
||||
use vek::Vec3;
|
||||
|
@ -38,7 +38,7 @@ impl Encode for BlockPos {
|
|||
}
|
||||
|
||||
impl Decode for BlockPos {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
// Use arithmetic right shift to determine sign.
|
||||
let val = i64::decode(r)?;
|
||||
let x = val >> 38;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Primitive types used in getters and setters on entities.
|
||||
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use crate::protocol::{Decode, Encode, VarInt};
|
||||
|
||||
|
@ -30,7 +30,7 @@ impl Encode for OptionalInt {
|
|||
}
|
||||
|
||||
impl Decode for OptionalInt {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Self(VarInt::decode(r)?.0 as u32))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
//! Namespaced identifiers.
|
||||
//!
|
||||
//!
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use ascii::{AsAsciiStr, AsciiChar, AsciiStr, IntoAsciiString};
|
||||
|
@ -208,7 +210,7 @@ impl Encode for Ident {
|
|||
}
|
||||
|
||||
impl Decode for Ident {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let string = BoundedString::<0, 32767>::decode(r)?.0;
|
||||
Ok(Ident::new(string)?)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ use crate::nbt;
|
|||
mod byte_angle;
|
||||
pub mod codec;
|
||||
pub mod packets;
|
||||
pub mod slot;
|
||||
mod var_int;
|
||||
mod var_long;
|
||||
|
||||
|
@ -35,7 +36,7 @@ pub trait Encode {
|
|||
|
||||
/// Types that can be read from the Minecraft protocol.
|
||||
pub trait Decode: Sized {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self>;
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self>;
|
||||
}
|
||||
|
||||
/// The maximum number of bytes in a single packet.
|
||||
|
@ -48,7 +49,7 @@ impl Encode for () {
|
|||
}
|
||||
|
||||
impl Decode for () {
|
||||
fn decode(_r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(_r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +62,7 @@ impl<T: Encode, U: Encode> Encode for (T, U) {
|
|||
}
|
||||
|
||||
impl<T: Decode, U: Decode> Decode for (T, U) {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok((T::decode(r)?, U::decode(r)?))
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ impl Encode for bool {
|
|||
}
|
||||
|
||||
impl Decode for bool {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let n = r.read_u8()?;
|
||||
ensure!(n < 2, "boolean is not 0 or 1");
|
||||
Ok(n == 1)
|
||||
|
@ -95,7 +96,7 @@ impl Encode for u8 {
|
|||
}
|
||||
|
||||
impl Decode for u8 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_u8()?)
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +109,7 @@ impl Encode for i8 {
|
|||
}
|
||||
|
||||
impl Decode for i8 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_i8()?)
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ impl Encode for u16 {
|
|||
}
|
||||
|
||||
impl Decode for u16 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_u16::<BigEndian>()?)
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +135,7 @@ impl Encode for i16 {
|
|||
}
|
||||
|
||||
impl Decode for i16 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_i16::<BigEndian>()?)
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +148,7 @@ impl Encode for u32 {
|
|||
}
|
||||
|
||||
impl Decode for u32 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_u32::<BigEndian>()?)
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +161,7 @@ impl Encode for i32 {
|
|||
}
|
||||
|
||||
impl Decode for i32 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_i32::<BigEndian>()?)
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +174,7 @@ impl Encode for u64 {
|
|||
}
|
||||
|
||||
impl Decode for u64 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_u64::<BigEndian>()?)
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +187,7 @@ impl Encode for i64 {
|
|||
}
|
||||
|
||||
impl Decode for i64 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(r.read_i64::<BigEndian>()?)
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +204,7 @@ impl Encode for f32 {
|
|||
}
|
||||
}
|
||||
impl Decode for f32 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let f = r.read_f32::<BigEndian>()?;
|
||||
ensure!(f.is_finite(), "attempt to decode non-finite f32 ({f})");
|
||||
Ok(f)
|
||||
|
@ -223,7 +224,7 @@ impl Encode for f64 {
|
|||
}
|
||||
|
||||
impl Decode for f64 {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let f = r.read_f64::<BigEndian>()?;
|
||||
ensure!(f.is_finite(), "attempt to decode non-finite f64 ({f})");
|
||||
Ok(f)
|
||||
|
@ -243,7 +244,7 @@ impl<T: Encode> Encode for Option<T> {
|
|||
}
|
||||
|
||||
impl<T: Decode> Decode for Option<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
if bool::decode(r)? {
|
||||
Ok(Some(T::decode(r)?))
|
||||
} else {
|
||||
|
@ -259,7 +260,7 @@ impl<T: Encode> Encode for Box<T> {
|
|||
}
|
||||
|
||||
impl<T: Decode> Decode for Box<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Box::new(T::decode(r)?))
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +272,7 @@ impl Encode for Box<str> {
|
|||
}
|
||||
|
||||
impl Decode for Box<str> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(String::decode(r)?.into_boxed_str())
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +320,7 @@ impl<T, const MIN: i64, const MAX: i64> Decode for BoundedInt<T, MIN, MAX>
|
|||
where
|
||||
T: Decode + Copy + Into<i64>,
|
||||
{
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let res = T::decode(r)?;
|
||||
let val = res.into();
|
||||
|
||||
|
@ -339,7 +340,7 @@ impl Encode for String {
|
|||
}
|
||||
|
||||
impl Decode for String {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
decode_string_bounded(0, 32767, r)
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +371,7 @@ impl<const MIN: usize, const MAX: usize> Encode for BoundedString<MIN, MAX> {
|
|||
}
|
||||
|
||||
impl<const MIN: usize, const MAX: usize> Decode for BoundedString<MIN, MAX> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
decode_string_bounded(MIN, MAX, r).map(Self)
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +389,7 @@ impl<T: Encode> Encode for Vec<T> {
|
|||
}
|
||||
|
||||
impl<T: Decode> Decode for Vec<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
decode_array_bounded(0, usize::MAX, r)
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +401,7 @@ impl<T: Encode> Encode for Box<[T]> {
|
|||
}
|
||||
|
||||
impl<T: Decode> Decode for Box<[T]> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
decode_array_bounded(0, usize::MAX, r).map(|v| v.into_boxed_slice())
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +413,7 @@ impl<T: Encode, const N: usize> Encode for [T; N] {
|
|||
}
|
||||
|
||||
impl<T: Decode, const N: usize> Decode for [T; N] {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let mut elems = ArrayVec::new();
|
||||
for _ in 0..N {
|
||||
elems.push(T::decode(r)?);
|
||||
|
@ -448,19 +449,19 @@ impl<T: Encode> Encode for Vec4<T> {
|
|||
}
|
||||
|
||||
impl<T: Decode> Decode for Vec2<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Vec2::new(T::decode(r)?, T::decode(r)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> Decode for Vec3<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Vec3::new(T::decode(r)?, T::decode(r)?, T::decode(r)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode> Decode for Vec4<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Vec4::new(
|
||||
T::decode(r)?,
|
||||
T::decode(r)?,
|
||||
|
@ -484,7 +485,7 @@ impl<T: Encode, const MIN: usize, const MAX: usize> Encode for BoundedArray<T, M
|
|||
}
|
||||
|
||||
impl<T: Decode, const MIN: usize, const MAX: usize> Decode for BoundedArray<T, MIN, MAX> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
decode_array_bounded(MIN, MAX, r).map(Self)
|
||||
}
|
||||
}
|
||||
|
@ -503,7 +504,7 @@ impl Encode for Uuid {
|
|||
}
|
||||
|
||||
impl Decode for Uuid {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Uuid::from_u128(r.read_u128::<BigEndian>()?))
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +516,7 @@ impl Encode for nbt::Compound {
|
|||
}
|
||||
|
||||
impl Decode for nbt::Compound {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(nbt::binary::from_reader(r)?)
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +533,7 @@ impl<T: Serialize> Encode for NbtBridge<T> {
|
|||
}
|
||||
|
||||
impl<T: DeserializeOwned> Decode for NbtBridge<T> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
Ok(Self(nbt::binary::from_reader(r)?))
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +545,7 @@ impl Encode for BitVec<u64> {
|
|||
}
|
||||
|
||||
impl Decode for BitVec<u64> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
BitVec::try_from_vec(Vec::decode(r)?)
|
||||
.map_err(|_| anyhow!("Array is too long for bit vector"))
|
||||
}
|
||||
|
@ -557,7 +558,7 @@ impl Encode for BitBox<u64> {
|
|||
}
|
||||
|
||||
impl Decode for BitBox<u64> {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
BitVec::decode(r).map(|v| v.into_boxed_bitslice())
|
||||
}
|
||||
}
|
||||
|
@ -569,7 +570,7 @@ impl Decode for BitBox<u64> {
|
|||
pub struct RawBytes(pub Vec<u8>);
|
||||
|
||||
impl Decode for RawBytes {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let mut buf = Vec::new();
|
||||
r.read_to_end(&mut buf)?;
|
||||
Ok(RawBytes(buf))
|
||||
|
@ -645,7 +646,7 @@ pub(crate) fn encode_string_bounded(
|
|||
pub(crate) fn decode_string_bounded(
|
||||
min: usize,
|
||||
max: usize,
|
||||
r: &mut impl Read,
|
||||
r: &mut &[u8],
|
||||
) -> anyhow::Result<String> {
|
||||
assert!(min <= max);
|
||||
|
||||
|
@ -665,7 +666,7 @@ pub(crate) fn decode_string_bounded(
|
|||
pub(crate) fn decode_array_bounded<T: Decode>(
|
||||
min: usize,
|
||||
max: usize,
|
||||
r: &mut impl Read,
|
||||
r: &mut &[u8],
|
||||
) -> anyhow::Result<Vec<T>> {
|
||||
assert!(min <= max);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use crate::protocol::{Decode, Encode};
|
||||
|
||||
|
@ -23,7 +23,7 @@ impl Encode for ByteAngle {
|
|||
}
|
||||
|
||||
impl Decode for ByteAngle {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
u8::decode(r).map(ByteAngle)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#![macro_use]
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::{bail, ensure, Context};
|
||||
use bitvec::prelude::BitVec;
|
||||
|
@ -42,7 +42,7 @@ pub trait EncodePacket: fmt::Debug {
|
|||
/// the body of the packet.
|
||||
pub trait DecodePacket: Sized + fmt::Debug {
|
||||
/// Reads a packet from the Minecraft protocol, including its packet ID.
|
||||
fn decode_packet(r: &mut impl Read) -> anyhow::Result<Self>;
|
||||
fn decode_packet(r: &mut &[u8]) -> anyhow::Result<Self>;
|
||||
}
|
||||
|
||||
/// Defines a struct which implements [`Encode`] and [`Decode`].
|
||||
|
@ -79,7 +79,7 @@ macro_rules! def_struct {
|
|||
}
|
||||
|
||||
impl Decode for $name {
|
||||
fn decode(_r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(_r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
$(
|
||||
let $field: $typ = Decode::decode(_r)
|
||||
.context(concat!("failed to read field `", stringify!($field), "` from struct `", stringify!($name), "`"))?;
|
||||
|
@ -149,7 +149,7 @@ macro_rules! def_enum {
|
|||
}
|
||||
|
||||
impl Decode for $name {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let tag_ctx = concat!("failed to read enum tag for `", stringify!($name), "`");
|
||||
let tag = <$tag_ty>::decode(r).context(tag_ctx)?.into();
|
||||
match tag {
|
||||
|
@ -261,7 +261,7 @@ macro_rules! def_bitfield {
|
|||
}
|
||||
|
||||
impl Decode for $name {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
<$inner_ty>::decode(r).map(Self)
|
||||
}
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ macro_rules! def_packet_group {
|
|||
}
|
||||
|
||||
impl DecodePacket for $packet {
|
||||
fn decode_packet(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode_packet(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let packet_id = VarInt::decode(r).context("failed to read packet ID")?.0;
|
||||
|
||||
ensure!(
|
||||
|
@ -314,7 +314,7 @@ macro_rules! def_packet_group {
|
|||
)*
|
||||
|
||||
impl DecodePacket for $group_name {
|
||||
fn decode_packet(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode_packet(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let packet_id = VarInt::decode(r)
|
||||
.context(concat!("failed to read ", stringify!($group_name), " packet ID"))?.0;
|
||||
|
||||
|
|
148
src/protocol/slot.rs
Normal file
148
src/protocol/slot.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
use byteorder::ReadBytesExt;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::nbt::Compound;
|
||||
use crate::protocol::{Decode, Encode, VarInt};
|
||||
|
||||
/// Represents a slot in an inventory.
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub enum Slot {
|
||||
#[default]
|
||||
Empty,
|
||||
Present {
|
||||
item_id: VarInt,
|
||||
item_count: u8,
|
||||
nbt: Option<Compound>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Encode for Slot {
|
||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||
match self {
|
||||
Slot::Empty => false.encode(w),
|
||||
Slot::Present {
|
||||
item_id,
|
||||
item_count,
|
||||
nbt,
|
||||
} => {
|
||||
true.encode(w)?;
|
||||
item_id.encode(w)?;
|
||||
item_count.encode(w)?;
|
||||
match &nbt {
|
||||
Some(n) => n.encode(w),
|
||||
None => 0u8.encode(w),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for Slot {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let present = bool::decode(r)?;
|
||||
if !present {
|
||||
return Ok(Slot::Empty);
|
||||
}
|
||||
Ok(Slot::Present {
|
||||
item_id: VarInt::decode(r)?,
|
||||
item_count: u8::decode(r)?,
|
||||
nbt: if r.get(0) == Some(&0) {
|
||||
r.read_u8()?;
|
||||
None
|
||||
} else {
|
||||
Some(Compound::decode(r)?)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serde_nbt::Value;
|
||||
|
||||
#[test]
|
||||
fn slot_with_nbt() {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
|
||||
// Example nbt blob
|
||||
// https://wiki.vg/Slot_Data
|
||||
let mut nbt = Compound::new();
|
||||
{
|
||||
let mut enchant = Compound::new();
|
||||
enchant.insert("id".to_string(), Value::Short(1));
|
||||
enchant.insert("lvl".to_string(), Value::Short(1));
|
||||
|
||||
let enchant_list = vec![enchant];
|
||||
nbt.insert(
|
||||
"StoredEnchantments".to_string(),
|
||||
Value::List(enchant_list.into()),
|
||||
);
|
||||
nbt.insert("Unbreakable".to_string(), Value::Int(1));
|
||||
}
|
||||
|
||||
Slot::Present {
|
||||
item_id: VarInt(1),
|
||||
item_count: 1,
|
||||
nbt: Some(nbt),
|
||||
}
|
||||
.encode(&mut buf)
|
||||
.unwrap();
|
||||
|
||||
let mut slice = buf.as_slice();
|
||||
let (item_id, item_count, nbt) = match Slot::decode(&mut slice).unwrap() {
|
||||
Slot::Empty => {
|
||||
panic!("Slot should be present")
|
||||
}
|
||||
Slot::Present {
|
||||
item_id,
|
||||
item_count,
|
||||
nbt,
|
||||
} => (item_id, item_count, nbt),
|
||||
};
|
||||
assert_eq!(1, item_id.0);
|
||||
assert_eq!(1, item_count);
|
||||
assert_eq!(&Value::Int(1), nbt.unwrap().get("Unbreakable").unwrap());
|
||||
|
||||
assert!(slice.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slot_no_nbt() {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
|
||||
Slot::Present {
|
||||
item_id: VarInt(1),
|
||||
item_count: 1,
|
||||
nbt: None,
|
||||
}
|
||||
.encode(&mut buf)
|
||||
.unwrap();
|
||||
|
||||
let mut slice = buf.as_slice();
|
||||
let nbt = match Slot::decode(&mut slice).unwrap() {
|
||||
Slot::Empty => {
|
||||
panic!("Slot should be present")
|
||||
}
|
||||
Slot::Present { nbt, .. } => nbt,
|
||||
};
|
||||
|
||||
assert_eq!(None, nbt);
|
||||
|
||||
assert!(slice.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_slot() {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
|
||||
Slot::Empty.encode(&mut buf).unwrap();
|
||||
|
||||
let mut slice = buf.as_slice();
|
||||
if let Slot::Present { .. } = Slot::decode(&mut slice).unwrap() {
|
||||
panic!("Slot should be empty")
|
||||
};
|
||||
|
||||
assert!(slice.is_empty());
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::bail;
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
|
@ -47,7 +47,7 @@ impl Encode for VarInt {
|
|||
}
|
||||
|
||||
impl Decode for VarInt {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let mut val = 0;
|
||||
for i in 0..Self::MAX_SIZE {
|
||||
let byte = r.read_u8()?;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::bail;
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
|
@ -30,7 +30,7 @@ impl Encode for VarLong {
|
|||
}
|
||||
|
||||
impl Decode for VarLong {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let mut val = 0;
|
||||
for i in 0..Self::MAX_SIZE {
|
||||
let byte = r.read_u8()?;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use serde::de::Visitor;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
@ -455,7 +455,7 @@ impl Encode for Text {
|
|||
}
|
||||
|
||||
impl Decode for Text {
|
||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
|
||||
let string = BoundedString::<0, 262144>::decode(r)?;
|
||||
Ok(serde_json::from_str(&string.0)?)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue