dlwp/
message.rs

1use crate::{
2    encryption::EncryptionInfo,
3    id::{DId, InstanceID, LId, Port},
4};
5use cerpton::utf::utf8_to_string;
6
7/// Divides the ``Message`` when it is represented as a ``String``
8pub const INFO_SPLIT: &str = "\\|\\";
9const INFO_SPLIT_AREA: &str = " \\|\\ ";
10pub const CONTENTS_LENGTH: usize = 4096;
11
12/// The start of a message being sent
13pub const MSG_INIT: &str = "\\z ";
14/// The start of a message being sent on a serial device
15pub const SN_MSG_INIT: &str = "\\\\z ";
16/// The end of a message being sent
17pub const MSG_END: &str = " \\q";
18
19/// "contents" type, 4096 byte array
20pub type Contents = [u8; CONTENTS_LENGTH];
21
22/// If the original ``String`` was less than 4096 bytes there will be many null characters (``\0``) at the end
23pub fn contents_to_string(contents: Contents) -> String {
24    utf8_to_string(contents.to_vec())
25}
26
27/// Converts a ``String`` to ``Contents``, will panic if the input ``String`` is larger than 4096 bytes
28pub fn string_to_contents(string: String) -> Contents {
29    let bytes: &[u8] = string.as_bytes().try_into().unwrap();
30    let mut ret = [0; 4096];
31
32    for i in 0..4096 {
33        if i >= bytes.len() {
34            break;
35        }
36
37        ret[i] = bytes[i];
38    }
39
40    return ret;
41}
42
43/// Splits a ``String`` using ``INFO_SPLIT`` into an ``&str`` array. Has ``inline`` incase it is called regularaly.
44#[inline]
45pub fn split_from_info(string: &String) -> Vec<&str> {
46    string.split(INFO_SPLIT_AREA).collect::<Vec<&str>>()
47}
48
49/// Checks if a ``Message`` represented as a ``String`` is valid. This starts by checking if it's "info splits" are in
50/// the right places. If it's ``ReceiveInfo`` and ``TransmitInfo`` does not contain empty values.
51#[inline]
52pub fn valid_message_string(string: &String, encrypted: bool) -> bool {
53    let split = split_from_info(&string);
54
55    if split.len() != 3 {
56        println!("full length is not 3");
57        return false;
58    }
59
60    let receive_info = split[0].split(" ").collect::<Vec<&str>>();
61    if receive_info.len() != 4 {
62        println!("ri len not 4");
63        return false;
64    }
65
66    for i in 0..receive_info.len() {
67        // If it can't be parsed to an integer, then it is not valid
68        let parse = receive_info[i].parse::<u64>();
69        if parse.is_err() {
70            println!("cannot parse ri");
71            return false;
72        } else {
73            if i == 0 || i == 1 {
74                // If ``rid`` and ``rdid`` are ``0`` it will be assumed that the ``Message`` will be empty
75                if parse.unwrap() == 0 {
76                    return false;
77                }
78            }
79        }
80    }
81
82    // The rest cannot be checked if ``encrypted`` is ture
83    if encrypted {
84        return true;
85    }
86
87    let transmit_info = split[1].split(" ").collect::<Vec<&str>>();
88    if transmit_info.len() != 6 {
89        return false;
90    }
91
92    for i in 0..transmit_info.len() {
93        // If it can't be parsed to an integer, then it is not valid
94        let parse = transmit_info[i].parse::<u64>();
95        if parse.is_err() {
96            return false;
97        } else {
98            if i == 0 || i == 2 {
99                // If ``tid`` and ``tdid`` are ``0`` it will be assumed that the ``Message`` will be empty
100                if parse.unwrap() == 0 {
101                    return false;
102                }
103            }
104        }
105    }
106
107    true
108}
109
110/// Struct containing information about the receiver
111#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
112pub struct ReceiveInfo {
113    pub rid: LId,
114    pub rdid: DId,
115    pub instance_id: DId,
116    pub port: u16,
117}
118
119impl ReceiveInfo {
120    pub fn empty() -> Self {
121        return ReceiveInfo {
122            rid: 0,
123            rdid: 0,
124            instance_id: 0,
125            port: 0,
126        };
127    }
128
129    pub fn get_from_message_string(message: String) -> Self {
130        let msg_split = split_from_info(&message);
131
132        if msg_split.len() != 3 && msg_split.len() != 2 {
133            return ReceiveInfo::empty();
134        }
135
136        let info_split = msg_split[0].split(' ').collect::<Vec<&str>>();
137
138        if info_split.len() != 4 {
139            return ReceiveInfo::empty();
140        }
141
142        let rid = info_split[0].parse::<u64>();
143        let rdid = info_split[1].parse::<u32>();
144        let instance = info_split[2].parse::<u32>();
145        let port = info_split[3].parse::<u16>();
146
147        if rid.is_err() || rdid.is_err() || instance.is_err() || port.is_err() {
148            return ReceiveInfo::empty();
149        }
150
151        return ReceiveInfo {
152            rid: rid.unwrap(),
153            rdid: rdid.unwrap(),
154            instance_id: instance.unwrap(),
155            port: port.unwrap(),
156        };
157    }
158}
159
160/// Struct containing information about the transmitter
161#[derive(Copy, Clone, Debug, PartialEq)]
162pub struct TransmitInfo {
163    pub tid: LId,
164    pub tdid: DId,
165    pub code: u16,
166}
167
168impl TransmitInfo {
169    pub fn empty() -> Self {
170        return TransmitInfo {
171            tid: 0,
172            tdid: 0,
173            code: 0,
174        };
175    }
176
177    pub fn into_ri(&self, instance: InstanceID, port: Port) -> ReceiveInfo {
178        ReceiveInfo {
179            rid: self.tid,
180            rdid: self.tdid,
181            instance_id: instance,
182            port,
183        }
184    }
185}
186
187#[derive(Copy, Clone, Debug, PartialEq)]
188pub struct Message {
189    /// The receiving information
190    pub ri: ReceiveInfo,
191    /// The transmitting information
192    pub ti: TransmitInfo,
193    /// The contents of the message >~4096 bytes
194    pub contents: [u8; 4096],
195    /// ``day``
196    pub day: i32,
197    /// ``week``
198    pub week: i32,
199    /// ``month``
200    pub month: i32,
201}
202
203impl Message {
204    pub fn empty() -> Self {
205        return Message {
206            ri: ReceiveInfo::empty(),
207            ti: TransmitInfo::empty(),
208            contents: [0; 4096],
209            day: -1,
210            week: -1,
211            month: -1,
212        };
213    }
214
215    /// Converts the ``Message`` to a ``String``. This returns a ``String`` following this format:
216    /// When a ``Message`` is encrypted, the transmit information and contents should be encrypted
217    pub fn as_string(&self) -> String {
218        format!(
219            "{} {} {} {} {} {} {} {} {} {} {} {} {}",
220            self.ri.rid,
221            self.ri.rdid,
222            self.ri.instance_id,
223            self.ri.port,
224            INFO_SPLIT,
225            self.ti.tid,
226            self.ti.code,
227            self.ti.tdid,
228            self.day,
229            self.week,
230            self.month,
231            INFO_SPLIT,
232            contents_to_string(self.contents)
233        )
234    }
235
236    pub fn get_ri_from_encoded(string: &String) -> ReceiveInfo {
237        let split_message = split_from_info(string);
238        if split_message.len() != 3 {
239            return ReceiveInfo::empty();
240        }
241
242        let split_ri = split_message[0].split(" ").collect::<Vec<&str>>();
243
244        if split_ri.len() != 4 {
245            return ReceiveInfo::empty();
246        }
247
248        ReceiveInfo {
249            rid: split_ri[0].parse().unwrap_or(0),
250            rdid: split_ri[1].parse().unwrap_or(0),
251            instance_id: split_ri[2].parse().unwrap_or(0),
252            port: split_ri[3].parse().unwrap_or(0),
253        }
254    }
255
256    #[inline]
257    pub fn ri_as_string(&self) -> String {
258        format!(
259            "{} {} {} {}",
260            self.ri.rid, self.ri.rdid, self.ri.instance_id, self.ri.port
261        )
262    }
263
264    #[inline]
265    pub fn ti_as_string(&self) -> String {
266        format!(
267            "{} {} {} {} {} {}",
268            self.ti.tid, self.ti.code, self.ti.tdid, self.day, self.week, self.month
269        )
270    }
271
272    pub fn encode(&self, encryption: EncryptionInfo) -> String {
273        let mut ret = String::new();
274
275        let ri = self.ri_as_string();
276        let ti = self.ti_as_string();
277        let contents = contents_to_string(self.contents);
278
279        ret.push_str(&ri);
280        ret.push_str(INFO_SPLIT_AREA);
281        // Find better way of doing this
282        ret.push_str(&(encryption.encode_function)(encryption.info, ti));
283        ret.push_str(INFO_SPLIT_AREA);
284        // Find better way of doing this
285        ret.push_str(&(encryption.encode_function)(encryption.info, contents));
286
287        ret
288    }
289
290    pub fn decode(string: &String, encryption: EncryptionInfo) -> Self {
291        let split = split_from_info(string);
292
293        // This is always plain text
294        let ri = split[0];
295        let ti = (encryption.decode_function)(encryption.info, split[1].to_string());
296        println!("og ti: {}, now ti: {}", split[1], ti);
297        let contents = (encryption.decode_function)(encryption.info, split[2].to_string());
298
299        let ret = Message::from_string(&format!(
300            "{}{}{}{}{}",
301            ri, INFO_SPLIT_AREA, ti, INFO_SPLIT_AREA, contents
302        ));
303
304        ret
305    }
306
307    /// Converts an unencrypted ``String`` formatted for ``Message``s to a new ``Message``.
308    pub fn from_string(string: &String) -> Self {
309        let valid = valid_message_string(string, false);
310
311        if valid == false {
312            println!("invalid: {}", string);
313            return Message::empty();
314        }
315
316        let mut ret_message = Message::empty();
317        let split = split_from_info(string);
318        let ri = split[0].split(" ").collect::<Vec<&str>>();
319        let ti = split[1].split(" ").collect::<Vec<&str>>();
320        let contents = split[2];
321
322        for i in 0..ri.len() {
323            let parse = ri[i].parse::<u64>();
324            if parse.is_err() {
325                println!("error");
326                return Message::empty();
327            }
328
329            match i {
330                0 => ret_message.ri.rid = parse.unwrap(),
331                1 => ret_message.ri.rdid = parse.unwrap() as u32,
332                2 => ret_message.ri.instance_id = parse.unwrap() as u32,
333                3 => ret_message.ri.port = parse.unwrap() as u16,
334                _ => break,
335            };
336        }
337
338        for i in 0..ti.len() {
339            let parse = ti[i].parse::<u64>();
340            if parse.is_err() {
341                println!("error1");
342                return Message::empty();
343            }
344
345            match i {
346                0 => ret_message.ti.tid = parse.unwrap(),
347                1 => ret_message.ti.code = parse.unwrap() as u16,
348                2 => ret_message.ti.tdid = parse.unwrap() as u32,
349                3 => ret_message.day = parse.unwrap() as i32,
350                4 => ret_message.week = parse.unwrap() as i32,
351                5 => ret_message.month = parse.unwrap() as i32,
352                _ => break,
353            };
354        }
355
356        ret_message.contents = string_to_contents(contents.to_owned());
357
358        ret_message
359    }
360}