sonet_rs/
packet.rs

1use std::any::Any;
2use std::collections::HashMap;
3
4/// Packet Trait. Can be serialized and deserialized from and into TCP Packets
5pub trait Packet {
6
7    /// Gets self as the Any type
8    fn as_any(&self) -> &dyn Any;
9
10    /// Gets the packet's name
11    fn get_name(&self) -> &'static str;
12
13    /// Gets the field names of the Packet Struct
14    fn object_field_names(&self) -> Vec<&'static str>;
15
16    /// Gets the field types of the Packet Struct
17    fn object_type_names(&self) -> Vec<&'static str>;
18
19    /// Gets the field values of the Packet Struct
20    fn get_values(&self) -> Vec<Box<dyn std::any::Any>>;
21}
22
23/// PacketWrapper contains a supplier that generates a packet instance with Vector parameters
24pub struct PacketWrapper {
25
26    /// Supplier for fields
27    fields_accessor: Option<Box<dyn Fn() -> Vec<&'static str> + Send + Sync>>,
28
29    /// Supplier for instances
30    instance_accessor: Option<Box<dyn Fn(Vec<Box<dyn Any>>) -> Box<dyn Packet + Send + Sync> + Send + Sync>>,
31
32    /// Supplier for types
33    types_accessor: Option<Box<dyn Fn() -> Vec<&'static str> + Send + Sync>>
34}
35
36/// Default PacketWrapper Implementation
37impl PacketWrapper {
38
39    /// Creates a new wrapper instance
40    pub fn new(
41        fields_accessor: Option<Box<dyn Fn() -> Vec<&'static str> + Send + Sync>>,
42        instance_accessor: Option<Box<dyn Fn(Vec<Box<dyn Any>>) -> Box<dyn Packet + Send + Sync> + Send + Sync>>,
43        types_accessor: Option<Box<dyn Fn() -> Vec<&'static str> + Send + Sync>>) -> Self {
44        Self {
45            fields_accessor,
46            instance_accessor,
47            types_accessor
48        }
49    }
50
51    /// Generate instance with the supplier
52    pub fn create_instance<T: Packet + Clone + Send + Sync + 'static>(&self, data: Vec<Box<dyn Any>>) -> T {
53        let boxed_packet: &Box<dyn Packet + Send + Sync> = &self.instance_accessor.as_ref().unwrap().as_ref()(data);
54        crate::cast_packet!(boxed_packet as T)
55    }
56
57    pub fn create_instance_box(&self, data: Vec<Box<dyn Any>>) -> Box<dyn Packet + Send + Sync> {
58        let boxed_packet: Box<dyn Packet + Send + Sync> = self.instance_accessor.as_ref().unwrap().as_ref()(data);
59        boxed_packet
60    }
61
62    /// Get the field names with the supplier
63    pub fn get_fields(&self) -> Vec<&'static str> {
64        let fields: Vec<&'static str> = self.fields_accessor.as_ref().unwrap().as_ref()();
65        fields
66    }
67
68    /// Get the field types with the supplier
69    pub fn get_types(&self) -> Vec<&'static str> {
70        let types: Vec<&'static str> = self.types_accessor.as_ref().unwrap().as_ref()();
71        types
72    }
73}
74
75/// PacketRegistry. Contains data of the registered packets
76pub struct PacketRegistry {
77
78    /// The data of the packets
79    pub keys: HashMap<String, PacketWrapper>,
80}
81
82/// Default PacketRegistry Implementation
83impl PacketRegistry {
84
85    /// New Registry
86    pub fn new() -> Self {
87        Self {
88            keys: HashMap::new()
89        }
90    }
91
92    /// Register a packet
93    pub fn register(&mut self, name: String, wrapper: PacketWrapper) {
94        self.keys.insert(name, wrapper);
95    }
96
97    pub fn get(&self, key: &str) -> &PacketWrapper {
98        &self.keys[key]
99    }
100}
101
102#[macro_export]
103macro_rules! is_type {
104    ($packet:ident, $packet_type:ident) => {{
105        $packet.as_any().is::<$packet_type>()
106    }}
107}
108
109#[macro_export]
110macro_rules! register_packet {
111    ($registry:ident, $packet:ident) => {{
112        $packet::register(&mut $registry);
113    }}
114}
115
116#[macro_export]
117macro_rules! register_packet_ref {
118    ($registry:ident, $packet:ident) => {{
119        $packet::register($registry);
120    }}
121}
122
123#[macro_export]
124macro_rules! cast_packet {
125    ($exp:ident as $ty:ty) => {{
126        let casted = $exp.as_any().downcast_ref::<$ty>().unwrap().clone();
127        casted
128    }}
129}
130
131#[macro_export]
132macro_rules! packet_data {
133    ($($exp:expr),*) => {{
134        let vec: Vec<Box<dyn std::any::Any>> = vec![$(Box::new($exp)),*];
135        vec
136    }}
137}
138
139#[macro_export]
140/// Creates a Packet implementation easily.
141///
142/// eg )
143/// ```rust
144/// packet! {
145///     @jvm("io.github.dolphin2410.packets.EntitySpawnPacket")
146///     EntitySpawnRustPacket {
147///         entity_id: i32,
148///         entity_name: String,
149///         network_connection_id: u8
150///     }
151/// }
152/// ```
153///
154/// With the following code, Sonet will map all the packets named "io.github.dolphin2410.packets.EntitySpawnPacket" to the struct EntitySpawnRustPacket. For Jvm compatibility, the names will default to Java's package-class names
155macro_rules! packet {
156    (@jvm($jvmname:literal) $name:ident { $($fname:ident : $ftype:ty),* }) => {
157
158        #[derive(Clone)]
159        pub struct $name {
160            $(pub $fname : $ftype),*
161        }
162
163        impl sonet_rs::packet::Packet for $name {
164            fn as_any(&self) -> &dyn std::any::Any {
165                self
166            }
167
168            fn get_name(&self) -> &'static str {
169                $jvmname
170            }
171
172            fn object_field_names(&self) -> Vec<&'static str> {
173                vec![$(stringify!($fname)),*]
174            }
175
176            fn object_type_names(&self) -> Vec<&'static str> {
177                vec![$(stringify!($ftype)),*]
178            }
179
180            fn get_values(&self) -> Vec<Box<dyn std::any::Any>> {
181                let mut values: Vec<Box<dyn std::any::Any>> = vec![];
182
183                $(values.push(Box::new(self.$fname.clone()));)*
184
185                values
186            }
187        }
188
189        impl $name {
190
191            pub fn field_names() -> Vec<&'static str> {
192                vec![$(stringify!($fname)),*]
193            }
194
195            pub fn type_names() -> Vec<&'static str> {
196                vec![$(stringify!($ftype)),*]
197            }
198
199            pub fn new(vec: Vec<Box<dyn std::any::Any>>) -> Self {
200                let mut iterator = sonet_rs::util::JIterator::new(vec);
201                Self {
202                    $($fname : (*iterator.next()).downcast_ref::<$ftype>().unwrap().to_owned() ),*
203                }
204            }
205
206            // fn jvm_name() -> &'static str {
207            //     $jvmname
208            // }
209
210            pub fn register(registry: &mut crate::packet::PacketRegistry) {
211                let wrapper = sonet_rs::packet::PacketWrapper::new(
212                    Some(Box::new(||{
213                        Self::field_names()
214                    })),
215                    Some(Box::new(|vec|{
216                        Box::new(Self::new(vec))
217                    })),
218                    Some(Box::new(||{
219                        Self::type_names()
220                    })));
221
222                registry.register($jvmname.to_string(), wrapper);
223            }
224        }
225    };
226}