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