aboutsummaryrefslogtreecommitdiff
path: root/src/protocol.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol.rs')
-rw-r--r--src/protocol.rs105
1 files changed, 79 insertions, 26 deletions
diff --git a/src/protocol.rs b/src/protocol.rs
index dbdbc6b..8f155fc 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -87,6 +87,15 @@ pub struct ProtocolPacketField {
pub kind: String,
}
+pub trait HasPacketKind {
+ type Kind: PacketKind;
+
+ fn kind(&self) -> Self::Kind;
+}
+
+pub trait PacketKind: HasPacketId + Clone + Copy + PartialEq + Eq {
+}
+
pub trait HasPacketId {
fn id(&self) -> Id;
@@ -237,7 +246,7 @@ macro_rules! proto_struct {
#[macro_export]
macro_rules! define_protocol {
- ($version: literal, $packett: ident, $rawpackett: ident, $rawdt: ident => {
+ ($version: literal, $packett: ident, $rawpackett: ident, $rawdt: ident, $kindt: ident => {
$($nam: ident, $id: literal, $state: ident, $direction: ident => $body: ident {
$($fnam: ident: $ftyp: ty),* }),*
}
@@ -256,19 +265,30 @@ macro_rules! define_protocol {
}
}
+ $crate::as_item! {
+ #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+ pub enum $kindt {
+ $($nam),*,
+ }
+ }
+
+ impl crate::protocol::HasPacketKind for $packett {
+ type Kind = $kindt;
+
+ fn kind(&self) -> Self::Kind {
+ match self {
+ $($packett::$nam(_) => $kindt::$nam),*,
+ }
+ }
+ }
+
impl crate::protocol::HasPacketId for $packett {
fn version() -> crate::types::VarInt {
crate::types::VarInt($version)
}
fn id(&self) -> crate::protocol::Id {
- use self::$packett::*;
- use crate::protocol::State::*;
- use crate::protocol::PacketDirection::*;
-
- match self {
- $($nam(_) => ($id, $state, $direction)),*
- }.into()
+ crate::protocol::HasPacketKind::kind(self).id()
}
}
@@ -306,15 +326,19 @@ macro_rules! define_protocol {
}
}
- impl<'a> crate::protocol::HasPacketId for $rawpackett<'a> {
- fn id(&self) -> crate::protocol::Id {
- use self::$rawpackett::*;
- use crate::protocol::State::*;
- use crate::protocol::PacketDirection::*;
+ impl<'a> crate::protocol::HasPacketKind for $rawpackett<'a> {
+ type Kind = $kindt;
+ fn kind(&self) -> Self::Kind {
match self {
- $($nam(_) => ($id, $state, $direction)),*
- }.into()
+ $($rawpackett::$nam(_) => $kindt::$nam),*,
+ }
+ }
+ }
+
+ impl<'a> crate::protocol::HasPacketId for $rawpackett<'a> {
+ fn id(&self) -> crate::protocol::Id {
+ crate::protocol::HasPacketKind::kind(self).id()
}
fn version() -> crate::types::VarInt {
@@ -327,17 +351,10 @@ macro_rules! define_protocol {
type Packet = $packett;
fn create(id: crate::protocol::Id, data: &'a[u8]) -> Result<Self, crate::protocol::PacketErr> {
- use self::$rawpackett::*;
- use crate::protocol::State::*;
- use crate::protocol::PacketDirection::*;
- use crate::protocol::PacketErr::UnknownId;
-
- match (id.id, id.state, id.direction) {
- $(($id, $state, $direction) => Ok($nam($rawdt{
- data,
- _typ: core::marker::PhantomData,
- }))),*,
- other => Err(UnknownId(other.into()))
+ if let Some(kind) = $kindt::from_id(id) {
+ Ok(kind.with_body_data(data))
+ } else {
+ Err(crate::protocol::PacketErr::UnknownId(id))
}
}
@@ -386,6 +403,42 @@ macro_rules! define_protocol {
}
}
+ impl crate::protocol::HasPacketId for $kindt {
+ fn id(&self) -> crate::protocol::Id {
+ use self::$kindt::*;
+ use crate::protocol::State::*;
+ use crate::protocol::PacketDirection::*;
+
+ match self {
+ $($nam => ($id, $state, $direction)),*
+ }.into()
+ }
+
+ fn version() -> crate::types::VarInt {
+ crate::types::VarInt($version)
+ }
+ }
+
+ impl $kindt {
+ pub fn from_id(id: crate::protocol::Id) -> Option<Self> {
+ match (id.id, id.state, id.direction) {
+ $(($id, crate::protocol::State::$state, crate::protocol::PacketDirection::$direction) => Some($kindt::$nam)),*,
+ _ => None
+ }
+ }
+
+ pub fn with_body_data<'a>(self, data: &'a [u8]) -> $rawpackett<'a> {
+ match self {
+ $($kindt::$nam => $rawpackett::$nam($rawdt{
+ data,
+ _typ: core::marker::PhantomData,
+ })),*,
+ }
+ }
+ }
+
+ impl crate::protocol::PacketKind for $kindt {}
+
$($crate::proto_struct!($body { $($fnam: $ftyp),* });)*
};
}