diff --git a/crates/packet_inspector/src/main.rs b/crates/packet_inspector/src/main.rs
index d13a221..6979001 100644
--- a/crates/packet_inspector/src/main.rs
+++ b/crates/packet_inspector/src/main.rs
@@ -23,7 +23,7 @@ use valence_protocol::packet::c2s::status::{QueryPingC2s, QueryRequestC2s};
use valence_protocol::packet::s2c::login::LoginSuccessS2c;
use valence_protocol::packet::s2c::status::{QueryPongS2c, QueryResponseS2c};
use valence_protocol::packet::{C2sPlayPacket, S2cLoginPacket, S2cPlayPacket};
-use valence_protocol::{DecodePacket, EncodePacket};
+use valence_protocol::Packet;
#[derive(Parser, Clone, Debug)]
#[clap(author, version, about)]
@@ -65,7 +65,7 @@ struct State {
impl State {
pub async fn rw_packet<'a, P>(&'a mut self) -> anyhow::Result
where
- P: DecodePacket<'a> + EncodePacket,
+ P: Packet<'a>,
{
while !self.dec.has_next_packet()? {
self.dec.reserve(4096);
diff --git a/crates/valence/src/client.rs b/crates/valence/src/client.rs
index c20c5e1..8c1b529 100644
--- a/crates/valence/src/client.rs
+++ b/crates/valence/src/client.rs
@@ -29,7 +29,7 @@ use valence_protocol::text::Text;
use valence_protocol::types::{GameMode, GlobalPos, Property, SoundCategory};
use valence_protocol::username::Username;
use valence_protocol::var_int::VarInt;
-use valence_protocol::EncodePacket;
+use valence_protocol::Packet;
use crate::dimension::DimensionId;
use crate::entity::data::Player;
@@ -173,9 +173,9 @@ impl Client {
///
/// If encoding the packet fails, the client is disconnected. Has no
/// effect if the client is already disconnected.
- pub fn write_packet
(&mut self, pkt: &P)
+ pub fn write_packet<'a, P>(&mut self, pkt: &P)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
self.enc.write_packet(pkt);
}
@@ -606,9 +606,9 @@ impl Client {
}
impl WritePacket for Client {
- fn write_packet
(&mut self, packet: &P)
+ fn write_packet<'a, P>(&mut self, packet: &P)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
self.enc.write_packet(packet)
}
diff --git a/crates/valence/src/instance.rs b/crates/valence/src/instance.rs
index 504dba6..b62a76f 100644
--- a/crates/valence/src/instance.rs
+++ b/crates/valence/src/instance.rs
@@ -16,7 +16,7 @@ use valence_protocol::packet::s2c::play::{OverlayMessageS2c, ParticleS2c, PlaySo
use valence_protocol::sound::Sound;
use valence_protocol::text::Text;
use valence_protocol::types::SoundCategory;
-use valence_protocol::EncodePacket;
+use valence_protocol::Packet;
use crate::dimension::DimensionId;
use crate::entity::McEntity;
@@ -313,9 +313,9 @@ impl Instance {
///
/// This is more efficient than sending the packet to each client
/// individually.
- pub fn write_packet
(&mut self, pkt: &P)
+ pub fn write_packet<'a, P>(&mut self, pkt: &P)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
PacketWriter::new(
&mut self.packet_buf,
@@ -340,9 +340,9 @@ impl Instance {
///
/// This is more efficient than sending the packet to each client
/// individually.
- pub fn write_packet_at
(&mut self, pkt: &P, pos: impl Into)
+ pub fn write_packet_at<'a, P>(&mut self, pkt: &P, pos: impl Into)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
let pos = pos.into();
if let Some(cell) = self.partition.get_mut(&pos) {
diff --git a/crates/valence/src/packet.rs b/crates/valence/src/packet.rs
index 744d518..d85833b 100644
--- a/crates/valence/src/packet.rs
+++ b/crates/valence/src/packet.rs
@@ -2,20 +2,20 @@ use std::io::Write;
use tracing::warn;
use valence_protocol::codec::{encode_packet, encode_packet_compressed, PacketEncoder};
-use valence_protocol::EncodePacket;
+use valence_protocol::Packet;
pub(crate) trait WritePacket {
- fn write_packet(&mut self, packet: &P)
+ fn write_packet<'a, P>(&mut self, packet: &P)
where
- P: EncodePacket + ?Sized;
+ P: Packet<'a>;
fn write_packet_bytes(&mut self, bytes: &[u8]);
}
impl WritePacket for &mut W {
- fn write_packet(&mut self, packet: &P)
+ fn write_packet<'a, P>(&mut self, packet: &P)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
(*self).write_packet(packet)
}
@@ -42,9 +42,9 @@ impl<'a> PacketWriter<'a> {
}
impl WritePacket for PacketWriter<'_> {
- fn write_packet
(&mut self, pkt: &P)
+ fn write_packet<'a, P>(&mut self, pkt: &P)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
let res = if let Some(threshold) = self.threshold {
encode_packet_compressed(self.buf, pkt, threshold, self.scratch)
@@ -65,9 +65,9 @@ impl WritePacket for PacketWriter<'_> {
}
impl WritePacket for PacketEncoder {
- fn write_packet
(&mut self, packet: &P)
+ fn write_packet<'a, P>(&mut self, packet: &P)
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
if let Err(e) = self.append_packet(packet) {
warn!("failed to write packet: {e:#}");
diff --git a/crates/valence/src/server/connection.rs b/crates/valence/src/server/connection.rs
index a77cf28..1578bc2 100644
--- a/crates/valence/src/server/connection.rs
+++ b/crates/valence/src/server/connection.rs
@@ -10,7 +10,7 @@ use tokio::task::JoinHandle;
use tokio::time::timeout;
use tracing::debug;
use valence_protocol::codec::{PacketDecoder, PacketEncoder};
-use valence_protocol::{DecodePacket, EncodePacket};
+use valence_protocol::Packet;
use crate::client::{Client, ClientConnection};
use crate::server::byte_channel::{
@@ -52,9 +52,9 @@ where
}
}
- pub async fn send_packet
(&mut self, pkt: &P) -> anyhow::Result<()>
+ pub async fn send_packet<'a, P>(&mut self, pkt: &P) -> anyhow::Result<()>
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
self.enc.append_packet(pkt)?;
let bytes = self.enc.take();
@@ -64,7 +64,7 @@ where
pub async fn recv_packet<'a, P>(&'a mut self) -> anyhow::Result
where
- P: DecodePacket<'a>,
+ P: Packet<'a>,
{
timeout(self.timeout, async {
while !self.dec.has_next_packet()? {
diff --git a/crates/valence/src/unit_test/util.rs b/crates/valence/src/unit_test/util.rs
index dfea93f..3cff187 100644
--- a/crates/valence/src/unit_test/util.rs
+++ b/crates/valence/src/unit_test/util.rs
@@ -6,7 +6,7 @@ use bytes::BytesMut;
use valence_protocol::codec::{PacketDecoder, PacketEncoder};
use valence_protocol::packet::S2cPlayPacket;
use valence_protocol::username::Username;
-use valence_protocol::EncodePacket;
+use valence_protocol::Packet;
use crate::client::{Client, ClientConnection};
use crate::config::{ConnectionMode, ServerPlugin};
@@ -135,7 +135,7 @@ impl MockClientHelper {
/// Inject a packet to be treated as a packet inbound to the server. Panics
/// if the packet cannot be sent.
- pub fn send(&mut self, packet: &(impl EncodePacket + ?Sized)) {
+ pub fn send<'a>(&mut self, packet: &impl Packet<'a>) {
self.enc
.append_packet(packet)
.expect("failed to encode packet");
diff --git a/crates/valence_protocol/src/codec.rs b/crates/valence_protocol/src/codec.rs
index b154bda..45f65c7 100644
--- a/crates/valence_protocol/src/codec.rs
+++ b/crates/valence_protocol/src/codec.rs
@@ -5,7 +5,7 @@ use bytes::{Buf, BufMut, BytesMut};
use tracing::debug;
use crate::var_int::{VarInt, VarIntDecodeError};
-use crate::{DecodePacket, Encode, EncodePacket, Result, MAX_PACKET_SIZE};
+use crate::{Encode, Packet, Result, MAX_PACKET_SIZE};
/// The AES block cipher with a 128 bit key, using the CFB-8 mode of
/// operation.
@@ -33,9 +33,9 @@ impl PacketEncoder {
self.buf.extend_from_slice(bytes)
}
- pub fn prepend_packet
(&mut self, pkt: &P) -> Result<()>
+ pub fn prepend_packet<'a, P>(&mut self, pkt: &P) -> Result<()>
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
let start_len = self.buf.len();
self.append_packet(pkt)?;
@@ -54,9 +54,9 @@ impl PacketEncoder {
Ok(())
}
- pub fn append_packet
(&mut self, pkt: &P) -> Result<()>
+ pub fn append_packet<'a, P>(&mut self, pkt: &P) -> Result<()>
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
let start_len = self.buf.len();
@@ -171,9 +171,9 @@ impl PacketEncoder {
}
}
-pub fn encode_packet
(buf: &mut Vec, pkt: &P) -> Result<()>
+pub fn encode_packet<'a, P>(buf: &mut Vec, pkt: &P) -> Result<()>
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
let start_len = buf.len();
@@ -201,14 +201,14 @@ where
}
#[cfg(feature = "compression")]
-pub fn encode_packet_compressed(
+pub fn encode_packet_compressed<'a, P>(
buf: &mut Vec,
pkt: &P,
threshold: u32,
scratch: &mut Vec,
) -> Result<()>
where
- P: EncodePacket + ?Sized,
+ P: Packet<'a>,
{
use std::io::Read;
@@ -287,7 +287,7 @@ impl PacketDecoder {
pub fn try_next_packet<'a, P>(&'a mut self) -> Result>
where
- P: DecodePacket<'a>,
+ P: Packet<'a>,
{
self.buf.advance(self.cursor);
self.cursor = 0;
@@ -368,7 +368,7 @@ impl PacketDecoder {
#[track_caller]
pub fn collect_into_vec<'a, P>(&'a mut self) -> Result>
where
- P: DecodePacket<'a>,
+ P: Packet<'a>,
{
#[cfg(feature = "encryption")]
assert!(
@@ -512,7 +512,7 @@ mod tests {
#[cfg(feature = "encryption")]
const CRYPT_KEY: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
- #[derive(PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
+ #[derive(PartialEq, Debug, Encode, Decode, Packet)]
#[packet_id = 42]
struct TestPacket<'a> {
a: bool,
diff --git a/crates/valence_protocol/src/lib.rs b/crates/valence_protocol/src/lib.rs
index 4b2b6f9..6f02f34 100644
--- a/crates/valence_protocol/src/lib.rs
+++ b/crates/valence_protocol/src/lib.rs
@@ -75,7 +75,7 @@ use std::io::Write;
use std::{fmt, io};
pub use anyhow::{Error, Result};
-pub use valence_protocol_macros::{ident_str, Decode, DecodePacket, Encode, EncodePacket};
+pub use valence_protocol_macros::{ident_str, Decode, Encode, Packet};
pub use {uuid, valence_nbt as nbt};
/// The Minecraft protocol version this library currently targets.
@@ -111,7 +111,7 @@ pub mod __private {
pub use anyhow::{anyhow, bail, ensure, Context, Result};
pub use crate::var_int::VarInt;
- pub use crate::{Decode, DecodePacket, Encode, EncodePacket};
+ pub use crate::{Decode, Encode, Packet};
}
/// The maximum number of bytes in a single Minecraft packet.
@@ -249,20 +249,21 @@ pub trait Decode<'a>: Sized {
fn decode(r: &mut &'a [u8]) -> Result;
}
-/// Like [`Encode`], but implementations must write a leading [`VarInt`] packet
-/// ID before any other data.
+/// Like [`Encode`] + [`Decode`], but implementations must read and write a
+/// leading [`VarInt`] packet ID before any other data.
///
/// # Deriving
///
/// This trait can be implemented automatically by using the
-/// [`EncodePacket`][macro] derive macro. The trait is implemented by writing
-/// the packet ID provided in the `#[packet_id = ...]` helper attribute followed
-/// by a call to [`Encode::encode`].
+/// [`Packet`][macro] derive macro. The trait is implemented by reading or
+/// writing the packet ID provided in the `#[packet_id = ...]` helper attribute
+/// followed by a call to [`Encode::encode`] or [`Decode::decode`]. The target
+/// type must implement [`Encode`], [`Decode`], and [`fmt::Debug`].
///
/// ```
-/// use valence_protocol::{Encode, EncodePacket};
+/// use valence_protocol::{Encode, Packet};
///
-/// #[derive(Encode, EncodePacket, Debug)]
+/// #[derive(Encode, Packet, Debug)]
/// #[packet_id = 42]
/// struct MyStruct {
/// first: i32,
@@ -275,60 +276,24 @@ pub trait Decode<'a>: Sized {
/// println!("{buf:?}");
/// ```
///
-/// [macro]: valence_protocol_macros::DecodePacket
+/// [macro]: valence_protocol_macros::Packet
/// [`VarInt`]: var_int::VarInt
-pub trait EncodePacket: fmt::Debug {
- /// The packet ID that is written when [`Self::encode_packet`] is called. A
- /// negative value indicates that the packet ID is not statically known.
+pub trait Packet<'a>: Sized + fmt::Debug {
+ /// The packet returned by [`Self::packet_id`]. If the packet ID is not
+ /// statically known, then a negative value is used instead.
const PACKET_ID: i32 = -1;
-
/// Like [`Encode::encode`], but a leading [`VarInt`] packet ID must be
/// written first.
///
/// [`VarInt`]: var_int::VarInt
fn encode_packet(&self, w: impl Write) -> Result<()>;
-}
-
-/// Like [`Decode`], but implementations must read a leading [`VarInt`] packet
-/// ID before any other data.
-///
-/// # Deriving
-///
-/// This trait can be implemented automatically by using the
-/// [`DecodePacket`][macro] derive macro. The trait is implemented by reading
-/// the packet ID provided in the `#[packet_id = ...]` helper attribute followed
-/// by a call to [`Decode::decode`].
-///
-/// ```
-/// use valence_protocol::{Decode, DecodePacket};
-///
-/// #[derive(Decode, DecodePacket, Debug)]
-/// #[packet_id = 42]
-/// struct MyStruct {
-/// first: i32,
-/// }
-///
-/// let buf = [42, 0, 0, 0, 0];
-/// let mut r = buf.as_slice();
-///
-/// let value = MyStruct::decode_packet(&mut r).unwrap();
-///
-/// assert_eq!(value.first, 0);
-/// assert!(r.is_empty());
-/// ```
-///
-/// [macro]: valence_protocol::DecodePacket
-/// [`VarInt`]: var_int::VarInt
-pub trait DecodePacket<'a>: Sized + fmt::Debug {
- /// The packet ID that is read when [`Self::decode_packet`] is called. A
- /// negative value indicates that the packet ID is not statically known.
- const PACKET_ID: i32 = -1;
-
/// Like [`Decode::decode`], but a leading [`VarInt`] packet ID must be read
/// first.
///
/// [`VarInt`]: var_int::VarInt
fn decode_packet(r: &mut &'a [u8]) -> Result;
+ /// Returns the ID of this packet.
+ fn packet_id(&self) -> i32;
}
#[allow(dead_code)]
@@ -336,7 +301,7 @@ pub trait DecodePacket<'a>: Sized + fmt::Debug {
mod derive_tests {
use super::*;
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 1]
struct RegularStruct {
foo: i32,
@@ -344,30 +309,30 @@ mod derive_tests {
baz: f64,
}
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 2]
struct UnitStruct;
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 3]
struct EmptyStruct {}
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 4]
struct TupleStruct(i32, bool, f64);
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 5]
- struct StructWithGenerics<'z, T: fmt::Debug = ()> {
+ struct StructWithGenerics<'z, T = ()> {
foo: &'z str,
bar: T,
}
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 6]
- struct TupleStructWithGenerics<'z, T: fmt::Debug = ()>(&'z str, i32, T);
+ struct TupleStructWithGenerics<'z, T = ()>(&'z str, i32, T);
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 7]
enum RegularEnum {
Empty,
@@ -375,13 +340,13 @@ mod derive_tests {
Fields { foo: i32, bar: bool, baz: f64 },
}
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 8]
enum EmptyEnum {}
- #[derive(Encode, EncodePacket, Decode, DecodePacket, Debug)]
+ #[derive(Encode, Decode, Packet, Debug)]
#[packet_id = 0xbeef]
- enum EnumWithGenericsAndTags<'z, T: fmt::Debug = ()> {
+ enum EnumWithGenericsAndTags<'z, T = ()> {
#[tag = 5]
First {
foo: &'z str,
@@ -396,7 +361,7 @@ mod derive_tests {
#[allow(unconditional_recursion)]
fn has_impls<'a, T>()
where
- T: Encode + EncodePacket + Decode<'a> + DecodePacket<'a>,
+ T: Encode + Decode<'a> + Packet<'a>,
{
has_impls::();
has_impls::();
diff --git a/crates/valence_protocol/src/packet.rs b/crates/valence_protocol/src/packet.rs
index 45b3787..bdb3772 100644
--- a/crates/valence_protocol/src/packet.rs
+++ b/crates/valence_protocol/src/packet.rs
@@ -12,8 +12,7 @@ pub use s2c::login::S2cLoginPacket;
pub use s2c::play::S2cPlayPacket;
pub use s2c::status::S2cStatusPacket;
-/// Defines an enum of packets and implements `EncodePacket` and `DecodePacket`
-/// for each.
+/// Defines an enum of packets and implements `Packet` for each.
macro_rules! packet_group {
(
$(#[$attrs:meta])*
@@ -35,9 +34,13 @@ macro_rules! packet_group {
}
}
- impl$(<$life>)? crate::EncodePacket for $packet$(<$life>)? {
+ impl<$enum_life> crate::Packet<$enum_life> for $packet$(<$life>)? {
const PACKET_ID: i32 = $packet_id;
+ fn packet_id(&self) -> i32 {
+ $packet_id
+ }
+
#[allow(unused_imports)]
fn encode_packet(&self, mut w: impl std::io::Write) -> crate::Result<()> {
use ::valence_protocol::__private::{Encode, Context, VarInt};
@@ -48,10 +51,6 @@ macro_rules! packet_group {
self.encode(w)
}
- }
-
- impl<$enum_life> crate::DecodePacket<$enum_life> for $packet$(<$life>)? {
- const PACKET_ID: i32 = $packet_id;
#[allow(unused_imports)]
fn decode_packet(r: &mut &$enum_life [u8]) -> ::valence_protocol::__private::Result {
@@ -65,7 +64,15 @@ macro_rules! packet_group {
}
)*
- impl<$enum_life> crate::EncodePacket for $enum_name<$enum_life> {
+ impl<$enum_life> crate::Packet<$enum_life> for $enum_name<$enum_life> {
+ fn packet_id(&self) -> i32 {
+ match self {
+ $(
+ Self::$packet(_) => <$packet as crate::Packet>::PACKET_ID,
+ )*
+ }
+ }
+
fn encode_packet(&self, mut w: impl std::io::Write) -> crate::Result<()> {
use crate::Encode;
use crate::var_int::VarInt;
@@ -73,7 +80,7 @@ macro_rules! packet_group {
match self {
$(
Self::$packet(pkt) => {
- VarInt(<$packet as crate::EncodePacket>::PACKET_ID).encode(&mut w)?;
+ VarInt(<$packet as crate::Packet>::PACKET_ID).encode(&mut w)?;
pkt.encode(w)?;
}
)*
@@ -81,9 +88,7 @@ macro_rules! packet_group {
Ok(())
}
- }
- impl<$enum_life> crate::DecodePacket<$enum_life> for $enum_name<$enum_life> {
fn decode_packet(r: &mut &$enum_life [u8]) -> crate::Result {
use crate::Decode;
use crate::var_int::VarInt;
@@ -91,7 +96,7 @@ macro_rules! packet_group {
let id = VarInt::decode(r)?.0;
Ok(match id {
$(
- <$packet as crate::DecodePacket>::PACKET_ID =>
+ <$packet as crate::Packet>::PACKET_ID =>
Self::$packet($packet::decode(r)?),
)*
id => anyhow::bail!("unknown packet ID {} while decoding {}", id, stringify!($enum_name)),
@@ -130,9 +135,13 @@ macro_rules! packet_group {
}
}
- impl crate::EncodePacket for $packet {
+ impl crate::Packet<'_> for $packet {
const PACKET_ID: i32 = $packet_id;
+ fn packet_id(&self) -> i32 {
+ $packet_id
+ }
+
#[allow(unused_imports)]
fn encode_packet(&self, mut w: impl std::io::Write) -> crate::Result<()> {
use ::valence_protocol::__private::{Encode, Context, VarInt};
@@ -143,10 +152,6 @@ macro_rules! packet_group {
self.encode(w)
}
- }
-
- impl crate::DecodePacket<'_> for $packet {
- const PACKET_ID: i32 = $packet_id;
#[allow(unused_imports)]
fn decode_packet(r: &mut &[u8]) -> ::valence_protocol::__private::Result {
@@ -160,7 +165,15 @@ macro_rules! packet_group {
}
)*
- impl crate::EncodePacket for $enum_name {
+ impl crate::Packet<'_> for $enum_name {
+ fn packet_id(&self) -> i32 {
+ match self {
+ $(
+ Self::$packet(_) => <$packet as crate::Packet>::PACKET_ID,
+ )*
+ }
+ }
+
fn encode_packet(&self, mut w: impl std::io::Write) -> crate::Result<()> {
use crate::Encode;
use crate::var_int::VarInt;
@@ -168,7 +181,7 @@ macro_rules! packet_group {
match self {
$(
Self::$packet(pkt) => {
- VarInt(<$packet as crate::EncodePacket>::PACKET_ID).encode(&mut w)?;
+ VarInt(<$packet as crate::Packet>::PACKET_ID).encode(&mut w)?;
pkt.encode(w)?;
}
)*
@@ -176,9 +189,7 @@ macro_rules! packet_group {
Ok(())
}
- }
- impl crate::DecodePacket<'_> for $enum_name {
fn decode_packet(r: &mut &[u8]) -> crate::Result {
use crate::Decode;
use crate::var_int::VarInt;
@@ -186,7 +197,7 @@ macro_rules! packet_group {
let id = VarInt::decode(r)?.0;
Ok(match id {
$(
- <$packet as crate::DecodePacket>::PACKET_ID =>
+ <$packet as crate::Packet>::PACKET_ID =>
Self::$packet($packet::decode(r)?),
)*
id => anyhow::bail!("unknown packet ID {} while decoding {}", id, stringify!($enum_name)),
diff --git a/crates/valence_protocol_macros/src/decode.rs b/crates/valence_protocol_macros/src/decode.rs
index c400f8a..8c1b25e 100644
--- a/crates/valence_protocol_macros/src/decode.rs
+++ b/crates/valence_protocol_macros/src/decode.rs
@@ -3,9 +3,7 @@ use quote::quote;
use syn::spanned::Spanned;
use syn::{parse2, parse_quote, Data, DeriveInput, Error, Fields, Result};
-use crate::{
- add_trait_bounds, decode_split_for_impl, find_packet_id_attr, pair_variants_with_discriminants,
-};
+use crate::{add_trait_bounds, decode_split_for_impl, pair_variants_with_discriminants};
pub fn derive_decode(item: TokenStream) -> Result {
let mut input = parse2::(item)?;
@@ -167,48 +165,3 @@ pub fn derive_decode(item: TokenStream) -> Result {
)),
}
}
-
-pub fn derive_decode_packet(item: TokenStream) -> Result {
- let mut input = parse2::(item)?;
-
- let Some(packet_id) = find_packet_id_attr(&input.attrs)? else {
- return Err(Error::new(
- input.ident.span(),
- "cannot derive `DecodePacket` without `#[packet_id = ...]` helper attribute",
- ))
- };
-
- let lifetime = input
- .generics
- .lifetimes()
- .next()
- .map(|l| l.lifetime.clone())
- .unwrap_or_else(|| parse_quote!('a));
-
- add_trait_bounds(
- &mut input.generics,
- quote!(::valence_protocol::__private::Decode<#lifetime>),
- );
-
- let (impl_generics, ty_generics, where_clause) =
- decode_split_for_impl(input.generics, lifetime.clone());
-
- let name = input.ident;
-
- Ok(quote! {
- impl #impl_generics ::valence_protocol::__private::DecodePacket<#lifetime> for #name #ty_generics
- #where_clause
- {
- const PACKET_ID: i32 = #packet_id;
-
- fn decode_packet(r: &mut lifetime [u8]) -> ::valence_protocol::__private::Result {
- use ::valence_protocol::__private::{Decode, Context, VarInt, ensure};
-
- let id = VarInt::decode(r).context("failed to decode packet ID")?.0;
- ensure!(id == #packet_id, "unexpected packet ID {} (expected {})", id, #packet_id);
-
- Self::decode(r)
- }
- }
- })
-}
diff --git a/crates/valence_protocol_macros/src/encode.rs b/crates/valence_protocol_macros/src/encode.rs
index 7974bb6..c2c22ad 100644
--- a/crates/valence_protocol_macros/src/encode.rs
+++ b/crates/valence_protocol_macros/src/encode.rs
@@ -3,7 +3,7 @@ use quote::quote;
use syn::spanned::Spanned;
use syn::{parse2, Data, DeriveInput, Error, Fields, LitInt, Result};
-use crate::{add_trait_bounds, find_packet_id_attr, pair_variants_with_discriminants};
+use crate::{add_trait_bounds, pair_variants_with_discriminants};
pub fn derive_encode(item: TokenStream) -> Result {
let mut input = parse2::(item)?;
@@ -163,41 +163,3 @@ pub fn derive_encode(item: TokenStream) -> Result {
)),
}
}
-
-pub fn derive_encode_packet(item: TokenStream) -> Result {
- let mut input = parse2::(item)?;
-
- let Some(packet_id) = find_packet_id_attr(&input.attrs)? else {
- return Err(Error::new(
- input.ident.span(),
- "cannot derive `EncodePacket` without `#[packet_id = ...]` helper attribute",
- ))
- };
-
- add_trait_bounds(
- &mut input.generics,
- quote!(::valence_protocol::__private::Encode),
- );
-
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
-
- let name = input.ident;
-
- Ok(quote! {
- impl #impl_generics ::valence_protocol::__private::EncodePacket for #name #ty_generics
- #where_clause
- {
- const PACKET_ID: i32 = #packet_id;
-
- fn encode_packet(&self, mut w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
- use ::valence_protocol::__private::{Encode, Context, VarInt};
-
- VarInt(#packet_id)
- .encode(&mut w)
- .context("failed to encode packet ID")?;
-
- self.encode(w)
- }
- }
- })
-}
diff --git a/crates/valence_protocol_macros/src/lib.rs b/crates/valence_protocol_macros/src/lib.rs
index 2357559..4037f81 100644
--- a/crates/valence_protocol_macros/src/lib.rs
+++ b/crates/valence_protocol_macros/src/lib.rs
@@ -1,6 +1,6 @@
-//! This crate provides derive macros for [`Encode`], [`Decode`],
-//! [`EncodePacket`], and [`DecodePacket`].
-//! It also provides the procedural macro [`ident_str!`]
+//! This crate provides derive macros for [`Encode`], [`Decode`], and
+//! [`Packet`]. It also provides the procedural macro [`ident_str!`] for parsing
+//! identifiers at compile time.
//!
//! See `valence_protocol`'s documentation for more information.
@@ -8,13 +8,14 @@ use proc_macro::TokenStream as StdTokenStream;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{
- parse_quote, Attribute, Error, GenericParam, Generics, Lifetime, LifetimeDef, Lit, LitInt,
- Meta, Result, Variant,
+ parse_quote, Attribute, Error, GenericParam, Generics, Lifetime, LifetimeDef, Lit, Meta,
+ Result, Variant,
};
mod decode;
mod encode;
mod ident_str;
+mod packet;
#[proc_macro_derive(Encode, attributes(tag))]
pub fn derive_encode(item: StdTokenStream) -> StdTokenStream {
@@ -24,14 +25,6 @@ pub fn derive_encode(item: StdTokenStream) -> StdTokenStream {
}
}
-#[proc_macro_derive(EncodePacket, attributes(packet_id))]
-pub fn derive_encode_packet(item: StdTokenStream) -> StdTokenStream {
- match encode::derive_encode_packet(item.into()) {
- Ok(tokens) => tokens.into(),
- Err(e) => e.into_compile_error().into(),
- }
-}
-
#[proc_macro_derive(Decode, attributes(tag))]
pub fn derive_decode(item: StdTokenStream) -> StdTokenStream {
match decode::derive_decode(item.into()) {
@@ -40,9 +33,9 @@ pub fn derive_decode(item: StdTokenStream) -> StdTokenStream {
}
}
-#[proc_macro_derive(DecodePacket, attributes(packet_id))]
-pub fn derive_decode_packet(item: StdTokenStream) -> StdTokenStream {
- match decode::derive_decode_packet(item.into()) {
+#[proc_macro_derive(Packet, attributes(packet_id))]
+pub fn derive_packet(item: StdTokenStream) -> StdTokenStream {
+ match packet::derive_packet(item.into()) {
Ok(tokens) => tokens.into(),
Err(e) => e.into_compile_error().into(),
}
@@ -56,22 +49,6 @@ pub fn ident_str(item: StdTokenStream) -> StdTokenStream {
}
}
-fn find_packet_id_attr(attrs: &[Attribute]) -> Result> {
- for attr in attrs {
- if let Meta::NameValue(nv) = attr.parse_meta()? {
- if nv.path.is_ident("packet_id") {
- let span = nv.lit.span();
- return match nv.lit {
- Lit::Int(i) => Ok(Some(i)),
- _ => Err(Error::new(span, "packet ID must be an integer literal")),
- };
- }
- }
- }
-
- Ok(None)
-}
-
fn pair_variants_with_discriminants(
variants: impl IntoIterator- ,
) -> Result
> {
diff --git a/crates/valence_protocol_macros/src/packet.rs b/crates/valence_protocol_macros/src/packet.rs
new file mode 100644
index 0000000..565d439
--- /dev/null
+++ b/crates/valence_protocol_macros/src/packet.rs
@@ -0,0 +1,87 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse2, parse_quote, Attribute, DeriveInput, Error, Lit, LitInt, Meta, Result};
+
+use crate::{add_trait_bounds, decode_split_for_impl};
+
+pub fn derive_packet(item: TokenStream) -> Result {
+ let mut input = parse2::(item)?;
+
+ let Some(packet_id) = find_packet_id_attr(&input.attrs)? else {
+ return Err(Error::new(
+ input.ident.span(),
+ "cannot derive `Packet` without `#[packet_id = ...]` helper attribute",
+ ))
+ };
+
+ let lifetime = input
+ .generics
+ .lifetimes()
+ .next()
+ .map(|l| l.lifetime.clone())
+ .unwrap_or_else(|| parse_quote!('a));
+
+ add_trait_bounds(
+ &mut input.generics,
+ quote!(::valence_protocol::__private::Encode),
+ );
+
+ add_trait_bounds(
+ &mut input.generics,
+ quote!(::valence_protocol::__private::Decode<#lifetime>),
+ );
+
+ add_trait_bounds(&mut input.generics, quote!(::std::fmt::Debug));
+
+ let (impl_generics, ty_generics, where_clause) =
+ decode_split_for_impl(input.generics, lifetime.clone());
+
+ let name = input.ident;
+
+ Ok(quote! {
+ impl #impl_generics ::valence_protocol::__private::Packet<#lifetime> for #name #ty_generics
+ #where_clause
+ {
+ const PACKET_ID: i32 = #packet_id;
+
+ fn packet_id(&self) -> i32 {
+ #packet_id
+ }
+
+ fn encode_packet(&self, mut w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
+ use ::valence_protocol::__private::{Encode, Context, VarInt};
+
+ VarInt(#packet_id)
+ .encode(&mut w)
+ .context("failed to encode packet ID")?;
+
+ self.encode(w)
+ }
+
+ fn decode_packet(r: &mut lifetime [u8]) -> ::valence_protocol::__private::Result {
+ use ::valence_protocol::__private::{Decode, Context, VarInt, ensure};
+
+ let id = VarInt::decode(r).context("failed to decode packet ID")?.0;
+ ensure!(id == #packet_id, "unexpected packet ID {} (expected {})", id, #packet_id);
+
+ Self::decode(r)
+ }
+ }
+ })
+}
+
+fn find_packet_id_attr(attrs: &[Attribute]) -> Result> {
+ for attr in attrs {
+ if let Meta::NameValue(nv) = attr.parse_meta()? {
+ if nv.path.is_ident("packet_id") {
+ let span = nv.lit.span();
+ return match nv.lit {
+ Lit::Int(i) => Ok(Some(i)),
+ _ => Err(Error::new(span, "packet ID must be an integer literal")),
+ };
+ }
+ }
+ }
+
+ Ok(None)
+}