Skip to main content

dec/
dec.rs

1use simple_sbe::decode::{decode_header, decode_message};
2use simple_sbe::otf::header::MessageHeaderListener;
3use simple_sbe::otf::listener::{TokenListener, TokenListenerError};
4use simple_sbe::token::{
5    ByteOrder, Encoding, Presence, PrimitiveType, PrimitiveValue, Signal, Token,
6};
7use simple_sbe::tokenize;
8use std::borrow::Cow;
9use std::collections::VecDeque;
10use std::env::args;
11use std::fs::File;
12use std::io::Read;
13
14fn main() -> anyhow::Result<()> {
15    let args = args().skip(1).take(2).collect::<Vec<_>>();
16    let mut schema_file = File::open(&args[0])?;
17    let mut message_file = File::open(&args[1])?;
18
19    let mut svbuf = Vec::new();
20    schema_file.read_to_end(&mut svbuf)?;
21
22    let mut msg_buf = Vec::new();
23    message_file.read_to_end(&mut msg_buf)?;
24
25    let tokens = tokenize(&svbuf);
26
27    for t in &tokens {
28        println!("{t:?}");
29    }
30
31    let mut l = MyListener::default();
32    // let mut it = tokens.into_iter();
33    println!("=== header ===");
34    let mut x = MessageHeaderListener::new(&mut l);
35    let (tokens, msg_buf) = decode_header(&tokens, &msg_buf, 0, &mut x);
36    let h = x.into_message_header()?;
37    println!("{h:?}");
38    println!("=== message ===");
39    let msg_buf = decode_message(&tokens, msg_buf, h.block_length, h.version as i32, &mut l);
40
41    Ok(())
42}
43
44#[derive(Default)]
45struct MyListener {
46    named_scope: VecDeque<String>,
47    composite_level: usize,
48}
49
50impl TokenListener for MyListener {
51    fn on_begin_message(&mut self, token: &Token) -> Result<(), TokenListenerError> {
52        self.named_scope.push_back(format!("{}", token.name));
53        Ok(())
54    }
55
56    fn on_end_message(&mut self, token: &Token) -> Result<(), TokenListenerError> {
57        self.named_scope.pop_back();
58        Ok(())
59    }
60
61    fn on_encoding(
62        &mut self,
63        field_token: &Token,
64        buffer: &[u8],
65        type_token: &Token,
66        acting_version: i32,
67    ) -> Result<(), TokenListenerError> {
68        // println!("    {name}: {{{}}} {p:?} = {buffer:02X?}", p.to_string());
69        self.print_scope();
70        if self.composite_level > 0 {
71            print!("{}", type_token.name);
72        } else {
73            print!("{}", field_token.name);
74        }
75
76        let np = self.const_or_not_present_value(type_token, field_token.version, acting_version);
77        if np.is_none() {
78            println!(
79                "={} : {buffer:02X?}",
80                buffer
81                    .chunks(type_token.encoding.primitive_type.size())
82                    .map(|b| format!(
83                        "{}",
84                        PrimitiveValue::new(type_token.encoding.primitive_type, b)
85                    ))
86                    .collect::<Vec<_>>()
87                    .join(", ")
88            );
89        } else {
90            print!("={np}");
91            for _ in 1..type_token.array_length() {
92                print!(", {np}");
93            }
94            println!(" [const]")
95        }
96
97        Ok(())
98    }
99
100    fn on_enum(
101        &mut self,
102        field_token: &Token,
103        enum_token: &Token,
104        buffer: &[u8],
105        tokens: &[Token],
106        acting_version: i32,
107    ) -> Result<(), TokenListenerError> {
108        // println!("begin enum {field_token:?}");
109        // println!("      enum {enum_token:?}");
110        // println!(
111        //     "~~> ENUM {:?}",
112        //     tokens
113        //         .iter()
114        //         .map(|x| (&x.signal, &x.name))
115        //         .collect::<Vec<_>>()
116        // );
117        let value = PrimitiveValue::new(enum_token.encoding.primitive_type, buffer);
118        let mut name: Cow<str> = "???".into();
119        if matches!(field_token.encoding.presence, Presence::Constant) {
120            name = field_token.encoding.const_value.to_string()[enum_token.name.len() + 1..]
121                .to_string()
122                .into();
123        } else {
124            for t in tokens {
125                // println!("{value:?} <> {:?} | {t:?}", t.encoding.const_value);
126                if value == t.encoding.const_value {
127                    name = (&t.name).into();
128                    break;
129                }
130            }
131        }
132        self.print_scope();
133        if self.composite_level > 0 {
134            print!("{}=", enum_token.name);
135        } else {
136            print!("{}=", field_token.name);
137        }
138        println!("{name} : {value:?}");
139
140        Ok(())
141    }
142
143    fn on_bit_set(
144        &mut self,
145        field_token: &Token,
146        set_token: &Token,
147        buffer: &[u8],
148        tokens: &[Token],
149        acting_version: i32,
150    ) -> Result<(), TokenListenerError> {
151        self.print_scope();
152        if self.composite_level > 0 {
153            print!("{}:", set_token.name);
154        } else {
155            print!("{}:", field_token.name);
156        }
157        let value: u64 = PrimitiveValue::new(set_token.encoding.primitive_type, buffer)
158            .try_into()
159            .unwrap();
160        for t in tokens {
161            let pos: u64 = (&t.encoding.const_value).try_into().unwrap();
162            let is_set = (1 << pos & value) != 0;
163            print!(" {}={is_set}", t.name);
164        }
165        println!();
166        //todo!()
167        Ok(())
168    }
169
170    fn on_begin_composite(
171        &mut self,
172        field_token: &Token,
173        composite_token: &Token,
174        tokens: &[Token],
175    ) -> Result<(), TokenListenerError> {
176        let name = if self.composite_level > 0 {
177            &composite_token.name
178        } else {
179            &field_token.name
180        };
181        self.named_scope.push_back(name.to_owned());
182        self.composite_level += 1;
183        // self.named_scope.push_back(format!("{}", field_token.name)); //TODO
184        Ok(())
185    }
186
187    fn on_end_composite(
188        &mut self,
189        field_token: &Token,
190        tokens: &[Token],
191    ) -> Result<(), TokenListenerError> {
192        self.composite_level -= 1;
193        let c = self.named_scope.pop_back();
194        println!("-<- Composite {c:?}");
195        debug_assert!(c.is_some());
196        Ok(())
197    }
198
199    fn on_group_header(
200        &mut self,
201        token: &Token,
202        num_in_group: usize,
203    ) -> Result<(), TokenListenerError> {
204        self.print_scope();
205        println!("{} Group Header : numInGroup={num_in_group}", token.name);
206        Ok(())
207    }
208
209    fn on_begin_group(
210        &mut self,
211        token: &Token,
212        group_index: usize,
213        num_in_group: usize,
214    ) -> Result<(), TokenListenerError> {
215        self.named_scope.push_back(format!("{}", token.name));
216        Ok(())
217    }
218
219    fn on_end_group(
220        &mut self,
221        token: &Token,
222        group_index: i32,
223        num_in_group: i32,
224    ) -> Result<(), TokenListenerError> {
225        self.named_scope.pop_back();
226        Ok(())
227    }
228
229    fn on_var_data(
230        &mut self,
231        field_token: &Token,
232        buffer: &[u8],
233        type_token: &Token,
234    ) -> Result<(), TokenListenerError> {
235        println!("VARDATA! {type_token:?}");
236        self.print_scope();
237        println!("{}='{:?}'", field_token.name, buffer);
238        // todo!()
239        Ok(())
240    }
241}
242
243impl MyListener {
244    fn print_scope(&self) {
245        for s in &self.named_scope {
246            print!("{s}.");
247        }
248    }
249
250    fn const_or_not_present_value<'t>(
251        &self,
252        type_token: &'t Token,
253        field_version: i32,
254        acting_version: i32,
255    ) -> &'t PrimitiveValue {
256        match &type_token.encoding.presence {
257            Presence::Constant => &type_token.encoding.const_value,
258            Presence::Optional if acting_version < field_version => {
259                type_token.encoding.applicable_null_value()
260            }
261            _ => &PrimitiveValue::None,
262        }
263    }
264
265    fn encoding_as_string(
266        &self,
267        type_token: &Token,
268        buffer: &[u8],
269        field_version: i32,
270        acting_version: i32,
271    ) {
272        let v = self.const_or_not_present_value(type_token, field_version, acting_version);
273        if v.is_none() {}
274    }
275}