Skip to main content

simple_sbe/
decode.rs

1use crate::otf::listener::TokenListener;
2use crate::token::{PrimitiveValue, Signal, Token};
3
4pub fn decode_header<'t, 'b, L>(
5    tokens: &'t [Token],
6    msg_buf: &'b [u8],
7    acting_version: i32,
8    listener: &mut L,
9) -> (&'t [Token], &'b [u8])
10where
11    L: TokenListener,
12{
13    println!(" == decode {msg_buf:02X?}");
14    let Some((tok, rest)) = tokens.split_first() else {
15        return (&[], &[]); //TODO
16    };
17    let count = tok.component_token_count as usize;
18    //TODO: actually check?
19    let Some((composite, rest)) = rest.split_at_checked(count - 1) else {
20        return (&[], &[]); //TODO
21    };
22    debug_assert_eq!(tok.signal, Signal::BeginComposite);
23    debug_assert_eq!(composite.last().unwrap().signal, Signal::EndComposite);
24    decode_composite(
25        tok,
26        &composite[0],
27        &composite[..count - 2],
28        msg_buf,
29        acting_version,
30        listener,
31    );
32    (rest, &msg_buf[tok.encoded_length as usize..])
33}
34
35pub fn decode_message<'t, 'b, L>(
36    tokens: &'t [Token],
37    msg_buf: &'b [u8],
38    block_length: usize,
39    acting_version: i32,
40    listener: &mut L,
41) -> &'b [u8]
42where
43    L: TokenListener,
44{
45    println!(" == decode {msg_buf:02X?}");
46    let Some((tok, rest)) = tokens.split_first() else {
47        return &[]; //TODO
48    };
49    //TODO: actually check?
50    debug_assert_eq!(tok.signal, Signal::BeginMessage);
51    listener.on_begin_message(tok).unwrap();
52
53    let rest = decode_fields(rest, msg_buf, acting_version, listener);
54
55    let end_tok = tokens.last().unwrap();
56    debug_assert_eq!(end_tok.signal, Signal::EndMessage);
57
58    decode_groups(rest, &msg_buf[block_length..], acting_version, listener);
59    // decode_data(rest, &msg_buf[block_length..], acting_version, listener);
60
61    listener.on_end_message(end_tok).unwrap();
62    &[]
63}
64
65fn decode_groups<'t, 'b, L>(
66    mut tokens: &'t [Token],
67    mut msg_buf: &'b [u8],
68    acting_version: i32,
69    listener: &mut L,
70) -> &'t [Token]
71where
72    L: TokenListener,
73{
74    println!(" == decode {msg_buf:02X?}");
75    loop {
76        let Some((
77            [
78                begin_tok,
79                dimension_type_comp_tok,
80                block_len_tok,
81                num_in_group_tok,
82                dimension_type_end_comp_tok,
83            ],
84            mut rest,
85        )) = tokens.split_first_chunk()
86        else {
87            println!("no group? {:?}", tokens);
88            break;
89        };
90
91        //TODO: actually check?
92        debug_assert_eq!(begin_tok.signal, Signal::BeginGroup);
93        debug_assert_eq!(dimension_type_comp_tok.signal, Signal::BeginComposite);
94        debug_assert_eq!(block_len_tok.signal, Signal::Encoding);
95        debug_assert_eq!(num_in_group_tok.signal, Signal::Encoding);
96        debug_assert_eq!(dimension_type_end_comp_tok.signal, Signal::EndComposite);
97
98        let is_present = begin_tok.version <= acting_version;
99        let block_len = is_present
100            .then_some(block_len_tok.offset as usize)
101            .unwrap_or(0);
102        let mut num_in_group: usize = 0;
103
104        if is_present {
105            let num: u64 = PrimitiveValue::new(
106                num_in_group_tok.encoding.primitive_type,
107                &msg_buf[num_in_group_tok.offset as usize
108                    ..num_in_group_tok.offset as usize + num_in_group_tok.encoded_length as usize],
109            )
110            .try_into()
111            .unwrap();
112            num_in_group = num as usize;
113            msg_buf = &msg_buf[dimension_type_comp_tok.encoded_length as usize..];
114        }
115
116        listener.on_group_header(begin_tok, num_in_group).unwrap();
117
118        for i in 0..num_in_group {
119            listener.on_begin_group(begin_tok, i, num_in_group).unwrap();
120
121            rest = decode_fields(rest, msg_buf, acting_version, listener);
122
123            //TODO: decode groups!!!
124
125            decode_data(rest, &msg_buf[block_len..], acting_version, listener);
126            // msg_buf = &msg_buf[block_len..];
127            break; //TODO
128        }
129        break; //TODO
130    }
131    &[]
132}
133
134fn decode_data<'t, 'b, L>(
135    mut tokens: &'t [Token],
136    mut msg_buf: &'b [u8],
137    acting_version: i32,
138    listener: &mut L,
139) -> &'t [Token]
140where
141    L: TokenListener,
142{
143    println!(" == decode {msg_buf:02X?}");
144    loop {
145        let Some(([begin_tok, comp_tok, len_tok, var_data_tok], rest)) = tokens.split_first_chunk()
146        else {
147            println!("no vardata? {:?}", tokens);
148            break;
149        };
150        if begin_tok.signal != Signal::BeginVarData {
151            println!(
152                "not begin var data field {:?}@{}",
153                begin_tok.signal, begin_tok.i
154            );
155            break;
156        }
157        debug_assert_eq!(comp_tok.signal, Signal::BeginComposite);
158        debug_assert_eq!(len_tok.signal, Signal::Encoding);
159        debug_assert_eq!(var_data_tok.signal, Signal::Encoding);
160        let is_present = begin_tok.version <= acting_version;
161        let len = is_present.then_some(len_tok.offset as usize).unwrap_or(0);
162        let off = is_present
163            .then_some(var_data_tok.offset as usize)
164            .unwrap_or(0);
165        listener
166            .on_var_data(begin_tok, &msg_buf[off..off + len], var_data_tok)
167            .unwrap();
168        tokens = rest;
169        msg_buf = &msg_buf[off + len..];
170    }
171    &[]
172}
173
174fn decode_fields<'t, 'b, L>(
175    mut tokens: &'t [Token],
176    msg_buf: &'b [u8],
177    acting_version: i32,
178    listener: &mut L,
179) -> &'t [Token]
180where
181    L: TokenListener,
182{
183    loop {
184        let Some(([field_tok, type_tok], rest)) = tokens.split_first_chunk() else {
185            println!("finished tok?? {:?}", tokens);
186            break;
187        };
188        if field_tok.signal != Signal::BeginField {
189            println!("not begin field {:?}@{}", field_tok.signal, field_tok.i);
190            break;
191        }
192
193        let type_token_count = type_tok.component_token_count as usize;
194        let Some((current, next)) = rest.split_at_checked(type_token_count) else {
195            println!("can't split next field");
196            break;
197        };
198        debug_assert_eq!(
199            type_token_count,
200            field_tok.component_token_count as usize - 2
201        );
202        debug_assert_eq!(current[type_token_count - 1].signal, Signal::EndField);
203
204        let off = type_tok.offset as usize;
205        let len = type_tok.encoded_length as usize;
206        let segment = &msg_buf[off..off + len];
207
208        match type_tok.signal {
209            Signal::BeginComposite => {
210                println!(
211                    "->- Composite@{}[{type_token_count}] {off} : {type_tok:?}",
212                    type_tok.i
213                );
214                debug_assert!(type_token_count >= 2);
215                let Some((inner, _)) = current.split_at_checked(type_token_count - 2) else {
216                    println!("no composite");
217                    break;
218                };
219                decode_composite(
220                    field_tok,
221                    type_tok,
222                    &inner,
223                    segment,
224                    acting_version,
225                    listener,
226                );
227                debug_assert_eq!(current[type_token_count - 2].signal, Signal::EndComposite);
228            }
229            Signal::BeginEnum => {
230                listener
231                    .on_enum(
232                        field_tok,
233                        type_tok,
234                        segment,
235                        &current[..type_token_count - 2],
236                        acting_version,
237                    )
238                    .unwrap();
239            }
240            Signal::BeginSet => {
241                listener
242                    .on_bit_set(
243                        field_tok,
244                        type_tok,
245                        segment,
246                        &current[..type_token_count - 2],
247                        acting_version,
248                    )
249                    .unwrap();
250            }
251            Signal::Encoding => {
252                let _count = len / type_tok.encoding.primitive_type.size();
253                let end = off + type_tok.encoding.primitive_type.size(); //TODO: add count?
254                listener
255                    .on_encoding(field_tok, segment, type_tok, acting_version)
256                    .unwrap();
257            }
258            _ => {
259                println!("unknown type");
260            }
261        }
262        tokens = next;
263    }
264    tokens
265}
266
267fn decode_composite<'b, L>(
268    field_token: &Token,
269    composite_token: &Token,
270    tokens: &[Token],
271    msg_buf: &'b [u8],
272    acting_version: i32,
273    listener: &mut L,
274) -> &'b [u8]
275where
276    L: TokenListener,
277{
278    listener
279        .on_begin_composite(field_token, composite_token, &tokens)
280        .unwrap();
281    println!(
282        "--> Composite {:?} : {msg_buf:?}",
283        tokens
284            .iter()
285            .map(|x| (&x.signal, &x.name))
286            .collect::<Vec<_>>()
287    );
288
289    let mut xtokens = tokens;
290    loop {
291        let Some((type_tok, rest)) = xtokens.split_first() else {
292            break;
293        };
294        let type_token_count = type_tok.component_token_count as usize;
295        match type_tok.signal {
296            Signal::BeginComposite => {
297                println!("Compositeception! {type_tok:?}");
298                let off = type_tok.offset as usize;
299                let len = type_tok.encoded_length as usize;
300                decode_composite(
301                    field_token,
302                    type_tok,
303                    &rest[..type_token_count - 2],
304                    &msg_buf[off..off + len],
305                    acting_version,
306                    listener,
307                );
308                xtokens = &rest[type_token_count - 1..];
309            }
310            Signal::BeginEnum => {
311                let off = type_tok.offset as usize;
312                let len = type_tok.encoded_length as usize;
313                listener
314                    .on_enum(
315                        field_token,
316                        type_tok,
317                        &msg_buf[off..off + len],
318                        &rest[..type_token_count - 2],
319                        acting_version,
320                    )
321                    .unwrap();
322                xtokens = &rest[type_token_count - 1..];
323            }
324            Signal::BeginSet => {
325                let off = type_tok.offset as usize;
326                let len = type_tok.encoded_length as usize;
327                listener
328                    .on_bit_set(
329                        field_token,
330                        type_tok,
331                        &msg_buf[off..off + len],
332                        &rest[..type_token_count - 2],
333                        acting_version,
334                    )
335                    .unwrap();
336                xtokens = &rest[type_token_count - 1..];
337            }
338            Signal::Encoding => {
339                // println!("encoding {type_tok:?}");
340                let name = &type_tok.name;
341                let s = type_tok.offset as usize;
342                let e = s + type_tok.encoded_length as usize;
343                let seg = &msg_buf[s..e];
344                let p = PrimitiveValue::new(type_tok.encoding.primitive_type, seg);
345                // println!("    {name}: {{{}}} {p:?} = {seg:02X?}", p.to_string());
346                listener
347                    .on_encoding(field_token, seg, type_tok, acting_version)
348                    .unwrap();
349                xtokens = &rest[type_token_count - 1..];
350            }
351            _ => {
352                panic!(
353                    "unknown type in composite {:?}@{}",
354                    type_tok.signal, type_tok.i
355                );
356            }
357        }
358    }
359
360    listener.on_end_composite(field_token, &tokens).unwrap();
361    &[]
362}