mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-27 05:56:33 +11:00
Replace EncodePacket
and DecodePacket
with Packet
(#261)
## Description Combines the `EncodePacket` and `DecodePacket` trait into a single `Packet` trait. This makes `valence_protocol` simpler and easier to use. This can be done because all packets were made to be bidirectional in #253. Additionally, a `packet_id` method has been added. This should help with #238. ## Test Plan Steps: 1. Run examples, packet_inspector, etc. Behavior should be the same.
This commit is contained in:
parent
6e8ebbe000
commit
7af119da72
13 changed files with 199 additions and 244 deletions
|
@ -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<P>
|
||||
where
|
||||
P: DecodePacket<'a> + EncodePacket,
|
||||
P: Packet<'a>,
|
||||
{
|
||||
while !self.dec.has_next_packet()? {
|
||||
self.dec.reserve(4096);
|
||||
|
|
|
@ -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<P>(&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<P>(&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)
|
||||
}
|
||||
|
|
|
@ -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<P>(&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<P>(&mut self, pkt: &P, pos: impl Into<ChunkPos>)
|
||||
pub fn write_packet_at<'a, P>(&mut self, pkt: &P, pos: impl Into<ChunkPos>)
|
||||
where
|
||||
P: EncodePacket + ?Sized,
|
||||
P: Packet<'a>,
|
||||
{
|
||||
let pos = pos.into();
|
||||
if let Some(cell) = self.partition.get_mut(&pos) {
|
||||
|
|
|
@ -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<P>(&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<W: WritePacket> WritePacket for &mut W {
|
||||
fn write_packet<P>(&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<P>(&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<P>(&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:#}");
|
||||
|
|
|
@ -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<P>(&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<P>
|
||||
where
|
||||
P: DecodePacket<'a>,
|
||||
P: Packet<'a>,
|
||||
{
|
||||
timeout(self.timeout, async {
|
||||
while !self.dec.has_next_packet()? {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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<P>(&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<P>(&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<P>(buf: &mut Vec<u8>, pkt: &P) -> Result<()>
|
||||
pub fn encode_packet<'a, P>(buf: &mut Vec<u8>, 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<P>(
|
||||
pub fn encode_packet_compressed<'a, P>(
|
||||
buf: &mut Vec<u8>,
|
||||
pkt: &P,
|
||||
threshold: u32,
|
||||
scratch: &mut Vec<u8>,
|
||||
) -> 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<Option<P>>
|
||||
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<Vec<P>>
|
||||
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,
|
||||
|
|
|
@ -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<Self>;
|
||||
}
|
||||
|
||||
/// 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<Self>;
|
||||
/// 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::<RegularStruct>();
|
||||
has_impls::<UnitStruct>();
|
||||
|
|
|
@ -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<Self> {
|
||||
|
@ -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<Self> {
|
||||
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<Self> {
|
||||
|
@ -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<Self> {
|
||||
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)),
|
||||
|
|
|
@ -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<TokenStream> {
|
||||
let mut input = parse2::<DeriveInput>(item)?;
|
||||
|
@ -167,48 +165,3 @@ pub fn derive_decode(item: TokenStream) -> Result<TokenStream> {
|
|||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derive_decode_packet(item: TokenStream) -> Result<TokenStream> {
|
||||
let mut input = parse2::<DeriveInput>(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<Self> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<TokenStream> {
|
||||
let mut input = parse2::<DeriveInput>(item)?;
|
||||
|
@ -163,41 +163,3 @@ pub fn derive_encode(item: TokenStream) -> Result<TokenStream> {
|
|||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derive_encode_packet(item: TokenStream) -> Result<TokenStream> {
|
||||
let mut input = parse2::<DeriveInput>(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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<Option<LitInt>> {
|
||||
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<Item = Variant>,
|
||||
) -> Result<Vec<(i32, Variant)>> {
|
||||
|
|
87
crates/valence_protocol_macros/src/packet.rs
Normal file
87
crates/valence_protocol_macros/src/packet.rs
Normal file
|
@ -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<TokenStream> {
|
||||
let mut input = parse2::<DeriveInput>(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<Self> {
|
||||
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<Option<LitInt>> {
|
||||
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)
|
||||
}
|
Loading…
Add table
Reference in a new issue