a4_core/
ser_de.rs

1use heapless::Vec as HVec;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
5pub enum SerWord {
6    LiteralVal(i32),
7    Verb(u16),
8    VerbSeq(u16),
9    UncondRelativeJump { offset: i32 },
10    CondRelativeJump { offset: i32, jump_on: bool },
11}
12
13// --------------------------------------------------------------------------------
14// NOTE! These two definitions MUST be kept in sync! Otherwise there will
15// be corruption and inter-compat issues!
16
17#[cfg(any(test, feature = "std"))]
18#[derive(Debug, Serialize, Deserialize)]
19pub struct SerDict {
20    pub data: Vec<Vec<SerWord>>,
21    pub data_map: Option<Vec<String>>,
22    pub bis: Vec<String>,
23}
24
25#[derive(Debug, Deserialize, Serialize)]
26pub struct SerDictFixed<'a, const SEQS_CT: usize, const SEQ_SZ: usize, const BIS_CT: usize> {
27    pub data: HVec<HVec<SerWord, SEQ_SZ>, SEQS_CT>,
28
29    #[serde(borrow)]
30    pub data_map: Option<HVec<&'a str, SEQS_CT>>,
31
32    #[serde(borrow)]
33    pub bis: HVec<&'a str, BIS_CT>,
34}
35
36// --------------------------------------------------------------------------------
37
38#[cfg(test)]
39mod test {
40    use crate::compiler::Context;
41    use crate::nostd_rt::NoStdContext;
42    use crate::ser_de::SerDictFixed;
43    use crate::std_rt::std_builtins;
44    use crate::{RuntimeWord, VerbSeqInner};
45
46    #[test]
47    fn roundtrip() {
48        let mut ctxt = Context::with_builtins(std_builtins());
49
50        ctxt.evaluate(vec![
51            ":".into(),
52            "star".into(),
53            "42".into(),
54            "emit".into(),
55            ";".into(),
56        ])
57        .unwrap();
58
59        ctxt.evaluate(vec![
60            ":".into(),
61            "mstar".into(),
62            "if".into(),
63            "star".into(),
64            "else".into(),
65            "star".into(),
66            "star".into(),
67            "then".into(),
68            ";".into(),
69        ])
70        .unwrap();
71
72        let serdict = ctxt.serialize();
73        println!("{:?}", serdict);
74
75        let mut ser = postcard::to_stdvec_cobs(&serdict).unwrap();
76        println!("{:?}", ser);
77
78        let loaded: SerDictFixed<4, 16, 4> = postcard::from_bytes_cobs(&mut ser).unwrap();
79        println!("{:?}", loaded);
80
81        for (ser_out, des_out) in serdict.data.iter().zip(loaded.data.iter()) {
82            for (ser_in, des_in) in ser_out.iter().zip(des_out.iter()) {
83                assert_eq!(ser_in, des_in);
84            }
85        }
86
87        for (ser_bis, des_bis) in serdict.bis.iter().zip(loaded.bis.iter()) {
88            assert_eq!(ser_bis, des_bis);
89        }
90
91        let mut ns_ctxt: NoStdContext<32, 16, 128, 4, 16> = NoStdContext::from_ser_dict(&loaded);
92
93        let temp_compiled = RuntimeWord::VerbSeq(VerbSeqInner::from_word(1));
94
95        ns_ctxt.rt.push_exec(temp_compiled.clone());
96        ns_ctxt.rt.push_exec(RuntimeWord::LiteralVal(0));
97
98        ns_ctxt.run_blocking().unwrap();
99
100        let out = ns_ctxt.rt.exchange_output();
101        assert_eq!(out, "**");
102
103        ns_ctxt.rt.push_exec(temp_compiled);
104        ns_ctxt.rt.push_exec(RuntimeWord::LiteralVal(-1));
105
106        ns_ctxt.run_blocking().unwrap();
107
108        let out = ns_ctxt.rt.exchange_output();
109        assert_eq!(out, "*");
110    }
111
112    // #[test]
113    #[allow(dead_code)]
114    fn roundtrip2() {
115        let mut ctxt = Context::with_builtins(std_builtins());
116
117        ctxt.evaluate(vec![":".into(), "nop".into(), ";".into()])
118            .unwrap();
119
120        ctxt.evaluate(vec![
121            ":".into(),
122            "test".into(),
123            "1000000".into(),
124            "0".into(),
125            "do".into(),
126            "nop".into(),
127            "loop".into(),
128            ";".into(),
129        ])
130        .unwrap();
131
132        let serdict = ctxt.serialize();
133        println!("{:?}", serdict);
134
135        let ser = postcard::to_stdvec_cobs(&serdict).unwrap();
136        println!("{:?}", ser);
137    }
138}