extern crate self as mcproto_types;
pub mod basic;
pub mod chat_type;
pub mod component;
pub mod contextual;
pub mod debug;
pub mod entity_metadata;
pub mod json_text_component;
pub mod lightdata;
pub mod nbt;
pub mod profile;
pub mod recipe;
pub mod slot;
pub mod sound_event;
pub mod teleport_flags;
pub mod text_component;
pub use basic::*;
pub use chat_type::*;
pub use component::*;
pub use contextual::*;
pub use debug::*;
pub use entity_metadata::*;
pub use json_text_component::*;
pub use lightdata::*;
pub use nbt::*;
pub use profile::*;
pub use recipe::*;
pub use slot::*;
pub use sound_event::*;
pub use teleport_flags::*;
pub use text_component::*;
pub use mcproto_derive::{ProtocolEnum, TypeStructCodec};
pub trait ContextualCodec {
fn encode_with_context(
&self,
writer: &mut impl std::io::Write,
context: &contextual::Context,
) -> Result<(), mcproto_codec::error::CodecError>;
fn decode_with_context(
reader: &mut impl std::io::Read,
context: &contextual::Context,
) -> Result<Self, mcproto_codec::error::CodecError>
where
Self: Sized;
}
pub trait TypeCodec {
fn encode(
&self,
writer: &mut impl std::io::Write,
) -> Result<(), mcproto_codec::error::CodecError>;
fn decode(reader: &mut impl std::io::Read) -> Result<Self, mcproto_codec::error::CodecError>
where
Self: Sized;
}
pub trait EnumRepr: TypeCodec {
#[must_use]
fn from_discriminant(value: i128) -> Option<Self>
where
Self: Sized;
#[must_use]
fn discriminant(&self) -> i128;
}
pub trait ProtocolEnum: Sized {
type Repr: EnumRepr;
#[must_use]
fn discriminant(&self) -> i128;
#[must_use]
fn to_repr(&self) -> Option<Self::Repr>;
#[must_use]
fn from_repr(repr: Self::Repr) -> Option<Self>;
}
#[doc(hidden)]
pub mod __private {
use std::io::{self, Read, Write};
pub use mcproto_codec::error::{CodecError, CodecKind};
use super::{EnumRepr, ProtocolEnum, TypeCodec};
use mcproto_codec::error::{CodecOperation, InvalidEncodingReason};
pub fn encode_protocol_enum<E: ProtocolEnum>(
value: &E,
writer: &mut impl Write,
) -> Result<(), CodecError> {
let repr = value.to_repr().ok_or_else(|| {
CodecError::invalid_encoding_for_operation(
CodecKind::Enum,
CodecOperation::Write,
0,
InvalidEncodingReason::EnumDiscriminantOutOfRange {
value: value.discriminant(),
},
)
})?;
repr.encode(writer)
.map_err(|error| error.with_context(CodecKind::Enum))
}
pub fn decode_protocol_enum<E: ProtocolEnum>(reader: &mut impl Read) -> Result<E, CodecError> {
let mut reader = CountingReader {
reader,
bytes_processed: 0,
};
let repr =
E::Repr::decode(&mut reader).map_err(|error| error.with_context(CodecKind::Enum))?;
let value = repr.discriminant();
E::from_repr(repr).ok_or_else(|| {
CodecError::invalid_encoding(
CodecKind::Enum,
reader.bytes_processed,
InvalidEncodingReason::InvalidEnumValue { value },
)
})
}
struct CountingReader<'a, R> {
reader: &'a mut R,
bytes_processed: usize,
}
impl<R: Read> Read for CountingReader<'_, R> {
fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
let read = self.reader.read(buffer)?;
self.bytes_processed += read;
Ok(read)
}
}
}
impl<T> ContextualCodec for T
where
T: TypeCodec,
{
fn encode_with_context(
&self,
writer: &mut impl std::io::Write,
_context: &contextual::Context,
) -> Result<(), mcproto_codec::error::CodecError> {
self.encode(writer)
}
fn decode_with_context(
reader: &mut impl std::io::Read,
_context: &contextual::Context,
) -> Result<Self, mcproto_codec::error::CodecError>
where
Self: Sized,
{
Self::decode(reader)
}
}
impl<T> TypeCodec for Box<T>
where
T: TypeCodec,
{
fn encode(
&self,
writer: &mut impl std::io::Write,
) -> Result<(), mcproto_codec::error::CodecError> {
self.as_ref().encode(writer)
}
fn decode(reader: &mut impl std::io::Read) -> Result<Self, mcproto_codec::error::CodecError> {
T::decode(reader).map(Self::new)
}
}