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