1use crate::{Deserialize, DeserializeErr, Serialize, Serializer, SerializeResult};
2use alloc::{string::String, fmt, vec::Vec, borrow::ToOwned};
3
4#[derive(Debug, PartialEq, Eq, Clone, Copy)]
5pub enum PacketDirection {
6 ClientBound,
7 ServerBound,
8}
9
10impl PacketDirection {
11 pub fn opposite(&self) -> Self {
12 use PacketDirection::*;
13 match self {
14 ClientBound => ServerBound,
15 ServerBound => ClientBound,
16 }
17 }
18}
19
20#[derive(Debug, PartialEq, Eq, Clone, Copy)]
21pub enum State {
22 Handshaking,
23 Status,
24 Login,
25 Play,
26}
27
28impl State {
29 pub fn name(&self) -> String {
30 use State::*;
31 match self {
32 Handshaking => "Handshaking",
33 Status => "Status",
34 Login => "Login",
35 Play => "Play",
36 }
37 .to_owned()
38 }
39}
40
41#[derive(Debug, PartialEq, Eq, Clone, Copy)]
42pub struct Id {
43 pub id: i32,
44 pub state: State,
45 pub direction: PacketDirection,
46}
47
48impl Serialize for Id {
49 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
50 to.serialize_other(&crate::types::VarInt(self.id))
51 }
52}
53
54impl From<(i32, State, PacketDirection)> for Id {
55 fn from(other: (i32, State, PacketDirection)) -> Self {
56 let (id, state, direction) = other;
57 Self { id, state, direction }
58 }
59}
60
61impl From<Id> for (i32, State, PacketDirection) {
62 fn from(id: Id) -> Self {
63 let Id { id, state, direction } = id;
64 (id, state, direction)
65 }
66}
67
68#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
69pub struct ProtocolSpec {
70 pub name: String,
71 pub packets: Vec<ProtocolPacketSpec>,
72}
73
74#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
75pub struct ProtocolPacketSpec {
76 pub state: String,
77 pub direction: String,
78 pub id: i32,
79 pub name: String,
80 pub body_struct: String,
81 pub fields: Vec<ProtocolPacketField>,
82}
83
84#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
85pub struct ProtocolPacketField {
86 pub name: String,
87 pub kind: String,
88}
89
90pub trait HasPacketKind {
91 type Kind: PacketKind;
92
93 fn kind(&self) -> Self::Kind;
94}
95
96pub trait PacketKind: HasPacketId + Clone + Copy + PartialEq + Eq {
97
98 #[cfg(feature = "gat")]
99 type RawPacket<'a>: RawPacket<'a>;
100
101 fn from_id(id: Id) -> Option<Self>;
102
103 #[cfg(feature = "gat")]
104 fn with_body_data<'a>(self, body: &'a [u8]) -> Self::RawPacket<'a>;
105}
106
107pub trait HasPacketId {
108
109 fn id(&self) -> Id;
110
111 fn version() -> crate::types::VarInt;
112}
113
114pub trait HasPacketBody {
115
116 fn mc_serialize_body<S>(&self, to: &mut S) -> SerializeResult where S: Serializer;
117}
118
119pub trait RawPacket<'a>: HasPacketId + Sized {
120
121 type Packet: Packet;
122
123 fn create(id: Id, data: &'a [u8]) -> Result<Self, PacketErr>;
124
125 fn data(&self) -> &'a [u8];
126
127 fn deserialize(&self) -> Result<Self::Packet, PacketErr>;
128}
129
130pub trait Packet: HasPacketId + HasPacketBody + Sized {}
131
132pub enum PacketErr {
133 UnknownId(Id),
134 DeserializeFailed(DeserializeErr),
135 ExtraData(Vec<u8>),
136}
137
138impl fmt::Display for PacketErr {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 use PacketErr::*;
141 match self {
142 UnknownId(id) => f.write_fmt(format_args!("unknown packet id {:?}", id)),
143 DeserializeFailed(err) => {
144 f.write_fmt(format_args!("failed to deserialize packet: {:?}", err))
145 }
146 ExtraData(data) => f.write_fmt(format_args!(
147 "extra data unparsed at end of packet: {:?}",
148 data
149 )),
150 }
151 }
152}
153
154impl fmt::Debug for PacketErr {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 <dyn fmt::Display>::fmt(self, f)
157 }
158}
159
160#[cfg(feature = "std")]
161impl std::error::Error for PacketErr {}
162
163pub trait ProtocolType: Serialize + Deserialize {}
164
165impl<T: Serialize + Deserialize> ProtocolType for T {}
166
167#[cfg(all(test, feature = "std"))]
168pub trait TestRandom {
169 fn test_gen_random() -> Self;
170}
171
172#[macro_export]
173macro_rules! as_item {
174 ($i:item) => {
175 $i
176 };
177}
178
179#[macro_export]
180macro_rules! proto_struct {
181 ($bodyt: ident { }) => {
182 #[derive(Debug, Clone, PartialEq, Default)]
183 pub struct $bodyt;
184
185 impl Serialize for $bodyt {
186 fn mc_serialize<S: Serializer>(&self, _: &mut S) -> SerializeResult {
187 Ok(())
188 }
189 }
190
191 impl Deserialize for $bodyt {
192 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
193 Deserialized::ok(Self::default(), data)
194 }
195 }
196
197 #[cfg(all(test, feature = "std"))]
198 impl TestRandom for $bodyt {
199 fn test_gen_random() -> Self {
200 Self::default()
201 }
202 }
203 };
204 ($bodyt: ident $(<$($g: ident),*>)? {
205 $($fname: ident: $ftyp: ty ),+
206 }) => {
207 $crate::as_item! {
208 #[derive(Debug, Clone, PartialEq)]
209 pub struct $bodyt$(<$($g),*> where $($g: alloc::fmt::Debug + Clone + PartialEq),*)? {
210 $(pub $fname: $ftyp),+
211 }
212 }
213
214 impl$(<$($g),*>)? Serialize for $bodyt$(<$($g),*> where $($g: Serialize + alloc::fmt::Debug + Clone + PartialEq),*)? {
215 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
216 $(
217 to.serialize_other(&self.$fname)?;
218 )+
219 Ok(())
220 }
221 }
222
223 impl$(<$($g),*>)? Deserialize for $bodyt$(<$($g),*> where $($g: Deserialize + alloc::fmt::Debug + Clone + PartialEq),*)? {
224 fn mc_deserialize(_rest: &[u8]) -> DeserializeResult<'_, Self> {
225 $(let Deserialized{ value: $fname, data: _rest } = <$ftyp>::mc_deserialize(_rest)?;)+
226
227 Deserialized::ok(Self{ $($fname),+ }, _rest)
228 }
229 }
230
231 #[allow(unused_parens)]
232 impl$(<$($g),*>)? From<($($ftyp),+)> for $bodyt$(<$($g),*>)? $(where $($g: alloc::fmt::Debug + Clone + PartialEq),*)? {
233 fn from(other: ($($ftyp),+)) -> Self {
234 let ($($fname),+) = other;
235 Self { $($fname),+ }
236 }
237 }
238
239 #[allow(unused_parens)]
240 impl$(<$($g),*>)? From<$bodyt$(<$($g),*>)?> for ($($ftyp),+) $(where $($g: alloc::fmt::Debug + Clone + PartialEq),*)? {
241 fn from(other: $bodyt$(<$($g),*>)?) -> Self {
242 ($(other.$fname),+)
243 }
244 }
245
246 #[cfg(all(test, feature = "std"))]
247 impl$(<$($g),*>)? TestRandom for $bodyt$(<$($g),*> where $($g: TestRandom + alloc::fmt::Debug + Clone + PartialEq),*)? {
248 fn test_gen_random() -> Self {
249 Self{ $($fname: <$ftyp>::test_gen_random()),+ }
250 }
251 }
252 }
253}
254
255#[macro_export]
256macro_rules! define_protocol {
257 ($version: literal, $packett: ident, $rawpackett: ident, $rawdt: ident, $kindt: ident => {
258 $($nam: ident, $id: literal, $state: ident, $direction: ident => $body: ident {
259 $($fnam: ident: $ftyp: ty),* }),*
260 }
261 ) => {
262 $crate::as_item! {
263 #[derive(Debug, PartialEq, Clone)]
264 pub enum $packett {
265 $($nam($body)),*,
266 }
267 }
268
269 $crate::as_item! {
270 #[derive(Debug, PartialEq)]
271 pub enum $rawpackett<'a> {
272 $($nam($rawdt<'a, $body>)),*,
273 }
274 }
275
276 $crate::as_item! {
277 #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
278 pub enum $kindt {
279 $($nam),*,
280 }
281 }
282
283 impl crate::protocol::HasPacketKind for $packett {
284 type Kind = $kindt;
285
286 fn kind(&self) -> Self::Kind {
287 match self {
288 $($packett::$nam(_) => $kindt::$nam),*,
289 }
290 }
291 }
292
293 impl crate::protocol::HasPacketId for $packett {
294 fn version() -> crate::types::VarInt {
295 crate::types::VarInt($version)
296 }
297
298 fn id(&self) -> crate::protocol::Id {
299 crate::protocol::HasPacketKind::kind(self).id()
300 }
301 }
302
303 impl crate::protocol::HasPacketBody for $packett {
304 fn mc_serialize_body<S>(&self, to: &mut S) -> crate::SerializeResult where S: crate::Serializer {
305 use self::$packett::*;
306 match self {
307 $($nam(body) => to.serialize_other(body)),+
308 }
309 }
310 }
311
312 impl crate::protocol::Packet for $packett {}
313
314 impl $packett {
315 pub fn describe() -> crate::protocol::ProtocolSpec {
316 crate::protocol::ProtocolSpec {
317 name: stringify!($packett).to_owned(),
318 packets: alloc::vec!(
319 $(crate::protocol::ProtocolPacketSpec{
320 state: stringify!($state).to_owned(),
321 direction: stringify!($direction).to_owned(),
322 id: $id,
323 name: stringify!($nam).to_owned(),
324 body_struct: stringify!($body).to_owned(),
325 fields: alloc::vec!(
326 $(crate::protocol::ProtocolPacketField{
327 name: stringify!($fnam).to_owned(),
328 kind: stringify!($ftyp).to_owned(),
329 }),*
330 )
331 }),*,
332 )
333 }
334 }
335 }
336
337 impl<'a> crate::protocol::HasPacketKind for $rawpackett<'a> {
338 type Kind = $kindt;
339
340 fn kind(&self) -> Self::Kind {
341 match self {
342 $($rawpackett::$nam(_) => $kindt::$nam),*,
343 }
344 }
345 }
346
347 impl<'a> crate::protocol::HasPacketId for $rawpackett<'a> {
348 fn id(&self) -> crate::protocol::Id {
349 crate::protocol::HasPacketKind::kind(self).id()
350 }
351
352 fn version() -> crate::types::VarInt {
353 crate::types::VarInt($version)
354 }
355 }
356
357 impl<'a> crate::protocol::RawPacket<'a> for $rawpackett<'a> {
358
359 type Packet = $packett;
360
361 fn create(id: crate::protocol::Id, data: &'a[u8]) -> Result<Self, crate::protocol::PacketErr> {
362 use crate::protocol::PacketKind;
363 if let Some(kind) = $kindt::from_id(id) {
364 Ok(kind.with_body_data(data))
365 } else {
366 Err(crate::protocol::PacketErr::UnknownId(id))
367 }
368 }
369
370 fn data(&self) -> &'a [u8] {
371 use self::$rawpackett::*;
372
373 match self {
374 $($nam(bod) => bod.data),*
375 }
376 }
377
378 fn deserialize(&self) -> Result<Self::Packet, crate::protocol::PacketErr> {
379 use crate::protocol::PacketErr::{ExtraData, DeserializeFailed};
380
381 match self {
382 $($rawpackett::$nam(bod) => {
383 let Deserialized { value: body, data: rest } =
384 $body::mc_deserialize(bod.data)
385 .map_err(move |err| DeserializeFailed(err))?;
386 if !rest.is_empty() {
387 Err(ExtraData(rest.to_vec()))
388 } else {
389 Ok($packett::$nam(body))
390 }
391 }),*,
392 }
393 }
394 }
395
396 #[derive(PartialEq, Debug)]
397 pub struct $rawdt<'a, T> {
398 pub data: &'a [u8],
399 _typ: core::marker::PhantomData<T>
400 }
401
402 impl<'a, T> $rawdt<'a, T> where T: crate::Deserialize {
403 pub fn deserialize(&self) -> Result<T, crate::protocol::PacketErr> {
404 use crate::protocol::PacketErr::*;
405
406 let Deserialized { value: body, data: rest } = T::mc_deserialize(self.data).map_err(DeserializeFailed)?;
407 if !rest.is_empty() {
408 Err(ExtraData(rest.to_vec()))
409 } else {
410 Ok(body)
411 }
412 }
413 }
414
415 impl crate::protocol::HasPacketId for $kindt {
416 fn id(&self) -> crate::protocol::Id {
417 use self::$kindt::*;
418 use crate::protocol::State::*;
419 use crate::protocol::PacketDirection::*;
420
421 match self {
422 $($nam => ($id, $state, $direction)),*
423 }.into()
424 }
425
426 fn version() -> crate::types::VarInt {
427 crate::types::VarInt($version)
428 }
429 }
430
431 impl crate::protocol::PacketKind for $kindt {
432 #[cfg(feature = "gat")]
433 type RawPacket<'a> = $rawpackett<'a>;
434
435 fn from_id(id: crate::protocol::Id) -> Option<Self> {
436 match (id.id, id.state, id.direction) {
437 $(($id, crate::protocol::State::$state, crate::protocol::PacketDirection::$direction) => Some($kindt::$nam)),*,
438 _ => None
439 }
440 }
441
442 #[cfg(feature = "gat")]
443 fn with_body_data<'a>(self, data: &'a [u8]) -> Self::RawPacket<'a> {
444 self.with_body_data_inner(data)
445 }
446 }
447
448 #[cfg(not(feature = "gat"))]
449 impl $kindt {
450 pub fn with_body_data<'a>(self, data: &'a [u8]) -> $rawpackett<'a> {
451 self.with_body_data_inner(data)
452 }
453 }
454
455 impl $kindt {
456 fn with_body_data_inner<'a>(self, data: &'a [u8]) -> $rawpackett<'a> {
457 match self {
458 $($kindt::$nam => $rawpackett::$nam($rawdt{
459 data,
460 _typ: core::marker::PhantomData,
461 })),*,
462 }
463 }
464 }
465
466 $($crate::proto_struct!($body { $($fnam: $ftyp),* });)*
467 };
468}
469
470#[macro_export]
471macro_rules! strip_plus {
472 (+ $($rest: tt)*) => {
473 $($rest)*
474 }
475}
476
477#[macro_export]
478macro_rules! proto_enum_deserialize_variant {
479 ($data: ident, $ty: ident :: $nam: ident ($bod: ty)) => {
480 Ok(<$bod>::mc_deserialize($data)?.map(move |body| $ty::$nam(body)))
481 };
482 ($data: ident, $ty: ident :: $nam: ident) => {
483 Deserialized::ok($ty::$nam, $data)
484 };
485}
486
487#[macro_export]
488macro_rules! instead_of_ident {
489 ($ident: tt, $replacement: tt) => {
490 $replacement
491 }
492}
493
494#[macro_export]
495macro_rules! proto_enum_with_type {
496 ($typ: ty, $typname: ident, $(($bval: literal, $nam: ident $(($bod: ty))?)),*) => {
497 $crate::as_item! {
498 #[derive(PartialEq, Clone, Debug)]
499 pub enum $typname {
500 $($nam $(($bod))?),*
501 }
502 }
503
504 impl Serialize for $typname {
505 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
506 let id_to_serialize: $typ = match self {
507 $($typname::$nam$((instead_of_ident!($bod, _)))? => $bval),*
508 }.into();
509 to.serialize_other(&id_to_serialize)?;
510 self.serialize_body(to)
511 }
512 }
513
514 impl Deserialize for $typname {
515 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
516 <$typ>::mc_deserialize(data)?.and_then(move |id, rest| {
517 Self::deserialize_with_id(id, rest)
518 })
519 }
520 }
521
522 impl $typname {
523 pub const fn variant_count() -> usize {
524 crate::strip_plus!($(+ crate::instead_of_ident!($bval, 1))+)
525 }
526
527 pub fn deserialize_with_id<'a>(id: $typ, data: &'a[u8]) -> DeserializeResult<'a, Self> {
528 match id.into() {
529 $($bval => proto_enum_deserialize_variant!(data, $typname::$nam $(($bod))?)),*,
530 other => {
531 return Err(DeserializeErr::CannotUnderstandValue(alloc::format!("invalid {} {:?}", stringify!($typname), other)))
532 }
533 }
534 }
535
536 pub fn name(&self) -> &str {
537 match self {
538 $($typname::$nam$((instead_of_ident!($bod, _)))? => stringify!($nam)),*
539 }
540 }
541
542 pub fn id(&self) -> $typ {
543 match self {
544 $($typname::$nam$((instead_of_ident!($bod, _)))? => $bval.into()),*
545 }
546 }
547
548 #[allow(unused_variables)]
549 pub fn serialize_body<S: Serializer>(&self, to: &mut S) -> SerializeResult {
550 match &self {
551 $($typname::$nam$((instead_of_ident!($bod, bod)))? => {
552 $(to.serialize_other(instead_of_ident!($bod, bod))?;)?
553 Ok(())
554 }),*
555 }
556 }
557 }
558
559 #[cfg(all(test, feature = "std"))]
560 impl TestRandom for $typname {
561 fn test_gen_random() -> Self {
562 let mut rng = rand::thread_rng();
563 use rand::distributions::Distribution;
564 let distr = rand::distributions::Uniform::new(1, Self::variant_count() + 1);
565 let mut idx: usize = distr.sample(&mut rng);
566 $(
567 idx -= 1;
568 if idx == 0 {
569 return $typname::$nam$((<$bod>::test_gen_random()))?;
570 }
571 )+
572 panic!("cannot generate random {}", stringify!($typname));
573 }
574 }
575 }
576}
577
578#[macro_export]
579macro_rules! proto_byte_enum {
580 ($typname: ident, $($bval: literal :: $nam: ident $(($bod: ty))?),*) => {
581 proto_enum_with_type!(u8, $typname, $(($bval, $nam $(($bod))?)),*);
582 }
583}
584
585#[macro_export]
586macro_rules! proto_varint_enum {
587 ($typname: ident, $($bval: literal :: $nam: ident $(($bod: ty))?),*) => {
588 proto_enum_with_type!(VarInt, $typname, $(($bval, $nam $(($bod))?)),*);
589 }
590}
591
592#[macro_export]
593macro_rules! proto_int_enum {
594 ($typname: ident, $($bval: literal :: $nam: ident $(($bod: ty))?),*) => {
595 proto_enum_with_type!(i32, $typname, $(($bval, $nam $(($bod))?)),*);
596 }
597}
598
599#[macro_export]
600macro_rules! proto_str_enum {
601 ($typname: ident, $($sval: literal :: $nam: ident $(($bod: ident))?),*) => {
602 crate::as_item! {
603 #[derive(PartialEq, Clone, Debug)]
604 pub enum $typname {
605 $($nam $(($bod))?),*
606 }
607 }
608
609 impl Serialize for $typname {
610 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
611 let name = self.name().to_owned();
612 to.serialize_other(&name)?;
613 self.serialize_body(to)
614 }
615 }
616
617 impl Deserialize for $typname {
618 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
619 String::mc_deserialize(data)?.and_then(move |name, rest| {
620 Self::deserialize_with_id(name.as_str(), rest)
621 })
622 }
623 }
624
625 impl $typname {
626 pub const fn variant_count() -> usize {
627 crate::strip_plus!($(+ crate::instead_of_ident!($sval, 1))+)
628 }
629
630 pub fn name(&self) -> &str {
631 match self {
632 $($typname::$nam$((instead_of_ident!($bod, _)))? => $sval),+,
633 }
634 }
635
636 pub fn id(&self) -> String {
637 self.name().to_owned()
638 }
639
640 pub fn deserialize_with_id<'a>(name: &str, data: &'a[u8]) -> DeserializeResult<'a, Self> {
641 match name {
642 $($sval => proto_enum_deserialize_variant!(data, $typname::$nam $(($bod))?)),*,
643 other => Err(DeserializeErr::CannotUnderstandValue(alloc::format!("invalid {} ident '{}'", stringify!($typname), other)))
644 }
645 }
646
647 #[allow(unused_variables)]
648 pub fn serialize_body<S: Serializer>(&self, to: &mut S) -> SerializeResult {
649 match &self {
650 $($typname::$nam$((instead_of_ident!($bod, bod)))? => {
651 $(to.serialize_other(instead_of_ident!($bod, bod))?;)?
652 Ok(())
653 }),*
654 }
655 }
656 }
657
658 impl From<&$typname> for String {
659 fn from(arg: &$typname) -> Self {
660 arg.name().to_owned()
661 }
662 }
663
664 impl From<$typname> for String {
665 fn from(arg: $typname) -> Self {
666 arg.name().to_owned()
667 }
668 }
669
670 #[cfg(all(test, feature = "std"))]
671 impl TestRandom for $typname {
672 fn test_gen_random() -> Self {
673 let mut rng = rand::thread_rng();
674 use rand::distributions::Distribution;
675 let distr = rand::distributions::Uniform::new(1, Self::variant_count() + 1);
676 let mut idx: usize = distr.sample(&mut rng);
677 $(
678 idx -= 1;
679 if idx == 0 {
680 return $typname::$nam$(($bod::test_gen_random()))?;
681 }
682 )+
683 panic!("cannot generate random {}", stringify!($typname));
684 }
685 }
686 }
687}
688
689#[macro_export]
690macro_rules! proto_byte_flag {
691 ($typname: ident, $($bval: literal :: $isnam: ident $setnam: ident),*) => {
692 #[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
693 pub struct $typname(pub u8);
694
695 impl $typname {
696 $(pub fn $isnam(&self) -> bool {
697 self.0 & $bval != 0
698 }
699
700 pub fn $setnam(&mut self, value: bool) {
701 if value {
702 self.0 |= $bval;
703 } else {
704 self.0 ^= $bval & self.0;
705 }
706 })+
707 }
708
709 impl Serialize for $typname {
710 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
711 to.serialize_byte(self.0)
712 }
713 }
714
715 impl Deserialize for $typname {
716 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
717 Ok(u8::mc_deserialize(data)?.map(move |b| $typname(b)))
718 }
719 }
720
721 #[cfg(all(test, feature = "std"))]
722 impl TestRandom for $typname {
723 fn test_gen_random() -> Self {
724 let mut out = <$typname>::default();
725 $(
726 out.$setnam(rand::random::<bool>());
727 )+
728 out
729 }
730 }
731 }
732}