bitis_lib/lib_impl/
compiler.rs

1use std::collections::HashMap;
2use std::process::{abort};
3use askama::Template;
4use logos::{Lexer, Logos, Span};
5use regex::Regex;
6use stringcase::Caser;
7
8
9// ************************************************************************
10// ************************************************************************
11fn integer_bit_size(bit_size: &u8) -> u8 {
12    match bit_size {
13        0..=8 => 8,
14        9..=16 => 16,
15        17..=32 => 32,
16        _ => 64
17    }
18}
19// ************************************************************************
20#[derive(Debug, Clone )]
21#[allow(unused)]
22pub struct AttributeEx {
23    base: Attribute,
24    rust_type_str: String,
25    // rust_pyo3_str: String,
26    base_type_str: String,
27    is_py_wrapped: bool, is_msg: bool, is_enum: bool, is_oo: bool, add_val: bool,
28}
29#[derive(Debug, Clone )]
30pub struct MessageR {
31    pub name: String,
32    // pub version_info: VersionInfo,
33    pub comment: Option<String>,
34    pub parent: Option<String>,
35    pub attributes: Vec<AttributeEx>,
36}
37#[derive(Debug, Clone )]
38pub struct OneOfInfoR {
39    name: String,
40    dyn_bits: u8,
41    attributes: Vec<AttributeEx>,
42}
43fn to_rust_attribute(attribute: &Attribute, msg_names: &Vec<String>) -> AttributeEx {
44    let (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val) = {
45        let mut is_py_wrapped = false;
46        let mut is_enum = false;
47        let mut is_msg = false;
48        let mut is_oo = false;
49        let mut add_val = false;
50
51        let (rtype, base_type) = match &attribute.specific_details {
52            AttributeDetails::AttributeSimple(a) => {
53                match a {
54                    SimpleType::NoTypeSetYet => {
55                        println!("Unexpected unspecified attribute type");
56                        abort()
57                    },
58                    SimpleType::Bool => { ("bool".to_string(), "bool".to_string()) }
59                    SimpleType::UIntFixed(b) => {
60                        add_val = true;
61                        let base = format!("u{}", integer_bit_size(&b));
62                        (format!("VarWithGivenBitSize<{}, {}>", base.clone(), b), base) }
63                    SimpleType::IntFixed(b) => {
64                        add_val = true;
65                        let base = format!("{}", integer_bit_size(&b));
66                        (format!("VarWithGivenBitSize<{}, {}>", base.clone(), b), base) }
67                    SimpleType::UIntDyn(b) => {
68                        add_val = true;
69                        let base = format!("u{}", integer_bit_size(&b.0));
70                        (format!("DynInteger<{}, {}>", base.clone(), b.1), base) }
71                    SimpleType::IntDyn(b) => {
72                        add_val = true;
73                        let base = format!("i{}", integer_bit_size(&b.0));
74                        (format!("DynInteger<{}, {}>", base.clone(), b.1), base) }
75                    SimpleType::Float => {
76                        add_val = true;
77                        let base = "f32".to_string();
78                        (base.clone(), base)
79                    }
80                    SimpleType::Double => {
81                        let base = "f64".to_string();
82                        (base.clone(), base) }
83                    SimpleType::FixedPrecision(fpp) => {
84                        add_val = true;
85                        (format!("FixPrecisionMinMax<{}, {}, {}>", fpp.bits, fpp.min_val, fpp.max_val), "f64".to_string())
86                    }
87                    SimpleType::Binary(b) => {
88                        add_val = true;
89                        (format!("Binary<{}>", b), "Vec<u8>".to_string()) }
90                }
91            }
92            AttributeDetails::AttributeEnumOrMsg(em) => {
93                is_py_wrapped = true;
94                is_msg = msg_names.contains(&em);
95                is_enum = !is_msg.clone();
96                (em.clone(), em.clone()) }
97            AttributeDetails::AttributeOneOf(ooi) => {
98                is_py_wrapped=true; is_oo = true;
99                (ooi.name.clone(), ooi.name.clone()) }
100        };
101        (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo,  add_val)
102    };
103    AttributeEx{base: attribute.clone(), rust_type_str: rtype, base_type_str: base_type,
104        is_py_wrapped, is_msg, is_enum, is_oo, add_val }
105}
106
107pub fn to_rust_messages(msgs: &Vec<Message>) -> Vec<MessageR> {
108    let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
109
110    msgs.iter().map(|msg| {
111        let attrs_rust: Vec<_> = msg.attributes.iter().map(|attribute| {
112            to_rust_attribute(attribute, &msgs_names) }).collect();
113        MessageR{name: msg.name.clone(), comment: msg.comment.clone(), parent: msg.parent.clone(),
114            attributes: attrs_rust}
115    }).collect()
116}
117pub fn to_rust_oneofs(oos: &Vec<OneOfInfo>, msgs: &Vec<Message>) -> HashMap<String, OneOfInfoR> {
118    let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
119
120    oos.iter().map(|oo| {
121        let attrs_rust: Vec<_> = oo.attributes.iter().map(|attribute| {
122            to_rust_attribute(attribute, &msgs_names) }).collect();
123        (oo.name.clone(), OneOfInfoR{name: oo.name.clone(), dyn_bits: oo.dyn_bits, attributes: attrs_rust})
124    }).collect()
125}
126
127#[derive(Clone, Debug)]
128pub struct JinjaData {
129    pub enums: Vec<Enum>,
130    pub msgs: Vec<MessageR>,
131    pub oos: HashMap<String, OneOfInfoR>,
132}
133
134#[derive(Template, Clone, Debug)]
135#[template(path = "data_objects.rs.jinja")]
136pub struct RustDataObjects {
137    pub d: JinjaData
138}
139#[derive(Template, Clone, Debug)]
140#[template(path = "pyclasses.py.rs.jinja")]
141pub struct RustPyDataObjects {
142    pub d: JinjaData
143}
144#[derive(Template, Clone, Debug)]
145#[template(path = "pylib.py.rs.jinja")]
146pub struct RustPyLib {
147    pub d: JinjaData,
148    pub lib_name: String
149}
150#[derive(Template, Clone, Debug)]
151#[template(path = "py_type_hints.pyi.jinja")]
152pub struct PyTypeHints {
153    pub d: JinjaData
154}
155
156
157mod filters {
158    #[allow(dead_code)]
159    pub fn snake_case<T: std::fmt::Display>(s: T) -> ::askama::Result<String> {
160        Ok(stringcase::snake_case(s.to_string().as_str()))
161    }
162    #[allow(dead_code)]
163    pub fn camel_case<T: std::fmt::Display>(s: T) -> ::askama::Result<String> {
164        Ok(stringcase::camel_case(s.to_string().as_str()))
165    }
166    #[allow(dead_code)]
167    pub fn pascal_case<T: std::fmt::Display>(s: T) -> ::askama::Result<String> {
168        Ok(stringcase::pascal_case(s.to_string().as_str()))
169    }
170    #[allow(dead_code)]
171    pub fn to_py_type<T: std::fmt::Display>(s: T) -> ::askama::Result<String> {
172        if ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64"].contains(&s.to_string().as_str()) {
173            Ok("int".to_string()) }
174        else if ["f32", "f64"].contains(&s.to_string().as_str()) {
175            Ok("float".to_string())
176        }
177        else { Ok(s.to_string()) }
178    }
179}
180
181// ************************************************************************
182type Error = (String, Span);
183
184type Result<T> = std::result::Result<T, Error>;
185
186#[derive(Debug, Clone)]
187pub enum DynOrFixedType {
188    Dyn(u8),
189    Fixed(u8)
190}
191#[derive(Debug, PartialEq, Eq, Clone, Copy)]
192pub struct FixedPrecisionProperties {
193    bits: u8, min_val: i64, max_val: i64
194}
195#[derive(Debug, PartialEq, Eq, Clone, Copy)]
196pub enum SimpleType {
197    NoTypeSetYet,
198    Bool,
199    UIntFixed(u8), IntFixed(u8),
200    UIntDyn((u8,u8)), IntDyn((u8,u8)),
201    Float, Double,
202    FixedPrecision(FixedPrecisionProperties),
203    Binary(u8)
204}
205/*impl SimpleType {
206    fn int_size(min_bits: u8) -> std::result::Result<u8, String> {
207        match min_bits {
208            1..=8 => Ok(8),
209            9..=16 => Ok(16),
210            17..=32 => Ok(32),
211            33..=64 => Ok(64),
212            34..=128 => Ok(128),
213            0 => Err("Bitsize of zero for integer is not allowed".into()),
214            _ => Err("Bitsize larger than 128  for integer are not allowed".into())
215        }
216    }
217    fn get_int_bits(self) -> std::result::Result<u8, String> {
218        match self {
219            SimpleType::UIntFixed(s) => Ok(SimpleType::int_size(s)?),
220            SimpleType::IntFixed(s) => Ok(SimpleType::int_size(s)?),
221            SimpleType::UIntDyn((s,_)) => Ok(SimpleType::int_size(s)?),
222            SimpleType::IntDyn((s,_)) => Ok(SimpleType::int_size(s)?),
223            SimpleType::FixedPrecision(fps) => Ok(SimpleType::int_size(fps.bits)?),
224            SimpleType::UFixedPrecision(fps) => Ok(SimpleType::int_size(fps.bits)?),
225            _ => Err("get_int_bits(): Only integers types allowed.".into())
226        }
227    }
228    fn get_int_bits_no_error(self) -> u8 {
229        match self.get_int_bits() {
230            Ok(bits) => bits,
231            Err(e) => { println!("Error: {}", e); abort(); }
232        }
233    }
234}*/
235
236#[derive(Debug, Clone )]
237pub struct OneOfInfo {
238    name: String,
239    dyn_bits: u8,
240    attributes: Vec<Attribute>,
241}
242#[derive(Debug, Clone )]
243pub enum AttributeDetails {
244    AttributeSimple(SimpleType),
245    AttributeEnumOrMsg(String),
246    AttributeOneOf(OneOfInfo),
247}
248#[derive(Debug, Clone )]
249pub struct Attribute {
250    name: String,
251    comment: Option<String>,
252    is_repeated_and_size: Option<DynOrFixedType>,
253    is_optional: bool,
254    specific_details: AttributeDetails
255}
256// #[derive(Debug, Clone)]
257// pub enum VersionInfo {
258//     Version(u16),
259//     BaseWithAllowedVersion(u16),
260// }
261#[derive(Debug, Clone)]
262pub struct Message {
263    pub name: String,
264    // pub version_info: VersionInfo,
265    pub comment: Option<String>,
266    pub parent: Option<String>,
267    pub attributes: Vec<Attribute>,
268}
269
270/// Enum information for bitis. The ids are always DynInteger with a given bit size.
271#[derive(Debug, Clone)]
272pub struct Enum {
273    pub name: String,
274    // pub version_info: VersionInfo,
275    pub comment: Option<String>,
276    pub bit_size: u8,
277    pub values: Vec<String>,
278}
279
280pub fn get_suffix_number(lex: &mut Lexer<Token>) -> Option<u8> {
281    let slice = lex.slice();
282    let re = Regex::new(r".*_d?([0-9]+)$").unwrap();
283    let num_str = re.captures(slice)?.get(1)?;
284    num_str.as_str().parse().ok()
285}
286pub fn get_d_suffix_numbers(lex: &mut Lexer<Token>) -> Option<(u8,u8)> {
287    let slice = lex.slice();
288    let re = Regex::new(r".*_([0-9]+)d([0-9]+)$").unwrap();
289    let first_num_str = re.captures(slice)?.get(1)?.as_str().parse().ok()?;
290    let second_num_str = re.captures(slice)?.get(2)?.as_str().parse().ok()?;
291    Some((first_num_str, second_num_str))
292}
293pub fn get_fp_properties_number(lex: &mut Lexer<Token>) -> Option<FixedPrecisionProperties> {
294    let slice = lex.slice();
295    let re = Regex::new(r".?fp_([0-9]+)\[ *(-?[0-9]+) *, *(-?[0-9]+) *]").unwrap();
296    let bits = re.captures(slice)?.get(1)?.as_str().parse::<u8>().ok()?;
297    let min_val = re.captures(slice)?.get(2)?.as_str().parse::<i64>().ok()?;
298    let max_val = re.captures(slice)?.get(3)?.as_str().parse::<i64>().ok()?;
299    Some(FixedPrecisionProperties {bits, min_val, max_val})
300}
301/*pub fn get_dyn_or_fixed_from_args(lex: &mut Lexer<Token>) -> Option<DynOrFixedType> {
302    let slice = lex.slice();
303    let re = Regex::new(r" *(dyn|fixed) *, *([0-9]+)").unwrap();
304    let type_str = re.captures(slice)?.get(1)?.as_str();
305    let bits = re.captures(slice)?.get(2)?.as_str().parse::<u8>().ok()?;
306    if type_str == "dyn" {
307        Some(DynOrFixedType::Dyn(bits))
308    }
309    else {
310        Some(DynOrFixedType::Fixed(bits))
311    }
312}*/
313pub fn get_enum_bit_size(lex: &mut Lexer<Token>) -> Option<u8> {
314    let slice = lex.slice();
315    let re = Regex::new(r"\( *([0-9]+) *\)").unwrap();
316    let bits = re.captures(slice)?.get(1)?.as_str().parse::<u8>().ok()?;
317    Some(bits)
318}
319pub fn get_version(lex: &mut Lexer<Token>) -> Option<u16> {
320    let slice = lex.slice();
321    let re = Regex::new(r"\[.* +(v[0-9]+) *]").unwrap();
322    let ver_str = re.captures(slice)?.get(1)?.as_str();
323    Some(ver_str.parse::<u16>().ok()?)
324}
325
326#[derive(Debug, Logos)]
327#[logos(skip r"[ \t\r\n\f]+")]
328#[logos(extras = u16)]
329#[allow(dead_code)]
330pub enum Token{
331    #[regex(r"//[^\n]*\n?", priority=40)] Comment,
332    #[regex(r"//\|[^\n]*\n?", |lex| lex.slice()[3..].to_owned(), priority=41)] SpecificComment(String),
333    #[token("msg", priority=20)] Msg,
334    #[token("enum", priority=20)] Enum,
335    #[token("oneof", priority=20)] OneOf,
336    #[token("{")] CBraceOpen,
337    #[token("}")] CBraceClose,
338    #[token("(")] BraceOpen,
339    #[token(")")] BraceClose,
340    #[token(":")] Colon,
341    #[token(";")] SemiColon,
342    #[token(",")] Comma,
343    // #[token("fixed", priority=20)] FixedFlag,
344    // #[token("dyn", priority=20)] DynFlag,
345    #[regex(r"\[ *base +use +starting +with +v[0-9]+ *\]", get_version, priority=35)] MsgBaseInfoToken(u16),
346    #[regex(r"\[ *version +v[0-9]+ *\]", get_version, priority=35)] MsgVersionToken(u16),
347    // #[regex(r"\[ *base +use +starting +with +v[0-9]+ *\]", get_version, priority=35)] MsgVersionToken((MsgVersion, u16)),
348    #[regex("[0-9]+", |lex| lex.slice().parse::<isize>().unwrap(), priority=1)] IntegerVal(isize),
349    #[regex(r"-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?",
350        |lex| lex.slice().parse::<f64>().unwrap(), priority=2)] Number(f64),
351    #[token("bool", priority=30)] Bool,
352    #[regex(r"uint_[0-9]+", get_suffix_number, priority=30)] UIntFixed(u8),
353    #[regex(r"int_[0-9]+", get_suffix_number, priority=30)] IntFixed(u8),
354    #[regex(r"uint_[0-9]+d[0-9]+", get_d_suffix_numbers, priority=31)] UIntDyn((u8,u8)),
355    #[regex(r"int_[0-9]+d[0-9]+", get_d_suffix_numbers, priority=31)] IntDyn((u8,u8)),
356    #[token("float", priority=30)] Float,
357    #[token("double", priority=30)] Double,
358    #[regex(r"fp_[0-9]+\[ *-?[0-9]+ *, *-?[0-9]+ *]", get_fp_properties_number, priority=30)] FixedPoint(FixedPrecisionProperties),
359    #[regex(r"ufp_[0-9]+\[ *-?[0-9]+ *, *-?[0-9]+ *]", get_fp_properties_number, priority=30)] UFixedPoint(FixedPrecisionProperties),
360    //#[token("str", priority=30)] String,
361    #[token("binary_d[0-9]+", get_suffix_number, priority=30)] Binary(u8),
362    #[regex(r"repeated_dyn_[0-9]+", get_suffix_number, priority=30)] RepeatedDyn(u8),
363    #[regex(r"repeated_fixed_[0-9]+", get_suffix_number, priority=30)] RepeatedFixed(u8),
364    #[token("optional", priority=30)] Optional,
365    #[regex(r"[A-Za-z][A-Za-z0-9_-]+", |lex| lex.slice().to_owned(), priority=11)] StringVal(String),
366    #[token("false", |_| false, priority=20)]
367    #[token("true", |_| true, priority=20)]
368    BoolVal(bool),
369    #[regex(r"\( *([0-9]+) *\)", get_enum_bit_size, priority=40)] EnumDynSize(u8),
370}
371
372#[derive(Debug, Clone)]
373pub enum Value {
374    /// null.
375    Message(Message),
376    /// Enum.
377    Enum(Enum)
378}
379
380macro_rules! parse_one_token {
381    ($token_enum: path, $lexer: expr, $error_msg_or_empty: expr) => {
382        loop {
383            let rv = $lexer.next();
384            if let Some(token) = rv {
385                match token {
386                    Ok($token_enum) => {
387                        break Ok(Ok(()));
388                    },
389                    Ok(Token::Comment) => (),
390                    _ => {
391                        if let Some(err_str) = $error_msg_or_empty {
392                            break Err((format!("{err_str}\nToken: {token:?}").to_owned(), $lexer.span()));
393                        }
394                        else {
395                            break Ok(Err($lexer.span()));
396                        }
397                    }
398                }
399            }
400            else {
401                break Err((format!("Unexpected end or text {rv:?}").to_owned(), $lexer.span()));
402            }
403        }
404    }
405}
406macro_rules! parse_one_token_with_arg {
407    ($token_enum: path, $lexer: expr, $error_msg_or_empty: expr) => {
408        loop {
409            let rv = $lexer.next();
410            if let Some(token) = rv {
411                match token {
412                    Ok($token_enum(s)) => {
413                        break Ok(Ok(s));
414                    },
415                    Ok(Token::Comment) => (),
416                    _ => {
417                        if let Some(err_str) = $error_msg_or_empty {
418                            break Err((format!("{}\nFound token: {:?}.",
419                                err_str, token).to_owned(), $lexer.span()));
420                        }
421                        else {
422                            break Ok(Err($lexer.span()));
423                        }
424                    }
425                }
426            }
427            else {
428                break Err((format!("Unexpected end or text {rv:?}").to_owned(), $lexer.span()));
429            }
430        }
431    }
432}
433
434
435pub fn parse_root(lexer: &mut Lexer<'_, Token>) -> Result<Vec<Value>> {
436    let mut list: Vec<Value> = Vec::new();
437    let mut specific_comment: Option<String> = None;
438    loop {
439        if let Some(token) = lexer.next() {
440            let rv = match token {
441                Ok(Token::Msg) => Some(parse_msg(lexer, specific_comment.clone())),
442                Ok(Token::Enum) => Some(parse_enum(lexer, specific_comment.clone())),
443                Ok(Token::Comment) => None,
444                Ok(Token::SpecificComment(s)) => {
445                    specific_comment = Some(s); None },
446                _ => Some(Err((format!("Unexpected token {:?}", token).to_owned(), lexer.span()))),
447            };
448            match rv {
449                None => (),
450                Some(Ok(value)) => { list.push(value); specific_comment = None; },
451                Some(Err(err)) => return Err(err)
452            }
453        }
454        else { break; }
455    }
456    Ok(list)
457}
458
459pub fn parse_msg(lexer: &mut Lexer<'_, Token>, comment_for_msg: Option<String>) -> Result<Value> {
460    let mut attributes = Vec::new();
461
462    let name = match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name but received:"))? {
463        Ok(s) => s,
464        Err(s) => { return Err(("Code should not be reached".into(), s)); }
465    };
466
467    // let version_info = if(lexer.extras == 0) {
468    //     if let Some(token) = lexer.next() {
469    //         match token {
470    //             Ok(Token::MsgVersionToken(v)) => VersionInfo::Version(v),
471    //             Ok(Token::MsgBaseInfoToken(v)) => VersionInfo::BaseWithAllowedVersion(v),
472    //             Ok(_) => { return Err((format!("Unexpected token {:?} for message '{}' when expecting version info", token, name)
473    //                                    .to_owned(), lexer.span())); }
474    //             Err(_) => { return Err((format!("Error: Syntax error for message '{}'", name).to_owned(), lexer.span())); }
475    //         }
476    //     } else { return Err(("Unexpectedly did not find version information".to_owned(), lexer.span())); }
477    // }
478    // else { VersionInfo::Version(lexer.extras) };
479
480    let parent = {
481        let has_parent; let p;
482        if let Some(token) = lexer.next() {
483            match token {
484                Ok(Token::Colon) => has_parent = true,
485                Ok(Token::CBraceOpen) => has_parent = false,
486                _ => { return Err((format!("Unexpected text for msg '{name}'.").into(), lexer.span())) },
487            }
488            if has_parent {
489                match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name."))? {
490                    Ok(s) => p = Some(s),
491                    Err(s) => { return Err((format!("For msg '{name} colon found but no parent name").into(), s)); }
492                };
493                parse_one_token!(Token::CBraceOpen, lexer, Some(format!("Expected curly bracket open for msg '{name}'")))?.unwrap();
494            }
495            else {
496                p = None
497            }
498        }
499        else { return Err(("Unexpected end of file".into(), lexer.span())); }
500        p
501    };
502
503    loop {
504        if let Some(token) = lexer.next() {
505            match token {
506                Ok(Token::CBraceClose) => break,
507                Ok(Token::Comment) => (),
508                Ok(ctoken) => match parse_attribute(ctoken, lexer, name.clone(), false) {
509                    Ok(a) => { attributes.push(a); },
510                    Err(e) => { return Err(e); }
511                },
512                _ => { return Err((format!("Error: Unexpected text found for msg '{name}'.").into(), lexer.span())) },
513            };
514        }
515        else { return Err(("Unexpected end of file".into(), lexer.span())); }
516    }
517
518    Ok(Value::Message(Message{name, /*version_info,*/ comment: comment_for_msg, parent, attributes}))
519}
520
521pub fn parse_attribute(last_token: Token, lexer: &mut Lexer<'_, Token>,
522                       parent_name: String, attributes_for_oneof: bool) -> Result<Attribute> {
523    let mut is_optional = false;
524    let mut is_repeated_and_size: Option<DynOrFixedType> = None;
525    let mut attr_type = SimpleType::NoTypeSetYet;
526    let mut ctoken = last_token;
527    let mut enum_or_msg_str = None;
528    let mut oneof_infos = None;
529    let lexer_span_start = lexer.span();
530    let mut specific_comment: Option<String> = None;
531
532    loop {
533        match ctoken {
534            Token::SpecificComment(s) => {
535                specific_comment = Some(s); () },
536            Token::Optional if is_repeated_and_size.is_some() =>
537                return Err(("Error: Optional and repeated not allowed together".to_owned(), lexer.span())),
538            Token::RepeatedFixed(_) | Token::RepeatedDyn(_) if is_optional =>
539                return Err(("Error: Optional and repeated are not allowed together".to_owned(), lexer.span())),
540
541            Token::Optional | Token::RepeatedDyn(_) | Token::RepeatedFixed(_) if attributes_for_oneof =>
542                return Err(("Error: Optional and repeated are not allowed in oneof".to_owned(), lexer.span())),
543
544            Token::Optional => is_optional = true,
545            Token::RepeatedDyn(b) => is_repeated_and_size = Some(DynOrFixedType::Dyn(b)),
546            Token::RepeatedFixed(b) => is_repeated_and_size = Some(DynOrFixedType::Fixed(b)),
547
548            Token::Bool => { attr_type = SimpleType::Bool; break; },
549            Token::UIntFixed(s) => { attr_type = SimpleType::UIntFixed(s); break; },
550            Token::UIntDyn((m,s)) => { attr_type = SimpleType::UIntDyn((m, s)); break; },
551            Token::IntFixed(s) => { attr_type = SimpleType::IntFixed(s); break; },
552            Token::IntDyn((m,s)) => { attr_type = SimpleType::IntDyn((m,s)); break; },
553            //Token::String => { attr_type = SimpleType::String; break; },
554            Token::Float => { attr_type = SimpleType::Float; break; },
555            Token::Double => { attr_type = SimpleType::Double; break; },
556            Token::FixedPoint(s) => { attr_type = SimpleType::FixedPrecision(s); break; },
557            Token::Binary(b) => { attr_type = SimpleType::Binary(b); break; },
558            Token::StringVal(s) => { enum_or_msg_str = Some(s); break; }
559            Token::OneOf => {
560                oneof_infos = match parse_oneof(lexer, parent_name.clone(), specific_comment.clone(),
561                                                is_repeated_and_size.clone(), is_optional.clone()) {
562                    Ok(oo) => Some(oo),
563                    Err(s) => { return Err(s); }
564                };
565                break;
566            }
567            _ => { return Err((format!("Error: Expected attribute type or modifier (got {ctoken:?}) when parsing msg or oneof '{parent_name}'")
568                                   .to_owned(), lexer.span())); }
569        }
570        if let Some(token) = lexer.next() {
571            match token {
572                Ok(t) => ctoken = t,
573                Err(_) => { return Err((format!("Error: Unexpected text found for msg '{parent_name}'.").to_owned(), lexer.span())); }
574            }
575        } else {
576            return Err(("Unexpected end of file".to_string(), lexer.span()));
577        }
578    }
579
580    let mut name= "".to_owned();
581    if oneof_infos.is_none() {
582        name = parse_one_token_with_arg!(
583            Token::StringVal, lexer, Some(format!("Error: Expected attribute name for msg '{parent_name}' (type: {attr_type:?}/{enum_or_msg_str:?})")))?.unwrap();
584
585        parse_one_token!(Token::SemiColon, lexer, Some(format!(
586            "Error: Expected semicolon to end line of attribute '{name}' of msg or oneof '{parent_name}'")))?.unwrap();
587    }
588    let num_of_set_types_or_opts = vec![(attr_type != SimpleType::NoTypeSetYet), enum_or_msg_str.is_some(), oneof_infos.is_some()]
589        .iter().map(|&x| if x { 1_u8 } else { 0_u8 }).sum::<u8>();
590    if num_of_set_types_or_opts > 1 {
591        let mut span = lexer_span_start.clone();
592        span.end = lexer.span().end;
593        return Err(("Error: Attribute contains inconsistent optional, simple types and messages or Enums".to_string(), span));
594    }
595
596    if let Some(oo) = oneof_infos {
597        Ok(oo)
598    }
599    else if let Some(t) = enum_or_msg_str {
600        Ok(Attribute{name, comment: specific_comment, is_repeated_and_size, is_optional,
601            specific_details: AttributeDetails::AttributeEnumOrMsg(t)})
602    }
603    else {
604        Ok(Attribute{name, comment: specific_comment, is_repeated_and_size, is_optional,
605            specific_details: AttributeDetails::AttributeSimple(attr_type)})
606    }
607}
608
609pub fn parse_oneof(lexer: &mut Lexer<'_, Token>, parent_name: String, comment: Option<String>,
610                   is_repeated_and_size: Option<DynOrFixedType>, is_optional: bool) -> Result<Attribute> {
611    let oo_name = parse_one_token_with_arg!(
612            Token::StringVal, lexer, Some(format!("Error: Expected name for oneof in parent '{parent_name}'")))?.unwrap();
613
614    let bit_size = match parse_one_token_with_arg!(Token::EnumDynSize, lexer, Some("Expected oneof properties for dyn size, e.g. (4)."))? {
615        Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
616    };
617
618    parse_one_token!(Token::CBraceOpen, lexer, Some("Error: Expected open curly bracket to enclose oneof elements"))?.unwrap();
619
620    let mut oo_attribs = Vec::new();
621    loop {
622        if let Some(token) = lexer.next() {
623            match token {
624                Ok(Token::CBraceClose) => break,
625                Ok(last_token) => {
626                    match parse_attribute(last_token, lexer, oo_name.clone(), true) {
627                        Ok(o) => oo_attribs.push(o),
628                        Err(s) => return Err(s),
629                    }
630                }
631                Err(_) => { return Err((format!("Error: Unexpected text when decoding oneof ({token:?})").to_owned(), lexer.span())); },
632            }
633        }
634    }
635    Ok(Attribute{name: oo_name.clone(), comment, is_repeated_and_size, is_optional,
636        specific_details: AttributeDetails::AttributeOneOf(OneOfInfo{
637            name: format!("OO_{}_{}", parent_name.to_pascal_case(), oo_name.to_pascal_case()),
638            dyn_bits: bit_size, attributes: oo_attribs})})
639}
640
641pub fn parse_enum(lexer: &mut Lexer<'_, Token>, comment: Option<String>) -> Result<Value> {
642    let name = match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name but received."))? {
643        Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
644    };
645
646    let bit_size = match parse_one_token_with_arg!(Token::EnumDynSize, lexer, Some("Expected enum properties for dyn size, e.g. (4)."))? {
647        Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
648    };
649
650    // let version_info = if(lexer.extras == 0) {
651    //     if let Some(token) = lexer.next() {
652    //         match token {
653    //             Ok(Token::MsgVersionToken(v)) => VersionInfo::Version(v),
654    //             Ok(Token::MsgBaseInfoToken(v)) => VersionInfo::BaseWithAllowedVersion(v),
655    //             Ok(_) => { return Err((format!("Unexpected token {:?} for enum '{}' when expecting version info", token, name)
656    //                                        .to_owned(), lexer.span())); }
657    //             Err(_) => { return Err((format!("Error: Syntax error for enum '{}'", name).to_owned(), lexer.span())); }
658    //         }
659    //     } else { return Err(("Unexpectedly did not find version information".to_owned(), lexer.span())); }
660    // }
661    // else { VersionInfo::Version(lexer.extras) };
662
663    parse_one_token!(Token::CBraceOpen, lexer, Some(format!("Expected open curly bracket for enum '{name}'")))?.unwrap();
664
665    let mut values = Vec::new();
666    loop {
667        if let Some(token) = lexer.next() {
668            match token {
669                Ok(Token::CBraceClose) => break,
670                Ok(Token::StringVal(s)) => values.push(s),
671                Ok(Token::Comma) | Ok(Token::Comment)=> (),
672                _ => { return Err((format!("Error: Unexpected text found for enum '{name}'.").into(), lexer.span())) },
673            }
674        } else { return Err(("Unexpected end of file".into(), lexer.span())); }
675    }
676
677    Ok(Value::Enum(Enum{name, /*version_info,*/ comment, bit_size, values}))
678}
679
680
681/*pub fn validate_bitis(parsed_bitis: &Vec<Value>) -> Option<String> {
682    let enum_types = parsed_bitis.iter().filter_map(|x|
683        match x { Value::Enum(ev) => Some(ev.name.clone()), _ => None }).collect::<Vec<String>>();
684    let msg_types = parsed_bitis.iter().filter_map(|x|
685        match x { Value::Message(msg) => Some(msg.name.clone()), _ => None }).collect::<Vec<String>>();
686
687    // ***
688    if let Some (err_str) = parsed_bitis.iter().find_map(|s| match s {
689        Value::Message(msg) => {
690            msg.attributes.iter().find_map(|a| match a.specific_details.clone() {
691                AttributeDetails::AttributeEnumOrMsg(eon) => {
692                    if !enum_types.contains(&eon) && !msg_types.contains(&eon) {
693                        Some(format!("Type or enum '{eon}' unknown"))
694                    }
695                    else { None }
696                },
697                _ => None
698            })
699        },
700        _ => None,
701    }) { return Some(err_str); };
702
703    // *** check msg versions
704    let msgs_with_version: Vec<_> = parsed_bitis.iter().filter_map(|s| match s {
705        Value::Message(msg) => {
706            Some(match msg.version {
707                MsgVersion::Fixed => format!("{}_fixed", msg.name),
708                // MsgVersion::VersionedMsg => format!("{}_versioned", msg.name),
709                // MsgVersion::Base => format!("{}_base", msg.name),
710                MsgVersion::Versioned(v) => format!("{}_v{}", msg.name, v)
711            })
712        },
713        _ => None,
714    }).collect();
715    match (1..msgs_with_version.len()).into_iter().find_map(|i| {
716        let s = &msgs_with_version[i - 1];
717        if msgs_with_version[i..].contains(s) { Some(s.clone()) } else { None }
718    })
719    {
720        Some(msg) => return Some(format!("Conflicting versions of {}.", msg)),
721        None => ()
722    };
723
724    let fixed_msgs: Vec<_> = parsed_bitis.iter().filter_map(|s| match s {
725        Value::Message(msg) => {
726            match msg.version.clone() {
727                MsgVersion::Fixed => Some(msg.name.clone()), _ => None }
728        }, _ => None,
729    }).collect();
730    if let Some (err_str) = parsed_bitis.iter().find_map(|s| match s {
731        Value::Message(msg) => {
732            match msg.version.clone() {
733                MsgVersion::Fixed => None,
734                _ => {
735                    if fixed_msgs.contains(&msg.name) {
736                        Some(format!("Multiple conflicting versions of {} (fixed and version).", msg.name))
737                    }
738                    else { None }
739                }
740            }
741        }, _ => None,
742    }) { return Some(err_str); };
743
744    // ***
745    // Check that only attributes were added
746    // parsed_bitis.iter().for_each(|s| match s {
747    //     Value::Message(msg) => {
748    //
749    //     },
750    //     Value::Enum(eon) => {
751    //
752    //     }
753    // })
754
755    None
756}
757*/
758// Struct that collects all bitis information
759#[derive(Debug, Clone)]
760pub struct BitisProcessed {
761    pub max_version_number: u16,
762    pub msgs: Vec<Message>,
763    pub enums: Vec<Enum>,
764    pub oo_enums: Vec<OneOfInfo>,
765}
766
767/// This function prepares message and enums for rendering
768pub fn process_and_validate_bitis(parsed_bitis: &Vec<Value>) -> BitisProcessed {
769    /*let (processed_msgs, max_msg_version_number) = {
770        let msgs: Vec<_> = parsed_bitis.iter().filter_map(|v| {
771            match v { Value::Message(msg) => Some(msg.clone()), _ => None }
772        }).collect();
773
774        let max_version_number: u16 = msgs.iter().fold(0_u16, |cur_max, v| {
775            std::cmp::max(cur_max, match v.version_info.clone()
776            { VersionInfo::BaseWithAllowedVersion(_) => 0, VersionInfo::Version(v) => v })
777        });
778        println!("Max version number for msgs found: {}", max_version_number);
779
780        // ***
781        // sort msgs per versions
782        let msgs_per_version: HashMap<u16, HashMap<String, Message>> = (0..=max_version_number).map(|cver| {
783            let msgs: HashMap<String, Message> = msgs.iter().filter_map(|cmsg| {
784                match &cmsg.version_info {
785                    VersionInfo::BaseWithAllowedVersion(_) if cver==0  => Some(cmsg.clone()),
786                    VersionInfo::Version(msg_ver) => {
787                        if *msg_ver == 0 {
788                            println!("Error: Message '{}' has version zero which is not allowed", cmsg.name);
789                            abort();
790                        } else if *msg_ver == cver { Some(cmsg.clone()) }
791                        else { None }
792                    }, _ => None
793                } }
794            ).map(|msg| { (msg.name.clone(), msg) }).collect();
795            (cver, msgs)
796        }).collect();
797
798        // todo check that messages as attributes are used with the correct version
799
800        // todo check that messages have the same allowed_to_be_used_starting_with_version for all versions
801
802        // todo check that attributes for different versions are unique
803
804        // ***
805        let msg_names_and_ver_type: HashMap<_, _> = msgs.iter().map(|v| {
806            (v.name.clone(), v.version_info.clone()) }).collect();
807
808        let msg_version_to_use_per_version: HashMap<String, HashMap<u16, u16>> = {
809            let mut temp_msg_last_version: HashMap<String, u16> =
810                msgs.iter().enumerate().map(|(x1, x2)| { (x2.name.clone(), x1.clone() as u16) }).collect();
811
812            msgs.iter().map(|v| {
813                (1..=max_version_number).map(|cver| {
814
815                }
816            }
817        }
818
819
820        // let msg_base_with_version: Vec<_> = msgs.iter().filter_map(|msg| {
821        // });
822
823        let msgs_processed: Vec<Vec<Message>> = msgs_per_version.iter()
824            .map(|(&cver, cver_msgs) | {
825                let mut msgs_for_version: HashMap<String, Message> = HashMap::new();
826
827                println!("Processing V{} msgs: {:?}", cver, cver_msgs);
828                if cver == 0 {
829                    msg_names_and_ver_type.iter().for_each(|(mi_name, _)| {
830                        if !cver_msgs.contains_key(mi_name) {
831                            println!("Error: Message '{}' not found in base version. All messages must be declared in base.", mi_name);
832                            abort();
833                        }
834                    });
835                }
836                else {
837                    // add missing msg definitions for each version
838                    let new_msgs: HashMap<_, _> = msg_names_and_ver_type.iter().filter_map(|(mi_name, ver_type)| {
839                        // do it only for versioned msgs
840                        if let VersionInfo::BaseWithAllowedVersion(_) = ver_type { None } else {
841                            // check if
842                            if !cver_msgs.contains_key(mi_name) {
843                                println!("Generating empty version msg '{mi_name}'");
844
845                                let base_ver_msg = msgs_per_version.get(&0).unwrap().get(mi_name).unwrap();
846
847                                let name = format!("{}_DataV{}", mi_name, cver);
848                                Some((name.clone(), Message { name, attributes: vec![], comment: Some("Automatically generated empty msg".to_string()),
849                                    ..base_ver_msg.clone() }))
850                            } else { None }
851                        }
852                    }).collect();
853                    msgs_for_version.extend(new_msgs);
854                }
855
856                cver_msgs.iter().for_each(|(_, cmsg)| {
857                    if let VersionInfo::Version(msg_ver) = &cmsg.version_info {
858                        match cver {
859                            cver_iter if cver_iter >= *msg_ver => {
860                                let cname = format!("{}_DataV{}", cmsg.name, cver_iter);
861                                msgs_for_version.insert(cname.clone(), Message { name: cname, ..cmsg.clone() });
862                            },
863                            _ => ()
864                        };
865                    }
866                    else {
867                        let processed_attributes: Vec<_> = cmsg.attributes.iter().map(|attr| {
868                            match &attr.specific_details {
869                                AttributeDetails::AttributeSimple(_) => attr.clone(),
870                                AttributeDetails::AttributeEnumOrMsg(at) => {
871                                    Attribute{specific_details: AttributeEnumOrMsg(format!("{}_V{}", at, cver)), ..attr.clone()}
872                                }
873                                AttributeDetails::AttributeOneOf(_) => {
874                                    Attribute{name: format!("{}_TODO", attr.name), ..attr.clone()}
875                                }
876                            }
877                        }).collect();
878                        let cname = format!("{}_BaseV{}", cmsg.name, cver);
879                        msgs_for_version.insert(cname.clone(), Message { name: cname, attributes: processed_attributes, ..cmsg.clone() });
880                    }
881                });
882                msgs_for_version.values().cloned().collect::<Vec<Message>>()
883            }).collect();
884
885        let mut msg_processed_concat: Vec<_> = msgs_processed.concat();
886        msg_processed_concat.sort_by_key(|msg| { msg.name.to_lowercase() });
887
888
889        (msg_processed_concat, max_version_number)
890    };*/
891
892    //
893    let msgs: Vec<_> = parsed_bitis.iter().filter_map(|v| {
894        match v { Value::Message(msg) => Some(msg.clone()), _ => None }
895    }).collect();
896    let enums: Vec<_> = parsed_bitis.iter().filter_map(|v| {
897        match v { Value::Enum(enm) => Some(enm.clone()), _ => None }
898    }).collect();
899
900    fn get_oneofs(attrs: &Vec<Attribute>) -> Option<Vec<OneOfInfo>> {
901        let direct_oos = attrs.iter().filter_map(|attr| {
902            match &attr.specific_details {
903                AttributeDetails::AttributeOneOf(oo) => Some(vec![oo.clone()]),
904                _ => None
905            }
906        }).collect::<Vec<Vec<OneOfInfo>>>().concat();
907
908        let inner_oos = direct_oos.iter().filter_map(|doo| {
909            get_oneofs(&doo.attributes)
910        }).collect::<Vec<Vec<_>>>().concat();
911
912        let all_oos = vec![direct_oos, inner_oos].concat();
913        if all_oos.len() == 0 { None }
914        else { Some(all_oos) }
915    }
916    let oo_enums: Vec<_> = msgs.iter().filter_map(|msg| {
917        get_oneofs(&msg.attributes)
918    }).collect::<Vec<_>>().concat();
919
920    // println!("\noo_enums:\n{:?}\n", oo_enums);
921
922    { // Test msgs and enum
923        let msg_names = msgs.iter().map(|msg| &msg.name).collect::<Vec<_>>();
924        msg_names.iter().for_each(|name| {
925            // println!("name: {}", name);
926            if msg_names.iter().filter(|cname| **cname == *name).count() > 1 {
927                println!("Error: Multiple instances of msg '{}' found.", name);
928                abort()
929            }
930        });
931        let enum_names = enums.iter().map(|enm| &enm.name).collect::<Vec<_>>();
932        enum_names.iter().for_each(|name| {
933            if enum_names.iter().filter(|cname| **cname == *name).count() > 1 {
934                println!("Error: Multiple instances of enum '{}' found.", name); abort()
935            }
936        });
937
938        // check that all attributes are defined
939        //...
940    }
941
942    BitisProcessed { max_version_number: 0, msgs, enums, oo_enums}
943}
944
945
946// ***************************************************
947
948#[cfg(test)]
949mod bitis_semantic {
950    use rstest::rstest;
951    use super::*;
952
953    #[rstest]
954    fn msg_empty_msg() {
955        let test_empty_msg = "msg Lala { }";
956
957        let mut lexer = Token::lexer(test_empty_msg);
958        lexer.extras = 0;
959
960        let parsed_bitis = parse_root(&mut lexer);
961        if let Err(s) = parsed_bitis.clone() {
962            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
963        }
964        assert_eq!(parsed_bitis.is_ok(), true);
965
966        let parsed_bitis = parsed_bitis.unwrap();
967        assert_eq!(parsed_bitis.len(), 1);
968
969        assert!(if let Value::Message(_) = parsed_bitis[0].clone() { true } else { false });
970
971        if let Value::Message(msg) = parsed_bitis[0].clone() {
972            assert_eq!(msg.name, "Lala".to_string());
973        }
974
975        // let validate_result = validate_bitis(&parsed_bitis);
976        // println!("validate_result: {:?}", validate_result);
977
978        let process_result = process_and_validate_bitis(&parsed_bitis);
979        println!("process_result {:?}", process_result);
980
981        assert_eq!(process_result.msgs.len(), 1);
982        assert_eq!(process_result.enums.len(), 0);
983    }
984
985    #[rstest]
986    fn msg_simple_msg() {
987        let test_empty_msg = "msg Lala { uint_7 a1; }";
988
989        let mut lexer = Token::lexer(test_empty_msg);
990        lexer.extras = 0;
991
992        let parsed_bitis = parse_root(&mut lexer);
993        if let Err(s) = parsed_bitis.clone() {
994            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
995        }
996        assert_eq!(parsed_bitis.is_ok(), true);
997
998        let parsed_bitis = parsed_bitis.unwrap();
999        assert_eq!(parsed_bitis.len(), 1);
1000
1001        if let Value::Message(msg) = parsed_bitis[0].clone() {
1002            assert_eq!(msg.attributes.len(), 1);
1003            assert_eq!(msg.attributes[0].name, "a1".to_string());
1004            if let AttributeDetails::AttributeSimple(s) = msg.attributes[0].specific_details.clone() {
1005                assert_eq!(s, SimpleType::UIntFixed(7));
1006            }
1007            else { assert!(false, "Attribute type must be AttributeSimple."); }
1008        }
1009        else { assert!(false, "Value must be a message."); }
1010    }
1011
1012    #[rstest]
1013    fn msg_simple_enum() {
1014        let test_empty_msg = "enum Lala(4) { one, two }";
1015
1016        let mut lexer = Token::lexer(test_empty_msg);
1017        lexer.extras = 0;
1018
1019        let parsed_bitis = parse_root(&mut lexer);
1020        if let Err(s) = parsed_bitis.clone() {
1021            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1022        }
1023        assert_eq!(parsed_bitis.is_ok(), true);
1024
1025        let parsed_bitis = parsed_bitis.unwrap();
1026        assert_eq!(parsed_bitis.len(), 1);
1027
1028        if let Value::Enum(enm) = parsed_bitis[0].clone() {
1029            assert_eq!(enm.values.len(), 2);
1030            assert_eq!(enm.values[0], "one".to_string());
1031            assert_eq!(enm.values[1], "two".to_string());
1032        }
1033        else { assert!(false, "Value must be a message."); }
1034    }
1035
1036
1037    /*#[rstest]
1038        #[case::float("float", SimpleType::Float)]
1039        #[case::uint_12("uint_12", SimpleType::UIntFixed(12))]
1040        #[case::uint_32d4("uint_32d4", SimpleType::UIntDyn((32,4)))]
1041        #[case::bool("bool", SimpleType::Bool)]
1042        fn msg_various_attribute_types(#[case] attr_type_str: String, #[case] attr_type: SimpleType) {
1043            let test_msg = format!("msg Lala [fixed] {{ {attr_type_str} attr; }}");
1044
1045            let mut lexer = Token::lexer(test_msg.as_str());
1046            lexer.extras = 0;
1047
1048            let parsed_bitis = parse_root(&mut lexer);
1049            assert_eq!(parsed_bitis.is_ok(), true);
1050
1051            let parsed_bitis = parsed_bitis.unwrap();
1052            assert_eq!(parsed_bitis.len(), 1);
1053
1054            assert!(if let Value::Message(_) = parsed_bitis[0].clone() { true } else { false });
1055
1056            if let Value::Message(msg) = parsed_bitis[0].clone() {
1057                assert_eq!(msg.name, "Lala".to_string());
1058
1059                assert_eq!(msg.attributes.len(), 1);
1060                assert_eq!(msg.attributes[0].name, "attr".to_string());
1061
1062                assert!(if let AttributeDetails::AttributeSimple(_) = msg.attributes[0].specific_details.clone() { true } else { false });
1063
1064                if let AttributeDetails::AttributeSimple(at) = msg.attributes[0].specific_details.clone() {
1065                    assert_eq!(at, attr_type);
1066                }
1067            }
1068
1069            let validate_result = validate_bitis(&parsed_bitis);
1070            println!("validate_result: {:?}", validate_result);
1071            assert!(validate_result.is_none());
1072        }*/
1073}
1074
1075#[cfg(test)]
1076mod bitis_generate_rust {
1077    use rstest::rstest;
1078    use super::*;
1079
1080    const HEADER: &str = "use bitis_lib::*;\n\n";
1081    const ENUMS_HEADER: &str = "// Enums\n";
1082    const OO_HEADER: &str = "// Enums for oneof\n";
1083    const MSG_HEADER: &str = "// Messages\n";
1084    const PER_ENUM_HEADER: &str = "#[derive(BiserdiEnum, Debug, Clone, PartialEq)]\n#[biserdi_enum_id_dynbits(3)]\n#[allow(nonstandard_style)]\n";
1085    const PER_OO_HEADER: &str = "#[derive(BiserdiOneOf, Debug, Clone, PartialEq)]\n#[biserdi_enum_id_dynbits(3)]\n#[allow(nonstandard_style)]\n";
1086    const PER_MSG_HEADER: &str = "#[derive(BiserdiMsg, Debug, Clone, PartialEq)]\n#[allow(nonstandard_style)]\n";
1087
1088    #[rstest]
1089    fn msg_empty_msg() {
1090        let test_empty_msg = "msg Lala { }";
1091
1092        let mut lexer = Token::lexer(test_empty_msg);
1093        lexer.extras = 0;
1094
1095        let parsed_bitis = parse_root(&mut lexer);
1096        if let Err(s) = parsed_bitis.clone() {
1097            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1098        }
1099        assert_eq!(parsed_bitis.is_ok(), true);
1100
1101        let parsed_bitis = parsed_bitis.unwrap();
1102        assert_eq!(parsed_bitis.len(), 1);
1103
1104        let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1105        let rdo = RustDataObjects{ d: JinjaData{
1106            enums: processed_bitis.enums,
1107            msgs: to_rust_messages(&processed_bitis.msgs),
1108            oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1109
1110        let rendered = rdo.render().unwrap();
1111        let lala_empty = "pub struct Lala {\n}\n";
1112        assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + "\n\n"  +
1113            MSG_HEADER + PER_MSG_HEADER +lala_empty).to_string());
1114    }
1115
1116    #[rstest]
1117    fn msg_simple_msg() {
1118        let test_empty_msg = "//| comment for Lala\nmsg Lala { uint_5 a1; repeated_fixed_4 bool bool_array; }";
1119        println!("Input code:\n{}", test_empty_msg);
1120
1121        let mut lexer = Token::lexer(test_empty_msg);
1122        lexer.extras = 0;
1123
1124        let parsed_bitis = parse_root(&mut lexer);
1125        if let Err(s) = parsed_bitis.clone() {
1126            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1127        }
1128        assert_eq!(parsed_bitis.is_ok(), true);
1129
1130        let parsed_bitis = parsed_bitis.unwrap();
1131        assert_eq!(parsed_bitis.len(), 1);
1132
1133        let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1134        let rdo = RustDataObjects{ d: JinjaData{
1135            enums: processed_bitis.enums, msgs: to_rust_messages(&processed_bitis.msgs),
1136            oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1137
1138        let rendered = rdo.render().unwrap();
1139        let lala_commment = "/// comment for Lala\n";
1140        let lala_empty = "pub struct Lala {\n  pub a1: VarWithGivenBitSize<u8, 5>,\n  pub bool_array: FixedArray<bool,4>,\n}\n";
1141        println!("rendered:\n{}",rendered);
1142        assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + "\n\n" +
1143            MSG_HEADER + lala_commment + PER_MSG_HEADER +lala_empty).to_string());
1144    }
1145
1146    #[rstest]
1147    fn msg_simple_enum() {
1148        let test_enum_msg = "//| comment for Numbers\nenum Numbers(3) {\n  // Comment for One\n  One,\n  Two,\n  Three\n}";
1149        println!("Input code:\n{}", test_enum_msg);
1150
1151        let mut lexer = Token::lexer(test_enum_msg);
1152        lexer.extras = 0;
1153
1154        let parsed_bitis = parse_root(&mut lexer);
1155        if let Err(s) = parsed_bitis.clone() {
1156            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_enum_msg[s.1.clone()], s.1);
1157        }
1158        assert_eq!(parsed_bitis.is_ok(), true);
1159
1160        let parsed_bitis = parsed_bitis.unwrap();
1161        assert_eq!(parsed_bitis.len(), 1);
1162
1163        let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1164        let rdo = RustDataObjects{ d: JinjaData{ enums: processed_bitis.enums,
1165            msgs: to_rust_messages(&processed_bitis.msgs),
1166            oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1167
1168        let rendered = rdo.render().unwrap();
1169        let lala_commment = "/// comment for Numbers\n";
1170        let lala_enum = "pub enum Numbers {\n  One,\n  Two,\n  Three,\n}\n\n";
1171        println!("*rendered:\n{}",rendered);
1172        assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + lala_commment + PER_ENUM_HEADER + lala_enum + OO_HEADER +
1173            "\n\n" + MSG_HEADER ).to_string());
1174    }
1175
1176    #[rstest]
1177    fn msg_simple_oneof() {
1178        let test_enum_msg = "//| comment for Oneof\nmsg TestOO {\n  oneof oo_li(3) { uint_3 test1; float test2; }\n  bool b1;\n}";
1179        println!("Input code:\n{}", test_enum_msg);
1180
1181        let mut lexer = Token::lexer(test_enum_msg);
1182        lexer.extras = 0;
1183
1184        let parsed_bitis = parse_root(&mut lexer);
1185        if let Err(s) = parsed_bitis.clone() {
1186            panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_enum_msg[s.1.clone()], s.1);
1187        }
1188        assert_eq!(parsed_bitis.is_ok(), true);
1189
1190        let parsed_bitis = parsed_bitis.unwrap();
1191        assert_eq!(parsed_bitis.len(), 1);
1192
1193        let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1194        let rdo = RustDataObjects{ d: JinjaData{ enums: processed_bitis.enums,
1195            msgs: to_rust_messages(&processed_bitis.msgs),
1196            oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1197
1198        let rendered = rdo.render().unwrap();
1199        let testoo_commment = "/// comment for Oneof\n";
1200        let testoo_enum = "pub enum OO_TestOo_OoLi {\n  Test1(VarWithGivenBitSize<u8, 3>),\n  Test2(f32),\n}\n\n";
1201        let testoo_msg = "pub struct TestOo {\n  pub oo_li: OO_TestOo_OoLi,\n  pub b1: bool,\n}\n";
1202        println!("*rendered:\n{}",rendered);
1203        assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + PER_OO_HEADER
1204            + testoo_enum + MSG_HEADER + testoo_commment + PER_MSG_HEADER + testoo_msg).to_string());
1205    }
1206}
1207
1208#[cfg(test)]
1209mod bitis_compile {
1210    use std::fs;
1211    use std::path::Path;
1212    use rstest::rstest;
1213    use super::*;
1214
1215    fn compile(content: &str) -> BitisProcessed {
1216        let mut lexer = Token::lexer(content);
1217        lexer.extras = 0;
1218        println!("*** content:\n{}", content);
1219        let bitis_parsed = match parse_root(&mut lexer) {
1220            Ok(v) => v,
1221            Err(e) => {
1222                let (err_str, err_span) = e.clone();
1223                let content_err = &content[err_span];
1224                println!("Error: {}\n  -> Source: '{}'", err_str, content_err);
1225                abort()
1226            }
1227        };
1228        println!("** content:\n{:?}", bitis_parsed);
1229        process_and_validate_bitis(&bitis_parsed)
1230    }
1231    fn render(d: JinjaData) {
1232        let rdo = RustDataObjects{ d: d.clone() };
1233        let rendered_rust = rdo.render().unwrap();
1234        println!("*** rendered DO:\n{}", rendered_rust);
1235        fs::write(Path::new("./test_data/test_py/bitis/src/messages_test.rs"), rendered_rust).expect("Unable to write file");
1236
1237        let rdo = RustPyDataObjects{ d: d.clone() };
1238        let rendered_rust = rdo.render().unwrap();
1239        println!("*** rendered PyDO:\n{}", rendered_rust);
1240        fs::write(Path::new("./test_data/test_py/bitis/src/pyrust_test.rs"), rendered_rust).expect("Unable to write file");
1241
1242        let rdo = RustPyLib{ d: d.clone(), lib_name: "bitis_msgs".into() };
1243        let rendered_rust = rdo.render().unwrap();
1244        println!("*** rendered pyLib:\n{}", rendered_rust);
1245        fs::write(Path::new("./test_data/test_py/bitis/src/lib_test.rs"), rendered_rust).expect("Unable to write file");
1246
1247        let rdo = PyTypeHints{ d };
1248        let rendered_rust = rdo.render().unwrap();
1249        println!("*** rendered py_type_hints:\n{}", rendered_rust);
1250        fs::write(Path::new("./test_data/test_py/bitis/bitis_msgs/bitis_msgs.pyi"), rendered_rust).expect("Unable to write file");
1251    }
1252
1253    #[rstest]
1254    #[ignore]
1255    fn simple_rust_py() {
1256        let bitis_str = "msg ParamTestSimple { uint_4 param_1; bool param_2; }";
1257
1258        let bitis_processed_org = compile(bitis_str);
1259
1260        let bitis_processed = bitis_processed_org.clone();
1261        let d = JinjaData{
1262            enums: bitis_processed.enums,
1263            msgs: to_rust_messages(&bitis_processed.msgs),
1264            oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1265        };
1266        render(d);
1267    }
1268
1269    #[rstest]
1270    #[ignore]
1271    fn nested_rust_py() {
1272        let bitis_str = "msg Inner { uint_2 val; }\nmsg ParamTestWithInner { uint_4 param_1; bool param_2; Inner inner; }";
1273
1274        let bitis_processed_org = compile(bitis_str);
1275
1276        let bitis_processed = bitis_processed_org.clone();
1277
1278        let d = JinjaData{
1279            enums: bitis_processed.enums,
1280            msgs: to_rust_messages(&bitis_processed.msgs),
1281            oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1282        };
1283        render(d);
1284    }
1285    #[test]
1286    #[ignore]
1287    fn nested_and_enum_rust_py() {
1288        let bitis_str = [
1289            "enum Numbers(4) { one, two, three, four }\n/// Test comment for Inner\nmsg Inner { uint_3 val; Numbers num; }\n",
1290            "msg ParamTestWithInner { uint_4 param_1; bool param_2; Inner inner; } }"
1291        ].join("");
1292
1293        let bitis_processed_org = compile(bitis_str.as_str());
1294
1295        let bitis_processed = bitis_processed_org.clone();
1296
1297        let d = JinjaData{
1298            enums: bitis_processed.enums,
1299            msgs: to_rust_messages(&bitis_processed.msgs),
1300            oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1301        };
1302        render(d);
1303    }
1304    #[test]
1305    fn oneof_nested_and_enum_rust_py() {
1306        let bitis_str = [
1307            "//| Test comment for Enum\nenum Numbers(4) { one, two, three, four }\n\n//| Test comment for Inner\nmsg Inner { uint_3 val; Numbers num; }\n",
1308            "msg ParamTestWithInner { uint_4 param_1; bool param_2; oneof action(4) { Inner inner; uint_3 val; } }"
1309        ].join("");
1310
1311        let bitis_processed_org = compile(bitis_str.as_str());
1312
1313        let bitis_processed = bitis_processed_org.clone();
1314
1315        let d = JinjaData{
1316            enums: bitis_processed.enums,
1317            msgs: to_rust_messages(&bitis_processed.msgs),
1318            oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1319        };
1320        render(d);
1321    }
1322}
1323
1324#[cfg(test)]
1325mod bitis_serialization {
1326    // use std::fs;
1327    use rstest::rstest;
1328    use super::*;
1329
1330    //noinspection DuplicatedCode
1331    #[rstest]
1332    fn msg_simple_msg_compile() {
1333        let test_empty_msg = "msg Lala { repeated_fixed_10 bool data_bool; uint_4 data1_uint; uint_12 data2_uint; }";
1334
1335        let mut lexer = Token::lexer(test_empty_msg);
1336        lexer.extras = 0;
1337
1338        let parsed_bitis = parse_root(&mut lexer);
1339        assert_eq!(parsed_bitis.is_ok(), true);
1340
1341        let _parsed_bitis = parsed_bitis.unwrap();
1342
1343        // let rdo = RustDataObjects {
1344        //     enums: parsed_bitis.iter().filter_map(|x|
1345        //         match x {
1346        //             Value::Enum(ev) => Some((ev.name.clone(), ev.clone())),
1347        //             _ => None
1348        //         })
1349        //         .collect::<HashMap<_, _>>(),
1350        //     msgs: parsed_bitis.iter().filter_map(|x|
1351        //         match x {
1352        //             Value::Message(mv) => Some((mv.name.clone(), mv.clone())),
1353        //             _ => None
1354        //         })
1355        //         .collect::<HashMap<_, _>>(),
1356        // };
1357        //
1358        // let rendered = rdo.render().unwrap();
1359        //
1360        // let current_test_simple_code = String::from(std::str::from_utf8(&fs::read("test_data/test_simple_msg.rs")
1361        //     .expect("Unable to read test_simple_msg.rs file")).unwrap());
1362        // assert_eq!(current_test_simple_code, rendered);
1363        //
1364        // let validate_result = validate_bitis(&parsed_bitis);
1365        // println!("validate_result: {:?}", validate_result);
1366        // assert!(validate_result.is_none());
1367    }
1368}
1369
1370#[cfg(test)]
1371mod bitis_processing {
1372    use rstest::rstest;
1373    use crate::AttributeDetails::{AttributeEnumOrMsg, AttributeSimple};
1374    use super::*;
1375
1376    #[rstest]
1377    #[ignore]
1378    fn msg_base_and_v2() {
1379        let bitis_values = vec![
1380            Value::Message(Message{
1381                name: "TestMsg".to_string(),
1382                /*version_info: VersionInfo::BaseWithAllowedVersion(0),*/
1383                comment: Some("This is a test".to_string()),
1384                parent: None,
1385                attributes: vec![Attribute{name: "a1".to_string(), comment: None,
1386                    is_repeated_and_size: None, is_optional: false,
1387                    specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1388                }],
1389            }),
1390            Value::Message(Message{
1391                name: "TestMsg".to_string(),
1392                /*version_info: VersionInfo::Version(2),*/
1393                comment: Some("This is a test".to_string()),
1394                parent: None,
1395                attributes: vec![Attribute{name: "a2".to_string(), comment: None,
1396                    is_repeated_and_size: None, is_optional: false,
1397                    specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1398                }],
1399            })
1400        ];
1401        let pb = process_and_validate_bitis(&bitis_values);
1402
1403        assert_eq!(pb.max_version_number, 2);
1404        assert_eq!(pb.msgs.len(), 3);
1405
1406        assert_eq!(pb.msgs[0].name, "TestMsg_Base".to_string());
1407        assert_eq!(pb.msgs[1].name, "TestMsg_V1".to_string());
1408        assert_eq!(pb.msgs[2].name, "TestMsg_V2".to_string());
1409
1410        assert_eq!(pb.msgs[0].attributes.len(), 1);
1411        assert_eq!(pb.msgs[0].attributes.get(0).unwrap().name, "a1".to_string());
1412        assert_eq!(pb.msgs[1].attributes.len(), 0);
1413        assert_eq!(pb.msgs[2].attributes.len(), 1);
1414        assert_eq!(pb.msgs[2].attributes.get(0).unwrap().name, "a2".to_string());
1415    }
1416
1417    #[rstest]
1418    #[ignore]
1419    fn msg_base_and_v2_and_add_msg() {
1420        let bitis_values = vec![
1421            Value::Message(Message{
1422                name: "TestMsgInner".to_string(),
1423                /*version_info: VersionInfo::BaseWithAllowedVersion(0),*/
1424                comment: Some("This is a test2".to_string()),
1425                parent: None,
1426                attributes: vec![Attribute{name: "lala".to_string(), comment: None,
1427                    is_repeated_and_size: None, is_optional: false,
1428                    specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1429                }],
1430            }),
1431            Value::Message(Message{
1432                name: "TestMsgInner".to_string(),
1433                /*version_info: VersionInfo::Version(1),*/
1434                comment: Some("This is a test2".to_string()),
1435                parent: None,
1436                attributes: vec![
1437                    Attribute{name: "lala".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1438                        specific_details: AttributeSimple(SimpleType::UIntFixed(4)),},
1439                    Attribute{name: "lala2".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1440                        specific_details: AttributeSimple(SimpleType::UIntFixed(3)),},
1441                ],
1442            }),
1443            Value::Message(Message{
1444                name: "TestMsg".to_string(),
1445                /*version_info: VersionInfo::BaseWithAllowedVersion(0),*/
1446                comment: Some("This is a test".to_string()),
1447                parent: None,
1448                attributes: vec![
1449                    Attribute{ name: "a1".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1450                        specific_details: AttributeSimple(SimpleType::UIntFixed(4)) },
1451                    Attribute{ name: "lala_use".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1452                        specific_details: AttributeEnumOrMsg("TestMsgInner".to_string()) },
1453                ],
1454            }),
1455            Value::Message(Message{
1456                name: "TestMsg".to_string(),
1457                /*version_info: VersionInfo::Version(2),*/
1458                comment: Some("This isa test".to_string()),
1459                parent: None,
1460                attributes: vec![Attribute{name: "a2".to_string(), comment: None,
1461                    is_repeated_and_size: None, is_optional: false,
1462                    specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1463                }],
1464            }),
1465        ];
1466        let pb = process_and_validate_bitis(&bitis_values);
1467
1468        assert_eq!(pb.max_version_number, 2);
1469        assert_eq!(pb.msgs.len(), 4);
1470
1471/*        assert_eq!(pb.msgs[0].name, "TestMsg_Base".to_string());
1472        assert_eq!(pb.msgs[1].name, "TestMsg_V1".to_string());
1473        assert_eq!(pb.msgs[2].name, "TestMsg_V2".to_string());
1474        assert_eq!(pb.msgs[3].name, "TestMsgLala".to_string());
1475
1476        if let MsgVersion::Versioned(l) = pb.msgs[0].version { assert_eq!(l, 0); }
1477        assert_eq!(pb.msgs[0].attributes.len(), 1);
1478        assert_eq!(pb.msgs[0].attributes.get(0).unwrap().name, "a1".to_string());
1479        assert_eq!(pb.msgs[1].attributes.len(), 0);
1480        assert_eq!(pb.msgs[2].attributes.len(), 1);
1481        assert_eq!(pb.msgs[2].attributes.get(0).unwrap().name, "a2".to_string());
1482        if let MsgVersion::Fixed = pb.msgs[0].version { assert!(false) }
1483        assert_eq!(pb.msgs[3].attributes.len(), 1);
1484        assert_eq!(pb.msgs[3].attributes.get(0).unwrap().name, "lala".to_string());*/
1485    }
1486}
1487