1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Macros for the [durian](https://docs.rs/durian/latest/durian/) crate
//!
//! # Procedural Macros
//!
//! Procedural macros for easily annotating structs as [`Packets`](https://docs.rs/durian/latest/durian/trait.Packet.html) and automatically
//! implementing [`PacketBuilders`](https://docs.rs/durian/latest/durian/trait.PacketBuilder.html). The only
//! requirement is the struct must be de/serializable, meaning all nested fields also need to be
//! de/serializable.
//!
//! `#[bincode_packet]` will de/serialize your Packet using [`bincode`](https://docs.rs/bincode/latest/bincode/) and applies necessary derive
//! macros automatically for you.
//!
//! ```rust
//! use durian::bincode_packet;
//!
//! // Automatically implements Packet, and generates a PositionPacketBuilder that implements
//! // PacketBuilder.  You can also add other macros such as derive macros so long s they don't
//! // conflict with what #[bincode_packet] adds (See bincode_packet documentation).
//! #[bincode_packet]
//! #[derive(Debug)]
//! struct Position {
//!     x: i32,
//!     y: i32
//! }
//!
//! // Works for Unit (empty) structs as well
//! #[bincode_packet]
//! struct Ack;
//! ```
//!
//! You can also use the derive macros (`BinPacket` and `UnitPacket`) manually:
//!
//! ```rust
//! use durian::serde::{Deserialize, Serialize};
//! use durian::{BinPacket, UnitPacket};
//!
//! #[derive(Serialize, Deserialize, BinPacket)]
//! #[serde(crate = "durian::serde")]
//! struct Position { x: i32, y: i32 }
//!
//! #[derive(UnitPacket)]
//! struct Ack;
//! ```
//!
//! # Declarative Macros
//!
//! Regular macros for easy and concise calls to the [`PacketManager`](https://docs.rs/durian/latest/durian/struct.PacketManager.html).
//!
//! These include macros for registering all your `send` and `receive` packets:
//!
//! - [`register_send!(packet_manager, <send packets>...)`](`register_send`)
//! - [`register_receive!(packet_manager, <receive packets>...)`](`register_receive`)
//!
//! Where the `<send packets>` a sequence of your `send` packet types, or a slice of those types, and
//! `<receive packets>` are a sequence of tuples containing (your `receive` packet type, the associated packet builder),
//! or a slice of those tuples.
//!
//! ### Example:
//!
//! ```rust
//! use durian::{bincode_packet, register_send, register_receive, PacketManager};
//!
//! // Send packets
//! #[bincode_packet]
//! struct Position { x: i32, y: i32 }
//! #[bincode_packet]
//! struct Ack;
//!
//! // Receive packets
//! #[bincode_packet]
//! struct UpdatePosition { x: i32, y: i32 }
//! #[bincode_packet]
//! struct NewMessage { message: String }
//!
//! fn main() {
//!     let mut manager = PacketManager::new();
//!     let register_receive_results = register_receive!(
//!         manager,
//!         (UpdatePosition, UpdatePositionPacketBuilder),
//!         (NewMessage, NewMessagePacketBuilder)
//!     );
//!     // Or equivalently in a slice,
//!     // register_receive_results!(manager,
//!     //      [(UpdatePosition, UpdatePositionPacketBuilder), (NewMessage, NewMessagePacketBuilder)]
//!     // );`
//!
//!     let register_send_results = register_send!(manager, Position, Ack);
//!     // Or equivalently in a slice, `register_send!(manager, [Position, Ack]);`
//!
//!     // You can then validate that all the registrations were successful:
//!     assert!(register_receive_results.iter().all(|r| r.is_ok()));
//!     assert!(register_send_results.iter().all(|r| r.is_ok()));
//!
//!     // The macros used above are equivalent to the following manual registration:
//!     //
//!     // manager.register_receive_packet::<UpdatePosition>(UpdatePositionPacketBuilder);
//!     // manager.register_receive_packet::<NewMessage>(NewMessagePacketBuilder);
//!     // manager.register_send_packet::<Position>();
//!     // manager.register_send_packet::<Ack>();
//! }
//! ```

#[allow(unused_imports)]
pub use durian_proc_macros::*;

#[macro_export]
macro_rules! register_send {
    ($manager:ident , [$($packet:ty),*]) => {
        {
            let mut results = std::vec::Vec::new();
            $(
                results.push($manager.register_send_packet::<$packet>());
            )*
            results
        }
    };
    ($manager:ident , $($packet:ty),*) => {
        {
            let mut results = std::vec::Vec::new();
            $(
                results.push($manager.register_send_packet::<$packet>());
            )*
            results
        }
    };
}

#[macro_export]
macro_rules! register_receive {
     ($manager:ident , [$(($packet:ty, $builder:expr)),*]) => {
        {
            let mut results = std::vec::Vec::new();
            $(
                results.push($manager.register_receive_packet::<$packet>($builder));
            )*
            results
        }
    };
    ($manager:ident , $(($packet:ty, $builder:expr)),*) => {
        {
            let mut results = std::vec::Vec::new();
            $(
                results.push($manager.register_receive_packet::<$packet>($builder));
            )*
            results
        }
    };
}