Skip to main content

tfserver/structures/
s_type.rs

1use bincode::config::{Configuration, Fixint, LittleEndian};
2use num_enum::TryFromPrimitive;
3use serde::{Deserialize, Serialize};
4use std::any::{Any, TypeId};
5use std::collections::HashSet;
6use std::hash::{DefaultHasher, Hash, Hasher};
7
8pub static BINCODE_CFG: Configuration<LittleEndian, Fixint> = bincode::config::standard()
9    .with_little_endian()
10    .with_fixed_int_encoding()
11    .with_no_limit();
12
13#[derive(Debug, Serialize, Deserialize)]
14pub enum ServerErrorEn {
15    MalformedMetaInfo(Option<String>),
16    NoSuchHandler(Option<String>),
17    InternalError(Option<Vec<u8>>),
18    PayloadLost,
19}
20#[derive(Serialize, Deserialize)]
21pub struct ServerError {
22    s_type: SystemSType,
23    pub en: ServerErrorEn,
24}
25
26impl ServerError {
27    pub fn new(en: ServerErrorEn) -> Self {
28        Self {
29            s_type: SystemSType::ServerError,
30            en,
31        }
32    }
33}
34
35///The trait for you structure type enum. Needed for proper routing of packets and type safety on serialization/deserialization of data.
36///
37///You need to create your own structure type for every project.
38///
39///There are a bunch of functions that already exists, from other traits. They kept manualy due to dyn compatibility.
40pub trait StructureType: Any + Send + Sync {
41    fn get_type_id(&self) -> TypeId;
42    ///We don't use the equals from rust trait, due to need of dyn compatibility
43    fn equals(&self, other: &dyn StructureType) -> bool;
44
45    fn as_any(&self) -> &dyn Any;
46    ///Only for local use, do not try to use this in serialize functions
47    fn hash(&self) -> u64;
48
49    ///We don't use the equals from rust trait, due to need of dyn compatibility
50    fn clone_unique(&self) -> Box<dyn StructureType>;
51
52    ///Returns the pointer to function that deserializes value into the current structure type
53    fn get_deserialize_function(&self) -> Box<dyn Fn(u64) -> Box<dyn StructureType>>;
54    ///Returns the pointer to function that serializes structure type value into the u64 value.
55    fn get_serialize_function(&self) -> Box<dyn Fn(Box<dyn StructureType>) -> u64>;
56}
57
58///Needed to be applied to the serializable/deserializable structures
59pub trait StrongType: Any {
60    ///Need to return reference of structure type enum inside structure
61    fn get_s_type(&self) -> &dyn StructureType;
62}
63
64#[repr(u8)]
65#[derive(Serialize, Deserialize, PartialEq, Clone, Hash, Eq, TryFromPrimitive, Copy)]
66pub enum SystemSType {
67    PacketMeta,
68    HandlerMetaReq,
69    HandlerMetaAns,
70    ServerError,
71}
72
73impl StrongType for ServerError {
74    fn get_s_type(&self) -> &(dyn StructureType + 'static) {
75        &self.s_type
76    }
77}
78
79impl SystemSType {
80    pub fn deserialize(val: u64) -> Box<dyn StructureType> {
81        Box::new(SystemSType::try_from(val as u8).unwrap())
82    }
83
84    pub fn serialize(refer: Box<dyn StructureType>) -> u64 {
85        refer
86            .as_any()
87            .downcast_ref::<SystemSType>()
88            .unwrap()
89            .clone() as u8 as u64
90    }
91}
92
93impl StructureType for SystemSType {
94    fn get_type_id(&self) -> TypeId {
95        return match self {
96            Self::PacketMeta => TypeId::of::<PacketMeta>(),
97            Self::HandlerMetaAns => TypeId::of::<HandlerMetaAns>(),
98            Self::HandlerMetaReq => TypeId::of::<HandlerMetaReq>(),
99            Self::ServerError => TypeId::of::<ServerError>(),
100        };
101    }
102
103    fn equals(&self, other: &dyn StructureType) -> bool {
104        let downcast = other.as_any().downcast_ref::<Self>();
105        if downcast.is_none() {
106            return false;
107        }
108        let downcast = downcast.unwrap();
109        return downcast.eq(self);
110    }
111    fn as_any(&self) -> &dyn Any {
112        self
113    }
114
115    fn hash(&self) -> u64 {
116        let mut hasher = DefaultHasher::default();
117        TypeId::of::<Self>().hash(&mut hasher);
118        ((*self).clone() as u8).hash(&mut hasher);
119        return hasher.finish();
120    }
121
122    fn clone_unique(&self) -> Box<dyn StructureType> {
123        Box::new(self.clone())
124    }
125
126    fn get_deserialize_function(&self) -> Box<dyn Fn(u64) -> Box<dyn StructureType>> {
127        Box::new(SystemSType::deserialize)
128    }
129
130    fn get_serialize_function(&self) -> Box<dyn Fn(Box<dyn StructureType>) -> u64> {
131        Box::new(SystemSType::serialize)
132    }
133}
134
135#[derive(Serialize, Deserialize, Clone)]
136pub struct PacketMeta {
137    pub s_type: SystemSType,
138    pub s_type_req: u64,
139    pub handler_id: u64,
140    pub has_payload: bool,
141}
142
143impl StrongType for PacketMeta {
144    fn get_s_type(&self) -> &dyn StructureType {
145        &self.s_type
146    }
147}
148
149#[derive(Serialize, Deserialize, Clone)]
150pub struct HandlerMetaReq {
151    pub s_type: SystemSType,
152    pub handler_name: String,
153}
154
155#[derive(Serialize, Deserialize, Clone)]
156pub struct HandlerMetaAns {
157    pub s_type: SystemSType,
158    pub id: u64,
159}
160
161impl StrongType for HandlerMetaReq {
162    fn get_s_type(&self) -> &dyn StructureType {
163        &self.s_type
164    }
165}
166
167impl StrongType for HandlerMetaAns {
168    fn get_s_type(&self) -> &(dyn StructureType + 'static) {
169        &self.s_type
170    }
171}
172
173pub struct TypeContainer {
174    s_type: Box<dyn StructureType>,
175}
176
177impl TypeContainer {
178    pub fn new(s_type: Box<dyn StructureType>) -> Self {
179        Self { s_type }
180    }
181}
182
183impl PartialEq<Self> for TypeContainer {
184    fn eq(&self, other: &Self) -> bool {
185        self.s_type.equals(other.s_type.as_ref())
186    }
187}
188
189impl Eq for TypeContainer {}
190
191impl Hash for TypeContainer {
192    fn hash<H: Hasher>(&self, state: &mut H) {
193        self.s_type.hash().hash(state);
194    }
195}
196
197impl Clone for TypeContainer {
198    fn clone(&self) -> Self {
199        Self {
200            s_type: self.s_type.clone_unique(),
201        }
202    }
203}
204
205#[derive(Eq, Clone)]
206pub struct TypeTupple {
207    pub s_types: HashSet<TypeContainer>,
208    pub handler_id: u64,
209}
210
211pub fn validate_s_type(target: &dyn StrongType) -> bool {
212    let s_type = target.get_s_type();
213    return s_type.get_type_id() == target.type_id();
214}
215///Function that serializes object into binary data with type safety/
216pub fn to_vec<T: Serialize + StrongType>(arg: &T) -> Option<Vec<u8>> {
217    if !validate_s_type(arg) {
218        eprintln!("stype validation failed");
219        return None;
220    }
221    let res = bincode::serde::encode_to_vec(arg, BINCODE_CFG.clone());
222    if res.is_err() {
223        eprintln!("bincode serialization failed");
224        return None;
225    }
226    Some(res.unwrap())
227}
228///Function that deserializes the binary data into the requested structure with type safety checks.
229pub fn from_slice<T: for<'a> Deserialize<'a> + StrongType>(arg: &[u8]) -> Result<T, String> {
230    let res = bincode::serde::decode_from_slice::<T, Configuration<LittleEndian, Fixint>>(
231        arg,
232        BINCODE_CFG.clone(),
233    );
234    if res.is_err() {
235        let error_server = bincode::serde::decode_from_slice::<
236            ServerError,
237            Configuration<LittleEndian, Fixint>,
238        >(arg, BINCODE_CFG.clone());
239        if error_server.is_err() {
240            return Err("Unknown packet type".to_string());
241        }
242        return Err(error_server.unwrap().0.en.to_string());
243    }
244    let res = res.unwrap().0;
245    if !validate_s_type(&res) {
246        let error_server = bincode::serde::decode_from_slice::<
247            ServerError,
248            Configuration<LittleEndian, Fixint>,
249        >(&arg, BINCODE_CFG.clone());
250        if error_server.is_err() {
251            return Err("Unknown packet type".to_string());
252        }
253        return Err(error_server.unwrap().0.en.to_string());
254    }
255    Ok(res)
256}
257
258impl PartialEq<Self> for TypeTupple {
259    fn eq(&self, other: &Self) -> bool {
260        let iterator_list = if self.s_types.len() < other.s_types.len() {
261            self.s_types.iter()
262        } else {
263            other.s_types.iter()
264        };
265
266        for s_type in iterator_list {
267            if !self.s_types.contains(&s_type) {
268                return false;
269            }
270        }
271        self.handler_id == other.handler_id
272    }
273}
274
275impl Hash for TypeTupple {
276    fn hash<H: Hasher>(&self, state: &mut H) {
277        self.handler_id.hash(state);
278    }
279}