1use std::collections::HashMap;
2use std::process::{abort};
3use askama::Template;
4use logos::{Lexer, Logos, Span};
5use regex::Regex;
6use stringcase::Caser;
7
8
9fn integer_bit_size(bit_size: &u8) -> u8 {
12 match bit_size {
13 0..=16 => 16,
14 17..=32 => 32,
17 _ => 64
18 }
19}
20#[derive(Debug, Clone )]
22#[allow(unused)]
23pub struct AttributeEx {
24 base: Attribute,
25 rust_type_str: String,
26 base_type_str: String,
28 is_py_wrapped: bool, is_msg: bool, is_enum: bool, is_oo: bool, add_val: bool,
29}
30#[derive(Debug, Clone )]
31pub struct MessageR {
32 pub name: String,
33 pub comment: Option<String>,
35 pub parent: Option<String>,
36 pub attributes: Vec<AttributeEx>,
37}
38#[derive(Debug, Clone )]
39#[allow(dead_code)]
40pub struct OneOfInfoR {
41 msg_name: String,
42 name: String,
43 dyn_bits: u8,
44 attributes: Vec<AttributeEx>,
45 default_attrib_name: String,
46}
47fn to_rust_attribute(attribute: &Attribute, msg_names: &Vec<String>) -> AttributeEx {
48 let (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val) = {
49 let mut is_py_wrapped = false;
50 let mut is_enum = false;
51 let mut is_msg = false;
52 let mut is_oo = false;
53 let mut add_val = false;
54
55 let (rtype, base_type) = match &attribute.specific_details {
56 AttributeDetails::AttributeSimple(a) => {
57 match a {
58 SimpleType::NoTypeSetYet => {
59 println!("Unexpected unspecified attribute type");
60 abort()
61 },
62 SimpleType::Bool => { ("bool".to_string(), "bool".to_string()) },
63 SimpleType::UIntFixed(b) => {
64 add_val = true;
65 let base = format!("u{}", integer_bit_size(&b));
66 (format!("IntWithGivenBitSize<{}, {}>", base.clone(), b), base) },
67 SimpleType::IntFixed(b) => {
68 add_val = true;
69 let base = format!("i{}", integer_bit_size(&b));
70 (format!("IntWithGivenBitSize<{}, {}>", base.clone(), b), base) },
71 SimpleType::UIntDyn(b) => {
72 add_val = true;
73 let base = format!("u{}", integer_bit_size(&b.0));
74 (format!("DynInteger<{}, {}, {}>", base.clone(), b.0, b.1), base) },
75 SimpleType::IntDyn(b) => {
76 add_val = true;
77 let base = format!("i{}", integer_bit_size(&b.0));
78 (format!("DynInteger<{}, {}, {}>", base.clone(), b.0, b.1), base) },
79 SimpleType::Float => {
80 add_val = true;
81 let base = "f32".to_string();
82 (base.clone(), base)
83 },
84 SimpleType::Double => {
85 let base = "f64".to_string();
86 (base.clone(), base) },
87 SimpleType::FixedPrecision(fpp) => {
88 add_val = true;
89 (format!("FixPrecisionMinMax<{}, {}, {}>", fpp.bits, fpp.min_val, fpp.max_val), "f64".to_string())
90 },
91 SimpleType::Binary(b) => {
92 add_val = true;
93 (format!("Binary<{}>", b), "Vec<u8>".to_string()) },
94 SimpleType::AString(b) => {
95 add_val = true;
96 (format!("BitisAString<{}>", b), "String".to_string()) },
97 }
98 }
99 AttributeDetails::AttributeEnumOrMsg(em) => {
100 is_py_wrapped = true;
101 is_msg = msg_names.contains(&em);
102 is_enum = !is_msg.clone();
103 (em.clone(), em.clone()) }
104 AttributeDetails::AttributeOneOf(ooi) => {
105 is_py_wrapped=true; is_oo = true;
106 (ooi.name.clone(), ooi.name.clone()) }
107 };
108 (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val)
109 };
110 AttributeEx{base: attribute.clone(), rust_type_str: rtype, base_type_str: base_type,
111 is_py_wrapped, is_msg, is_enum, is_oo, add_val }
112}
113
114pub fn to_rust_messages(msgs: &Vec<Message>) -> Vec<MessageR> {
115 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
116
117 msgs.iter().map(|msg| {
118 let attrs_rust: Vec<_> = msg.attributes.iter().map(|attribute| {
119 to_rust_attribute(attribute, &msgs_names) }).collect();
120 MessageR{name: msg.name.clone(), comment: msg.comment.clone(), parent: msg.parent.clone(),
121 attributes: attrs_rust}
122 }).collect()
123}
124pub fn to_rust_oneofs(oos: &Vec<(String, OneOfInfo)>, msgs: &Vec<Message>) -> HashMap<String, OneOfInfoR> {
125 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
126
127 oos.iter().map(|(msg_name, oo)| {
128 let attrs_rust: Vec<_> = oo.attributes.iter().map(|attribute| {
129 to_rust_attribute(attribute, &msgs_names) }).collect();
130 (oo.name.clone(), OneOfInfoR{msg_name: msg_name.clone(), name: oo.name.clone(), dyn_bits: oo.dyn_bits,
131 attributes: attrs_rust, default_attrib_name: oo.default_attrib_name.clone()})
132 }).collect()
133}
134
135fn to_cpp_attribute(attribute: &Attribute, msg_names: &Vec<String>) -> AttributeEx {
136 let (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val) = {
137 let mut is_py_wrapped = false;
138 let mut is_enum = false;
139 let mut is_msg = false;
140 let mut is_oo = false;
141 let mut add_val = false;
142
143 let (rtype, base_type) = match &attribute.specific_details {
144 AttributeDetails::AttributeSimple(a) => {
145 match a {
146 SimpleType::NoTypeSetYet => {
147 println!("Unexpected unspecified attribute type");
148 abort()
149 },
150 SimpleType::Bool => { ("BitisBool".to_string(), "bool".to_string()) }
151 SimpleType::UIntFixed(b) => {
152 add_val = true;
153 let base = format!("uint{}_t", integer_bit_size(&b));
154 (format!("IntgralWithGivenBitSize<{}, {}>", base.clone(), b), base) }
155 SimpleType::IntFixed(b) => {
156 add_val = true;
157 let base = format!("int{}_t", integer_bit_size(&b));
158 (format!("IntgralWithGivenBitSize<{}, {}>", base.clone(), b), base) }
159 SimpleType::UIntDyn(b) => {
160 add_val = true;
161 let base = format!("uint{}_t", integer_bit_size(&b.0));
162 (format!("DynInteger<{}, {}, {}>", base.clone(), b.0, b.1), base) }
163 SimpleType::IntDyn(b) => {
164 add_val = true;
165 let base = format!("int{}_t", integer_bit_size(&b.0));
166 (format!("DynInteger<{}, {}, {}>", base.clone(), b.0, b.1), base) }
167 SimpleType::Float => {
168 add_val = true;
169 let base = "float".to_string();
170 (format!("BitisFloatingPoint<{}>", base.clone()), base)
171 }
172 SimpleType::Double => {
173 let base = "double".to_string();
174 (format!("BitisFloatingPoint<{}>", base.clone()), base) },
175 SimpleType::FixedPrecision(fpp) => {
176 add_val = true;
177 (format!("FixPrecisionMinMax<{}, {}, {}>", fpp.bits, fpp.min_val, fpp.max_val), "double".to_string())
178 },
179 SimpleType::Binary(b) => {
180 add_val = true;
181 (format!("Binary<{}>", b), "Vec<u8>".to_string()) },
182 SimpleType::AString(b) => {
183 add_val = true;
184 (format!("BitisAString<{}>", b), "char *".to_string()) },
185 }
186 }
187 AttributeDetails::AttributeEnumOrMsg(em) => {
188 is_py_wrapped = true;
189 is_msg = msg_names.contains(&em);
190 is_enum = !is_msg.clone();
191 (em.clone(), em.clone()) }
192 AttributeDetails::AttributeOneOf(ooi) => {
193 is_py_wrapped=true; is_oo = true;
194 (ooi.name.clone(), ooi.name.clone()) }
195 };
196 (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val)
197 };
198 AttributeEx{base: attribute.clone(), rust_type_str: rtype, base_type_str: base_type,
199 is_py_wrapped, is_msg, is_enum, is_oo, add_val }
200}
201pub fn to_cpp_messages(msgs: &Vec<Message>) -> Vec<MessageR> {
202 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
203
204 msgs.iter().map(|msg| {
205 let attrs_rust: Vec<_> = msg.attributes.iter().map(|attribute| {
206 to_cpp_attribute(attribute, &msgs_names) }).collect();
207 MessageR{name: msg.name.clone(), comment: msg.comment.clone(), parent: msg.parent.clone(),
208 attributes: attrs_rust}
209 }).collect()
210}
211pub fn to_cpp_oneofs(oos: &Vec<(String, OneOfInfo)>, msgs: &Vec<Message>) -> HashMap<String, OneOfInfoR> {
212 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
213
214 oos.iter().map(|(msg_name, oo)| {
215 let attrs_cpp: Vec<_> = oo.attributes.iter().map(|attribute| {
216 to_cpp_attribute(attribute, &msgs_names) }).collect();
217 (oo.name.clone(), OneOfInfoR{msg_name: msg_name.clone(), name: oo.name.clone(), dyn_bits: oo.dyn_bits.clone(),
218 attributes: attrs_cpp, default_attrib_name: oo.default_attrib_name.clone() })
219 }).collect()
220}
221
222#[derive(Clone, Debug)]
223pub struct JinjaData {
224 pub enums: Vec<Enum>,
225 pub msgs: Vec<MessageR>,
226 pub oos: HashMap<String, OneOfInfoR>,
227}
228
229#[derive(Template, Clone, Debug)]
230#[template(path = "data_objects.rs.jinja")]
231pub struct RustDataObjects {
232 pub d: JinjaData
233}
234#[derive(Template, Clone, Debug)]
235#[template(path = "pyclasses.py.rs.jinja")]
236pub struct RustPyDataObjects {
237 pub d: JinjaData
238}
239#[derive(Template, Clone, Debug)]
240#[template(path = "pylib.py.rs.jinja")]
241pub struct RustPyLib {
242 pub d: JinjaData,
243 pub lib_name: String
244}
245#[derive(Template, Clone, Debug)]
246#[template(path = "py_type_hints.pyi.jinja")]
247pub struct PyTypeHints {
248 pub d: JinjaData
249}
250#[derive(Template, Clone, Debug)]
251#[template(path = "data_objects.cpp.jinja")]
252pub struct CppDataObjects {
253 pub d: JinjaData,
254 pub object_order: Vec<String>,
255 pub bitis_header_lib_file_name: String,
256 pub bitis_version: String,
257}
258
259
260mod filters {
261 #[allow(dead_code)]
262 pub fn snake_case<T: std::fmt::Display>(s: T, _: &dyn askama::Values) -> ::askama::Result<String> {
263 Ok(stringcase::snake_case(s.to_string().as_str()))
264 }
265 #[allow(dead_code)]
266 pub fn camel_case<T: std::fmt::Display>(s: T, _: &dyn askama::Values,) -> ::askama::Result<String> {
267 Ok(stringcase::camel_case(s.to_string().as_str()))
268 }
269 #[allow(dead_code)]
270 pub fn pascal_case<T: std::fmt::Display>(s: T, _: &dyn askama::Values,) -> ::askama::Result<String> {
271 Ok(stringcase::pascal_case(s.to_string().as_str()))
272 }
273 #[allow(dead_code)]
274 pub fn to_py_type<T: std::fmt::Display>(s: T, _: &dyn askama::Values,) -> ::askama::Result<String> {
275 if ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64"].contains(&s.to_string().as_str()) {
276 Ok("int".to_string()) }
277 else if ["f32", "f64"].contains(&s.to_string().as_str()) {
278 Ok("float".to_string())
279 }
280 else { Ok(s.to_string()) }
281 }
282}
283
284type Error = (String, Span);
286
287type Result<T> = std::result::Result<T, Error>;
288
289#[derive(Debug, Clone)]
290pub enum DynOrFixedType {
291 Dyn(u8),
292 Fixed(u8)
293}
294#[derive(Debug, PartialEq, Eq, Clone, Copy)]
295pub struct FixedPrecisionProperties {
296 bits: u8, min_val: i64, max_val: i64
297}
298#[derive(Debug, PartialEq, Eq, Clone, Copy)]
299pub enum SimpleType {
300 NoTypeSetYet,
301 Bool,
302 UIntFixed(u8), IntFixed(u8),
303 UIntDyn((u8,u8)), IntDyn((u8,u8)),
304 Float, Double,
305 FixedPrecision(FixedPrecisionProperties),
306 Binary(u8),
307 AString(u8)
308}
309#[derive(Debug, Clone )]
341pub struct OneOfInfo {
342 name: String,
343 dyn_bits: u8,
344 attributes: Vec<Attribute>,
345 default_attrib_name: String,
346}
347#[derive(Debug, Clone )]
348pub enum AttributeDetails {
349 AttributeSimple(SimpleType),
350 AttributeEnumOrMsg(String),
351 AttributeOneOf(OneOfInfo),
352}
353#[derive(Debug, Clone )]
354pub struct Attribute {
355 name: String,
356 comment: Option<String>,
357 is_repeated_and_size: Option<DynOrFixedType>,
358 is_optional: bool,
359 specific_details: AttributeDetails
360}
361#[derive(Debug, Clone)]
367pub struct Message {
368 pub name: String,
369 pub comment: Option<String>,
371 pub parent: Option<String>,
372 pub attributes: Vec<Attribute>,
373}
374
375#[derive(Debug, Clone)]
377pub struct Enum {
378 pub name: String,
379 pub comment: Option<String>,
381 pub bit_size: u8,
382 pub values: Vec<String>,
383 pub default: String
384}
385
386pub fn get_suffix_number(lex: &mut Lexer<Token>) -> Option<u8> {
387 let slice = lex.slice();
388 let re = Regex::new(r".*_d?([0-9]+)$").unwrap();
389 let num_str = re.captures(slice)?.get(1)?;
390 num_str.as_str().parse().ok()
391}
392pub fn get_d_suffix_numbers(lex: &mut Lexer<Token>) -> Option<(u8,u8)> {
393 let slice = lex.slice();
394 let re = Regex::new(r".*_([0-9]+)d([0-9]+)$").unwrap();
395 let first_num_str = re.captures(slice)?.get(1)?.as_str().parse().ok()?;
396 let second_num_str = re.captures(slice)?.get(2)?.as_str().parse().ok()?;
397 Some((first_num_str, second_num_str))
398}
399pub fn get_fp_properties_number(lex: &mut Lexer<Token>) -> Option<FixedPrecisionProperties> {
400 let slice = lex.slice();
401 let re = Regex::new(r"fp_([0-9]+)\[ *(-?[0-9]+) *, *(-?[0-9]+) *]").unwrap();
402 let bits = re.captures(slice)?.get(1)?.as_str().parse::<u8>().ok()?;
403 let min_val = re.captures(slice)?.get(2)?.as_str().parse::<i64>().ok()?;
404 let max_val = re.captures(slice)?.get(3)?.as_str().parse::<i64>().ok()?;
405 Some(FixedPrecisionProperties {bits, min_val, max_val})
406}
407pub fn get_enum_bit_size(lex: &mut Lexer<Token>) -> Option<u8> {
420 let slice = lex.slice();
421 let re = Regex::new(r"\( *([0-9]+) *\)").unwrap();
422 let bits = re.captures(slice)?.get(1)?.as_str().parse::<u8>().ok()?;
423 Some(bits)
424}
425pub fn get_version(lex: &mut Lexer<Token>) -> Option<u16> {
426 let slice = lex.slice();
427 let re = Regex::new(r"\[.* +(v[0-9]+) *]").unwrap();
428 let ver_str = re.captures(slice)?.get(1)?.as_str();
429 Some(ver_str.parse::<u16>().ok()?)
430}
431
432#[derive(Debug, Logos)]
433#[logos(skip r"[ \t\r\n\f]+")]
434#[logos(extras = u16)]
435#[allow(dead_code)]
436pub enum Token{
437 #[regex(r"//[^\n]*\n?", priority=40)] Comment,
438 #[regex(r"//\|[^\n]*\n?", |lex| lex.slice()[3..].to_owned(), priority=41)] SpecificComment(String),
439 #[token("msg", priority=20)] Msg,
440 #[token("enum", priority=20)] Enum,
441 #[token("oneof", priority=20)] OneOf,
442 #[token("{")] CBraceOpen,
443 #[token("}")] CBraceClose,
444 #[token("(")] BraceOpen,
445 #[token(")")] BraceClose,
446 #[token(":")] Colon,
447 #[token(";")] SemiColon,
448 #[token(",")] Comma,
449 #[token("*")] Star,
450 #[regex(r"\[ *base +use +starting +with +v[0-9]+ *\]", get_version, priority=35)] MsgBaseInfoToken(u16),
453 #[regex(r"\[ *version +v[0-9]+ *\]", get_version, priority=35)] MsgVersionToken(u16),
454 #[regex("[0-9]+", |lex| lex.slice().parse::<isize>().unwrap(), priority=1)] IntegerVal(isize),
456 #[regex(r"-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?",
457 |lex| lex.slice().parse::<f64>().unwrap(), priority=2)] Number(f64),
458 #[token("bool", priority=30)] Bool,
459 #[token("msg_size_type", priority=30)] MsgSizeType,
460 #[regex(r"uint_[0-9]+", get_suffix_number, priority=30)] UIntFixed(u8),
461 #[regex(r"int_[0-9]+", get_suffix_number, priority=30)] IntFixed(u8),
462 #[regex(r"uint_[0-9]+d[0-9]+", get_d_suffix_numbers, priority=31)] UIntDyn((u8,u8)),
463 #[regex(r"int_[0-9]+d[0-9]+", get_d_suffix_numbers, priority=31)] IntDyn((u8,u8)),
464 #[token("float", priority=30)] Float,
465 #[token("double", priority=30)] Double,
466 #[regex(r"astr_d[0-9]+", get_suffix_number, priority=31)] AStr(u8),
467 #[regex(r"fp_[0-9]+\[ *-?[0-9]+ *, *-?[0-9]+ *]", get_fp_properties_number, priority=30)] FixedPoint(FixedPrecisionProperties),
468 #[token("binary_d[0-9]+", get_suffix_number, priority=30)] Binary(u8),
470 #[regex(r"repeated_dyn_[0-9]+", get_suffix_number, priority=30)] RepeatedDyn(u8),
471 #[regex(r"repeated_fixed_[0-9]+", get_suffix_number, priority=30)] RepeatedFixed(u8),
472 #[token("optional", priority=30)] Optional,
473 #[regex(r"[A-Za-z][A-Za-z0-9_-]+", |lex| lex.slice().to_owned(), priority=11)] StringVal(String),
474 #[token("false", |_| false, priority=20)]
475 #[token("true", |_| true, priority=20)] BoolVal(bool),
476 #[regex(r"\( *([0-9]+) *\)", get_enum_bit_size, priority=40)] EnumDynSize(u8),
477}
478
479#[derive(Debug, Clone)]
480pub enum Value {
481 Message(Message),
483 Enum(Enum)
485}
486
487macro_rules! parse_one_token {
488 ($token_enum: path, $lexer: expr, $error_msg_or_empty: expr) => {
489 loop {
490 let rv = $lexer.next();
491 if let Some(token) = rv {
492 match token {
493 Ok($token_enum) => {
494 break Ok(Ok(()));
495 },
496 Ok(Token::Comment) => (),
497 _ => {
498 if let Some(err_str) = $error_msg_or_empty {
499 break Err((format!("{err_str}\nToken: {token:?}").to_owned(), $lexer.span()));
500 }
501 else {
502 break Ok(Err($lexer.span()));
503 }
504 }
505 }
506 }
507 else {
508 break Err((format!("Unexpected end or text {rv:?}").to_owned(), $lexer.span()));
509 }
510 }
511 }
512}
513macro_rules! parse_one_token_with_arg {
514 ($token_enum: path, $lexer: expr, $error_msg_or_empty: expr) => {
515 loop {
516 let rv = $lexer.next();
517 if let Some(token) = rv {
518 match token {
519 Ok($token_enum(s)) => {
520 break Ok(Ok(s));
521 },
522 Ok(Token::Comment) => (),
523 _ => {
524 if let Some(err_str) = $error_msg_or_empty {
525 break Err((format!("{}\nFound token: {:?}.",
526 err_str, token).to_owned(), $lexer.span()));
527 }
528 else {
529 break Ok(Err($lexer.span()));
530 }
531 }
532 }
533 }
534 else {
535 break Err((format!("Unexpected end or text {rv:?}").to_owned(), $lexer.span()));
536 }
537 }
538 }
539}
540
541pub fn parse_root(lexer: &mut Lexer<'_, Token>) -> Result<Vec<Value>> {
542 let mut list: Vec<Value> = Vec::new();
543 let mut specific_comment: Option<String> = None;
544 loop {
545 if let Some(token) = lexer.next() {
546 let rv = match token {
547 Ok(Token::Msg) => Some(parse_msg(lexer, specific_comment.clone())),
548 Ok(Token::Enum) => Some(parse_enum(lexer, specific_comment.clone())),
549 Ok(Token::Comment) => None,
550 Ok(Token::SpecificComment(s)) => {
551 specific_comment = Some(s.trim().to_string()); None },
552 _ => Some(Err((format!("Unexpected token {:?}", token).to_owned(), lexer.span()))),
553 };
554 match rv {
555 None => (),
556 Some(Ok(value)) => { list.push(value); specific_comment = None; },
557 Some(Err(err)) => return Err(err)
558 }
559 }
560 else { break; }
561 }
562 Ok(list)
563}
564
565pub fn parse_msg(lexer: &mut Lexer<'_, Token>, comment_for_msg: Option<String>) -> Result<Value> {
566 let mut attributes = Vec::new();
567
568 let name = match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name but received:"))? {
569 Ok(s) => s,
570 Err(s) => { return Err(("Code should not be reached".into(), s)); }
571 };
572
573 let parent = {
587 let has_parent; let p;
588 if let Some(token) = lexer.next() {
589 match token {
590 Ok(Token::Colon) => has_parent = true,
591 Ok(Token::CBraceOpen) => has_parent = false,
592 _ => { return Err((format!("Unexpected text for msg '{name}'.").into(), lexer.span())) },
593 }
594 if has_parent {
595 match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name."))? {
596 Ok(s) => p = Some(s),
597 Err(s) => { return Err((format!("For msg '{name} colon found but no parent name").into(), s)); }
598 };
599 parse_one_token!(Token::CBraceOpen, lexer, Some(format!("Expected curly bracket open for msg '{name}'")))?.unwrap();
600 }
601 else {
602 p = None
603 }
604 }
605 else { return Err(("Unexpected end of file".into(), lexer.span())); }
606 p
607 };
608
609 loop {
610 if let Some(token) = lexer.next() {
611 match token {
612 Ok(Token::CBraceClose) => break,
613 Ok(Token::Comment) => (),
614 Ok(ctoken) => match parse_attribute(ctoken, lexer, name.clone(), false) {
615 Ok(a) => { attributes.push(a); },
616 Err(e) => { return Err(e); }
617 },
618 _ => { return Err((format!("Error: Unexpected text found for msg '{name}'.").into(), lexer.span())) },
619 };
620 }
621 else { return Err(("Unexpected end of file".into(), lexer.span())); }
622 }
623
624 Ok(Value::Message(Message{name, comment: comment_for_msg, parent, attributes}))
625}
626
627pub fn parse_attribute(last_token: Token, lexer: &mut Lexer<'_, Token>,
628 parent_name: String, attributes_for_oneof: bool) -> Result<Attribute> {
629 let mut is_optional = false;
630 let mut is_repeated_and_size: Option<DynOrFixedType> = None;
631 let mut attr_type = SimpleType::NoTypeSetYet;
632 let mut ctoken = last_token;
633 let mut enum_or_msg_str = None;
634 let mut oneof_infos = None;
635 let lexer_span_start = lexer.span();
636 let mut specific_comment: Option<String> = None;
637
638 loop {
639 match ctoken {
640 Token::SpecificComment(s) => {
641 specific_comment = Some(s); () },
642 Token::Optional if is_repeated_and_size.is_some() =>
643 return Err(("Error: Optional and repeated not allowed together".to_owned(), lexer.span())),
644 Token::RepeatedFixed(_) | Token::RepeatedDyn(_) if is_optional =>
645 return Err(("Error: Optional and repeated are not allowed together".to_owned(), lexer.span())),
646
647 Token::Optional | Token::RepeatedDyn(_) | Token::RepeatedFixed(_) if attributes_for_oneof =>
648 return Err(("Error: Optional and repeated are not allowed in oneof".to_owned(), lexer.span())),
649
650 Token::Optional => is_optional = true,
651 Token::RepeatedDyn(b) => is_repeated_and_size = Some(DynOrFixedType::Dyn(b)),
652 Token::RepeatedFixed(b) => is_repeated_and_size = Some(DynOrFixedType::Fixed(b)),
653 Token::Bool => { attr_type = SimpleType::Bool; break; },
654 Token::AStr(s) => {
655 attr_type = SimpleType::AString(s); break; },
656 Token::UIntFixed(s) => { attr_type = SimpleType::UIntFixed(s); break; },
657 Token::UIntDyn((m,s)) if m < s =>
658 return Err(("Error: Unsigned dyn integer bit size of integer type must be bigger than the bit size of the package".to_owned(), lexer.span())),
659 Token::UIntDyn((m,s)) => { attr_type = SimpleType::UIntDyn((m, s)); break; },
663 Token::IntFixed(s) => { attr_type = SimpleType::IntFixed(s); break; },
664 Token::IntDyn((m,s)) if m < s =>
665 return Err(("Error: Unsigned dyn integer bit size of integer type must be bigger than the bit size of the package".to_owned(), lexer.span())),
666 Token::IntDyn((m,s)) => {
670 attr_type = SimpleType::IntDyn((m,s)); break;
671 },
672 Token::Float => { attr_type = SimpleType::Float; break; },
674 Token::Double => { attr_type = SimpleType::Double; break; },
675 Token::FixedPoint(s) => { attr_type = SimpleType::FixedPrecision(s); break; },
676 Token::Binary(b) => { attr_type = SimpleType::Binary(b); break; },
677 Token::StringVal(s) => { enum_or_msg_str = Some(s); break; }
678 Token::OneOf if is_optional || is_repeated_and_size.is_some() =>
679 return Err(("Error: Oneof is not allowed to be used with modifiers".to_owned(), lexer.span())),
680 Token::OneOf => {
681 oneof_infos = match parse_oneof(lexer, parent_name.clone(), specific_comment.clone(),
682 is_repeated_and_size.clone(), is_optional.clone()) {
683 Ok(oo) => Some(oo),
684 Err(s) => { return Err(s); }
685 };
686 break;
687 }
688 _ => { return Err((format!("Error: Expected attribute type or modifier (got {ctoken:?}) when parsing msg or oneof '{parent_name}'")
689 .to_owned(), lexer.span())); }
690 }
691 if let Some(token) = lexer.next() {
692 match token {
693 Ok(t) => ctoken = t,
694 Err(_) => { return Err((format!("Error: Unexpected text found for msg '{parent_name}'.").to_owned(), lexer.span())); }
695 }
696 } else {
697 return Err(("Unexpected end of file".to_string(), lexer.span()));
698 }
699 }
700
701 let mut name= "".to_owned();
702 if oneof_infos.is_none() {
703 name = parse_one_token_with_arg!(
704 Token::StringVal, lexer, Some(format!("Error: Expected attribute name for msg '{parent_name}' (type: {attr_type:?}/{enum_or_msg_str:?})")))?.unwrap();
705
706 parse_one_token!(Token::SemiColon, lexer, Some(format!(
707 "Error: Expected semicolon to end line of attribute '{name}' of msg or oneof '{parent_name}'")))?.unwrap();
708 }
709 let num_of_set_types_or_opts = vec![(attr_type != SimpleType::NoTypeSetYet), enum_or_msg_str.is_some(), oneof_infos.is_some()]
710 .iter().map(|&x| if x { 1_u8 } else { 0_u8 }).sum::<u8>();
711 if num_of_set_types_or_opts > 1 {
712 let mut span = lexer_span_start.clone();
713 span.end = lexer.span().end;
714 return Err(("Error: Attribute contains inconsistent optional, simple types and messages or Enums".to_string(), span));
715 }
716
717 if let Some(oo) = oneof_infos {
718 Ok(oo)
719 }
720 else if let Some(t) = enum_or_msg_str {
721 Ok(Attribute{name, comment: specific_comment,
722 is_repeated_and_size: is_repeated_and_size, is_optional,
723 specific_details: AttributeDetails::AttributeEnumOrMsg(t)})
724 }
725 else {
726 Ok(Attribute{name, comment: specific_comment,
727 is_repeated_and_size: is_repeated_and_size, is_optional,
728 specific_details: AttributeDetails::AttributeSimple(attr_type)})
729 }
730}
731
732pub fn parse_oneof(lexer: &mut Lexer<'_, Token>, parent_name: String, comment: Option<String>,
733 is_repeated_and_size: Option<DynOrFixedType>, is_optional: bool) -> Result<Attribute> {
734 let oo_name = parse_one_token_with_arg!(
735 Token::StringVal, lexer, Some(format!("Error: Expected name for oneof in parent '{parent_name}'")))?.unwrap();
736
737 let bit_size = match parse_one_token_with_arg!(Token::EnumDynSize, lexer, Some("Expected oneof properties for dyn size, e.g. (4)."))? {
738 Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
739 };
740
741 parse_one_token!(Token::CBraceOpen, lexer, Some("Error: Expected open curly bracket to enclose oneof elements"))?.unwrap();
742
743 let mut oo_attribs = Vec::new();
744 let mut is_default = false; let mut default_name = None;
745 loop {
746 if let Some(token) = lexer.next() {
747 match token {
748 Ok(Token::CBraceClose) => break,
749 Ok(Token::Comment) => { },
750 Ok(Token::Star) => { is_default = true; },
751 Ok(last_token) => {
752 let oo_attr = match parse_attribute(last_token, lexer, oo_name.clone(), true) {
753 Ok(o) => o,
754 Err(s) => return Err(s),
755 };
756 oo_attribs.push(oo_attr.clone());
757
758 if is_default {
759 if default_name.is_some() {
760 return Err((format!("Error: Multiple attributes of one-of '{}' (in '{}') are marked as default.",
761 oo_name, parent_name), lexer.span())); }
762 default_name = Some(oo_attr.name); is_default = false;
763 }
764 }
765 Err(_) => { return Err((format!("Error: Unexpected text when decoding oneof ({token:?})").to_owned(), lexer.span())); },
766 }
767 }
768 }
769
770 if default_name.is_none() {
771 return Err((format!("Error: No default name in oneof elements for '{}' in '{}'",
772 oo_name, parent_name), lexer.span()));
773 }
774
775 Ok(Attribute{name: oo_name.clone(), comment,
776 is_repeated_and_size: is_repeated_and_size, is_optional,
777 specific_details: AttributeDetails::AttributeOneOf(OneOfInfo{
778 name: format!("OO_{}_{}", parent_name.to_pascal_case(), oo_name.to_pascal_case()),
779 dyn_bits: bit_size, attributes: oo_attribs,
780 default_attrib_name: default_name.unwrap(),
781 })})
782}
783
784pub fn parse_enum(lexer: &mut Lexer<'_, Token>, comment: Option<String>) -> Result<Value> {
785 let name = match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name but received."))? {
786 Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
787 };
788
789 let bit_size = match parse_one_token_with_arg!(Token::EnumDynSize, lexer, Some("Expected enum properties for dyn size, e.g. (4)."))? {
790 Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
791 };
792
793 parse_one_token!(Token::CBraceOpen, lexer, Some(format!("Expected open curly bracket for enum '{name}'")))?.unwrap();
807
808 let mut values = Vec::new();
809 let (mut value_found, mut is_default) = (false, false);
810 let mut default_val = None;
811 loop {
812 if let Some(token) = lexer.next() {
813 match token {
814 Ok(Token::CBraceClose) => break,
815 Ok(Token::StringVal(s)) => {
816 values.push(s.clone()); value_found=true;
817 if is_default { default_val = Some(s); }
818 is_default = false;
819 },
820 Ok(Token::Comma) => {
821 if !value_found { return Err(("Error: found comma but no enum value.".to_string(), lexer.span())) }
822 value_found=false },
823 Ok(Token::Comment) => (),
824 Ok(Token::Star) => {
825 if default_val.is_some() || value_found {
826 return Err(("Error: found default value marker (*) but default already set or marker not preceding value.".to_string(), lexer.span()))}
827 is_default = true;
828 }
829 _ => { return Err((format!("Error: Unexpected text found for enum '{name}'."), lexer.span())) },
830 }
831 } else { return Err(("Unexpected end of file".into(), lexer.span())); }
832 }
833 if default_val.is_none() { return Err(("Error: missing default value marker.".to_string(), lexer.span())); }
834
835 Ok(Value::Enum(Enum{name, comment, bit_size, values, default: default_val.unwrap() }))
836}
837
838
839#[derive(Debug, Clone)]
918pub struct Dependencies {
919 pub in_deps: Vec<String>,
920 pub out_deps: Vec<String>,
921}
922#[derive(Debug, Clone)]
923pub struct BitisProcessed {
924 pub max_version_number: u16,
925 pub msgs: Vec<Message>,
926 pub enums: Vec<Enum>,
927 pub oo_enums: Vec<(String, OneOfInfo)>,
928}
929
930pub fn process_and_validate_bitis(parsed_bitis: &Vec<Value>) -> BitisProcessed {
932 let msgs: Vec<_> = parsed_bitis.iter().filter_map(|v| {
1057 match v { Value::Message(msg) => Some(msg.clone()), _ => None }
1058 }).collect();
1059 let enums: Vec<_> = parsed_bitis.iter().filter_map(|v| {
1060 match v { Value::Enum(enm) => Some(enm.clone()), _ => None }
1061 }).collect();
1062
1063 fn get_oneofs(msg_name: String, attrs: &Vec<Attribute>) -> Option<Vec<(String, OneOfInfo)>> {
1064 let direct_oos = attrs.iter().filter_map(|attr| {
1065 match &attr.specific_details {
1066 AttributeDetails::AttributeOneOf(oo) => Some(vec![(msg_name.clone(), oo.clone())]),
1067 _ => None
1068 }
1069 }).collect::<Vec<Vec<(String, OneOfInfo)>>>().concat();
1070
1071 let inner_oos = direct_oos.iter().filter_map(|(_, doo)| {
1072 get_oneofs(msg_name.clone(), &doo.attributes)
1073 }).collect::<Vec<Vec<_>>>().concat();
1074
1075 let all_oos = vec![direct_oos, inner_oos].concat();
1076 if all_oos.len() == 0 { None }
1077 else { Some(all_oos) }
1078 }
1079 let oo_enums: Vec<_> = msgs.iter().filter_map(|msg| {
1080 get_oneofs(msg.name.clone(), &msg.attributes)
1081 }).collect::<Vec<_>>().concat();
1082
1083 { let msg_names = msgs.iter().map(|msg| &msg.name).collect::<Vec<_>>();
1087 msg_names.iter().for_each(|name| {
1088 if msg_names.iter().filter(|cname| **cname == *name).count() > 1 {
1090 println!("Error: Multiple instances of msg '{}' found.", name);
1091 abort()
1092 }
1093 });
1094 let enum_names = enums.iter().map(|enm| &enm.name).collect::<Vec<_>>();
1095 enum_names.iter().for_each(|name| {
1096 if enum_names.iter().filter(|cname| **cname == *name).count() > 1 {
1097 println!("Error: Multiple instances of enum '{}' found.", name); abort()
1098 }
1099 });
1100
1101 let enums_and_msg_names = [&msg_names[..], &enum_names[..]].concat();
1102
1103 msgs.iter().for_each(|msg| {
1105 for attr in msg.attributes.clone() {
1106 match attr.specific_details {
1107 AttributeDetails::AttributeEnumOrMsg(enum_or_msg) => {
1108 let em_found = enums_and_msg_names.contains(&&enum_or_msg);
1109 if !em_found {
1110 println!("!!! Error: Attribute '{}' type '{}' in message '{}' not defined.", attr.name, enum_or_msg, msg.name);
1111 panic!("->Exiting");
1112 }
1113 },
1114 _ => {}
1115 }
1116 }
1117 });
1118 }
1119
1120 {
1121 println!("FixedPoint summary:");
1122 msgs.iter().for_each(|msg| {
1123 for attr in msg.attributes.clone() {
1124 match attr.specific_details {
1125 AttributeDetails::AttributeSimple(asi) => match asi {
1126 SimpleType::FixedPrecision(fpp) => {
1127 let values_number = 1_u64 << fpp.bits;
1128 let prec = (fpp.max_val - fpp.min_val) as f64 / values_number as f64;
1129 println!("{}::{} => [{} : {}] precision: {}", msg.name, attr.name,
1130 fpp.min_val, fpp.max_val, prec);
1131 }
1132 _ => {}
1133 },
1134 _ => {}
1135 }
1136 }
1137 });
1138 }
1139
1140 BitisProcessed { max_version_number: 0, msgs, enums, oo_enums}
1141}
1142
1143pub fn dependencies_process(jd: JinjaData) -> Vec<String>{
1144 let mut dependencies = HashMap::new();
1145
1146 for msgs in jd.msgs.clone() {
1147 dependencies.insert(
1148 msgs.name.clone(), Dependencies{in_deps: vec![], out_deps: vec![]});
1149 }
1150 for enm in jd.enums {
1151 dependencies.insert(
1152 enm.name.clone(), Dependencies{in_deps: vec![], out_deps: vec![]});
1153 }
1154 for (_, oos) in jd.oos.clone() {
1155 dependencies.insert(
1156 oos.name.clone(), Dependencies{in_deps: vec![], out_deps: vec![]});
1157 }
1158
1159 println!("{:?}", dependencies);
1160
1161 if dependencies.len() == 0 {
1162 println!("No dependencies found, skipping message and type analysis!");
1163 return Vec::new();
1164 }
1165
1166 for msgs in jd.msgs {
1168 for attr in msgs.attributes {
1169 if attr.is_enum || attr.is_msg || attr.is_oo {
1170 println!("attr '{}' -> attr.rust_type_str: {}", attr.base.name, attr.rust_type_str);
1171 println!("{:?}", attr);
1172 dependencies.get_mut(&attr.rust_type_str).unwrap().out_deps.push(msgs.name.clone());
1173 dependencies.get_mut(&msgs.name).unwrap().in_deps.push(attr.rust_type_str.clone());
1174 }
1175 }
1176 }
1177 for (_, msgs) in jd.oos {
1178 for attr in msgs.attributes {
1179 if attr.is_enum || attr.is_msg || attr.is_oo {
1180 dependencies.get_mut(&attr.rust_type_str).unwrap().out_deps.push(msgs.name.clone());
1181 dependencies.get_mut(&msgs.name).unwrap().in_deps.push(attr.rust_type_str.clone());
1182 }
1183 }
1184 }
1185 println!("{:#?}", dependencies.clone());
1186
1187 let mut object_order = Vec::new();
1188 while dependencies.len() > 0 {
1189 let mut cobjs: Vec<_> = dependencies.clone().iter().filter_map(|(obj_name, deps)| {
1190 if deps.in_deps.len() == 0 { Some(obj_name.clone()) }
1191 else { None }
1192 }).collect();
1193
1194 for co in cobjs.clone() {
1195 dependencies.remove(&co);
1196 }
1197 for co in cobjs.clone() {
1198 for (_, deps) in &mut dependencies {
1199 deps.in_deps.retain(|x| *x != co);
1200 }
1201 }
1202 object_order.append(&mut cobjs);
1203 }
1204 println!("{:?}", object_order);
1205
1206 object_order
1207}
1208#[cfg(test)]
1211mod bitis_semantic {
1212 use rstest::rstest;
1213 use super::*;
1214
1215 #[rstest]
1216 fn msg_empty_msg() {
1217 let test_empty_msg = "msg Lala { }";
1218
1219 let mut lexer = Token::lexer(test_empty_msg);
1220 lexer.extras = 0;
1221
1222 let parsed_bitis = parse_root(&mut lexer);
1223 if let Err(s) = parsed_bitis.clone() {
1224 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1225 }
1226 assert_eq!(parsed_bitis.is_ok(), true);
1227
1228 let parsed_bitis = parsed_bitis.unwrap();
1229 assert_eq!(parsed_bitis.len(), 1);
1230
1231 assert!(if let Value::Message(_) = parsed_bitis[0].clone() { true } else { false });
1232
1233 if let Value::Message(msg) = parsed_bitis[0].clone() {
1234 assert_eq!(msg.name, "Lala".to_string());
1235 }
1236
1237 let process_result = process_and_validate_bitis(&parsed_bitis);
1241 println!("process_result {:?}", process_result);
1242
1243 assert_eq!(process_result.msgs.len(), 1);
1244 assert_eq!(process_result.enums.len(), 0);
1245 }
1246
1247 #[rstest]
1248 fn msg_simple_msg() {
1249 let test_empty_msg = "msg Lala { uint_7 a1; }";
1250
1251 let mut lexer = Token::lexer(test_empty_msg);
1252 lexer.extras = 0;
1253
1254 let parsed_bitis = parse_root(&mut lexer);
1255 if let Err(s) = parsed_bitis.clone() {
1256 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1257 }
1258 assert_eq!(parsed_bitis.is_ok(), true);
1259
1260 let parsed_bitis = parsed_bitis.unwrap();
1261 assert_eq!(parsed_bitis.len(), 1);
1262
1263 if let Value::Message(msg) = parsed_bitis[0].clone() {
1264 assert_eq!(msg.attributes.len(), 1);
1265 assert_eq!(msg.attributes[0].name, "a1".to_string());
1266 if let AttributeDetails::AttributeSimple(s) = msg.attributes[0].specific_details.clone() {
1267 assert_eq!(s, SimpleType::UIntFixed(7));
1268 }
1269 else { assert!(false, "Attribute type must be AttributeSimple."); }
1270 }
1271 else { assert!(false, "Value must be a message."); }
1272 }
1273
1274 #[rstest]
1275 fn msg_simple_enum() {
1276 let test_empty_msg = "enum Lala(4) { *one, two }";
1277
1278 let mut lexer = Token::lexer(test_empty_msg);
1279 lexer.extras = 0;
1280
1281 let parsed_bitis = parse_root(&mut lexer);
1282 if let Err(s) = parsed_bitis.clone() {
1283 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1284 }
1285 assert_eq!(parsed_bitis.is_ok(), true);
1286
1287 let parsed_bitis = parsed_bitis.unwrap();
1288 assert_eq!(parsed_bitis.len(), 1);
1289
1290 if let Value::Enum(enm) = parsed_bitis[0].clone() {
1291 assert_eq!(enm.values.len(), 2);
1292 assert_eq!(enm.values[0], "one".to_string());
1293 assert_eq!(enm.values[1], "two".to_string());
1294 }
1295 else { assert!(false, "Value must be a message."); }
1296 }
1297
1298
1299 }
1336
1337#[cfg(test)]
1338mod bitis_generate_rust {
1339 use rstest::rstest;
1340 use super::*;
1341
1342 const HEADER: &str = "use bitis_lib::*;\n\n";
1343 const ENUMS_HEADER: &str = "// Enums\n";
1344 const OO_HEADER: &str = "// Enums for oneof\n";
1345 const MSG_HEADER: &str = "// Messages\n";
1346 const PER_ENUM_HEADER: &str = "#[derive(BiserdiEnum, Debug, Clone, PartialEq)]\n#[biserdi_enum_id_dynbits(3)]\n#[allow(nonstandard_style)]\n";
1347 const PER_OO_HEADER: &str = "#[derive(BiserdiOneOf, Debug, Clone, PartialEq)]\n#[biserdi_enum_id_dynbits(3)]\n#[allow(nonstandard_style)]\n";
1348 const PER_MSG_HEADER: &str = "#[derive(BiserdiMsg, Debug, Clone, PartialEq)]\n#[allow(nonstandard_style)]\n";
1349
1350 #[rstest]
1351 #[ignore]
1352 fn msg_empty_msg() {
1353 let test_empty_msg = "msg Lala { }";
1354
1355 let mut lexer = Token::lexer(test_empty_msg);
1356 lexer.extras = 0;
1357
1358 let parsed_bitis = parse_root(&mut lexer);
1359 if let Err(s) = parsed_bitis.clone() {
1360 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1361 }
1362 assert_eq!(parsed_bitis.is_ok(), true);
1363
1364 let parsed_bitis = parsed_bitis.unwrap();
1365 assert_eq!(parsed_bitis.len(), 1);
1366
1367 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1368 let rdo = RustDataObjects{ d: JinjaData{
1369 enums: processed_bitis.enums,
1370 msgs: to_rust_messages(&processed_bitis.msgs),
1371 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1372
1373 let rendered = rdo.render().unwrap();
1374 let lala_empty = "pub struct Lala {\n}\n";
1375 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + "\n\n" +
1376 MSG_HEADER + PER_MSG_HEADER +lala_empty).to_string());
1377 }
1378
1379 #[rstest]
1380 #[ignore]
1381 fn msg_simple_msg() {
1382 let test_empty_msg = "//| comment for Lala\nmsg Lala { int_5 a1; repeated_fixed_4 bool bool_array; }";
1383 println!("Input code:\n{}", test_empty_msg);
1384
1385 let mut lexer = Token::lexer(test_empty_msg);
1386 lexer.extras = 0;
1387
1388 let parsed_bitis = parse_root(&mut lexer);
1389 if let Err(s) = parsed_bitis.clone() {
1390 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1391 }
1392 assert_eq!(parsed_bitis.is_ok(), true);
1393
1394 let parsed_bitis = parsed_bitis.unwrap();
1395 assert_eq!(parsed_bitis.len(), 1);
1396
1397 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1398 let rdo = RustDataObjects{ d: JinjaData{
1399 enums: processed_bitis.enums, msgs: to_rust_messages(&processed_bitis.msgs),
1400 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1401
1402 let rendered = rdo.render().unwrap();
1403 let lala_commment = "/// comment for Lala\n";
1404 let lala_empty = "pub struct Lala {\n pub a1: IntWithGivenBitSize<i8, 5>,\n pub bool_array: FixedArray<bool,4>,\n}\n";
1405 println!("rendered:\n{}",rendered);
1406 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + "\n\n" +
1407 MSG_HEADER + lala_commment + PER_MSG_HEADER +lala_empty).to_string());
1408 }
1409
1410 #[rstest]
1411 #[ignore]
1412 fn msg_simple_enum() {
1413 let test_enum_msg = "//| comment for Numbers\nenum Numbers(3) {\n // Comment for One\n One,\n Two,\n Three\n}";
1414 println!("Input code:\n{}", test_enum_msg);
1415
1416 let mut lexer = Token::lexer(test_enum_msg);
1417 lexer.extras = 0;
1418
1419 let parsed_bitis = parse_root(&mut lexer);
1420 if let Err(s) = parsed_bitis.clone() {
1421 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_enum_msg[s.1.clone()], s.1);
1422 }
1423 assert_eq!(parsed_bitis.is_ok(), true);
1424
1425 let parsed_bitis = parsed_bitis.unwrap();
1426 assert_eq!(parsed_bitis.len(), 1);
1427
1428 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1429 let rdo = RustDataObjects{ d: JinjaData{ enums: processed_bitis.enums,
1430 msgs: to_rust_messages(&processed_bitis.msgs),
1431 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1432
1433 let rendered = rdo.render().unwrap();
1434 let lala_commment = "/// comment for Numbers\n";
1435 let lala_enum = "pub enum Numbers {\n One,\n Two,\n Three,\n}\n\n";
1436 println!("*rendered:\n{}",rendered);
1437 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + lala_commment + PER_ENUM_HEADER + lala_enum + OO_HEADER +
1438 "\n\n" + MSG_HEADER ).to_string());
1439 }
1440
1441 #[rstest]
1442 #[ignore]
1443 fn msg_simple_oneof() {
1444 let test_enum_msg = "//| comment for Oneof\nmsg TestOO {\n oneof oo_li(3) { uint_3 test1; float test2; }\n bool b1;\n}";
1445 println!("Input code:\n{}", test_enum_msg);
1446
1447 let mut lexer = Token::lexer(test_enum_msg);
1448 lexer.extras = 0;
1449
1450 let parsed_bitis = parse_root(&mut lexer);
1451 if let Err(s) = parsed_bitis.clone() {
1452 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_enum_msg[s.1.clone()], s.1);
1453 }
1454 assert_eq!(parsed_bitis.is_ok(), true);
1455
1456 let parsed_bitis = parsed_bitis.unwrap();
1457 assert_eq!(parsed_bitis.len(), 1);
1458
1459 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1460 let rdo = RustDataObjects{ d: JinjaData{ enums: processed_bitis.enums,
1461 msgs: to_rust_messages(&processed_bitis.msgs),
1462 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1463
1464 let rendered = rdo.render().unwrap();
1465 let testoo_commment = "/// comment for Oneof\n";
1466 let testoo_enum = "pub enum OO_TestOo_OoLi {\n Test1(IntWithGivenBitSize<u8, 3>),\n Test2(f32),\n}\n\n";
1467 let testoo_msg = "pub struct TestOo {\n pub oo_li: OO_TestOo_OoLi,\n pub b1: bool,\n}\n";
1468 println!("*rendered:\n{}",rendered);
1469 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + PER_OO_HEADER
1470 + testoo_enum + MSG_HEADER + testoo_commment + PER_MSG_HEADER + testoo_msg).to_string());
1471 }
1472}
1473
1474#[cfg(test)]
1475mod bitis_compile {
1476 use std::fs;
1477 use std::path::Path;
1478 use rstest::rstest;
1479 use super::*;
1480
1481 fn compile(content: &str) -> BitisProcessed {
1482 let mut lexer = Token::lexer(content);
1483 lexer.extras = 0;
1484 println!("*** content:\n{}", content);
1485 let bitis_parsed = match parse_root(&mut lexer) {
1486 Ok(v) => v,
1487 Err(e) => {
1488 let (err_str, err_span) = e.clone();
1489 let content_err = &content[err_span];
1490 println!("Error: {}\n -> Source: '{}'", err_str, content_err);
1491 abort()
1492 }
1493 };
1494 println!("** content:\n{:?}", bitis_parsed);
1495 process_and_validate_bitis(&bitis_parsed)
1496 }
1497 fn render(d: JinjaData) {
1498 let rdo = RustDataObjects{ d: d.clone() };
1499 let rendered_rust = rdo.render().unwrap();
1500 println!("*** rendered DO:\n{}", rendered_rust);
1501 fs::write(Path::new("./test_data/test_py/bitis/src/messages_test.rs"), rendered_rust).expect("Unable to write file");
1502
1503 let rdo = RustPyDataObjects{ d: d.clone() };
1504 let rendered_rust = rdo.render().unwrap();
1505 println!("*** rendered PyDO:\n{}", rendered_rust);
1506 fs::write(Path::new("./test_data/test_py/bitis/src/pyrust_test.rs"), rendered_rust).expect("Unable to write file");
1507
1508 let rdo = RustPyLib{ d: d.clone(), lib_name: "bitis_msgs".into() };
1509 let rendered_rust = rdo.render().unwrap();
1510 println!("*** rendered pyLib:\n{}", rendered_rust);
1511 fs::write(Path::new("./test_data/test_py/bitis/src/lib_test.rs"), rendered_rust).expect("Unable to write file");
1512
1513 let rdo = PyTypeHints{ d };
1514 let rendered_rust = rdo.render().unwrap();
1515 println!("*** rendered py_type_hints:\n{}", rendered_rust);
1516 fs::write(Path::new("./test_data/test_py/bitis/bitis_msgs/bitis_msgs.pyi"), rendered_rust).expect("Unable to write file");
1517 }
1518
1519 #[rstest]
1520 #[ignore]
1521 fn simple_rust_py() {
1522 let bitis_str = "msg ParamTestSimple { uint_4 param_1; bool param_2; }";
1523
1524 let bitis_processed_org = compile(bitis_str);
1525
1526 let bitis_processed = bitis_processed_org.clone();
1527 let d = JinjaData{
1528 enums: bitis_processed.enums,
1529 msgs: to_rust_messages(&bitis_processed.msgs),
1530 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1531 };
1532 render(d);
1533 }
1534
1535 #[rstest]
1536 #[ignore]
1537 fn nested_rust_py() {
1538 let bitis_str = "msg Inner { uint_2 val; }\nmsg ParamTestWithInner { uint_4 param_1; bool param_2; Inner inner; }";
1539
1540 let bitis_processed_org = compile(bitis_str);
1541
1542 let bitis_processed = bitis_processed_org.clone();
1543
1544 let d = JinjaData{
1545 enums: bitis_processed.enums,
1546 msgs: to_rust_messages(&bitis_processed.msgs),
1547 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1548 };
1549 render(d);
1550 }
1551 #[test]
1552 #[ignore]
1553 fn nested_and_enum_rust_py() {
1554 let bitis_str = [
1555 "enum Numbers(4) { one, two, three, four }\n/// Test comment for Inner\nmsg Inner { uint_3 val; Numbers num; }\n",
1556 "msg ParamTestWithInner { uint_4 param_1; bool param_2; Inner inner; } }"
1557 ].join("");
1558
1559 let bitis_processed_org = compile(bitis_str.as_str());
1560
1561 let bitis_processed = bitis_processed_org.clone();
1562
1563 let d = JinjaData{
1564 enums: bitis_processed.enums,
1565 msgs: to_rust_messages(&bitis_processed.msgs),
1566 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1567 };
1568 render(d);
1569 }
1570 #[rstest]
1571 #[ignore]
1572 fn oneof_nested_and_enum_rust_py() {
1573 let bitis_str = [
1574 "//| 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",
1575 "msg ParamTestWithInner { uint_4 param_1; bool param_2; oneof action(4) { Inner inner; uint_3 val; } }"
1576 ].join("");
1577
1578 let bitis_processed_org = compile(bitis_str.as_str());
1579
1580 let bitis_processed = bitis_processed_org.clone();
1581
1582 let d = JinjaData{
1583 enums: bitis_processed.enums,
1584 msgs: to_rust_messages(&bitis_processed.msgs),
1585 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1586 };
1587 render(d);
1588 }
1589}
1590
1591#[cfg(test)]
1592mod bitis_serialization {
1593 use rstest::rstest;
1595 use super::*;
1596
1597 #[rstest]
1599 fn msg_simple_msg_compile() {
1600 let test_empty_msg = "msg Lala { repeated_fixed_10 bool data_bool; uint_4 data1_uint; uint_12 data2_uint; }";
1601
1602 let mut lexer = Token::lexer(test_empty_msg);
1603 lexer.extras = 0;
1604
1605 let parsed_bitis = parse_root(&mut lexer);
1606 assert_eq!(parsed_bitis.is_ok(), true);
1607
1608 let _parsed_bitis = parsed_bitis.unwrap();
1609
1610 }
1635}
1636
1637#[cfg(test)]
1638mod bitis_processing {
1639 use rstest::rstest;
1640 use crate::AttributeDetails::{AttributeEnumOrMsg, AttributeSimple};
1641 use super::*;
1642
1643 #[rstest]
1644 #[ignore]
1645 fn msg_base_and_v2() {
1646 let bitis_values = vec![
1647 Value::Message(Message{
1648 name: "TestMsg".to_string(),
1649 comment: Some("This is a test".to_string()),
1651 parent: None,
1652 attributes: vec![Attribute{name: "a1".to_string(), comment: None,
1653 is_repeated_and_size: None, is_optional: false,
1654 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1655 }],
1656 }),
1657 Value::Message(Message{
1658 name: "TestMsg".to_string(),
1659 comment: Some("This is a test".to_string()),
1661 parent: None,
1662 attributes: vec![Attribute{name: "a2".to_string(), comment: None,
1663 is_repeated_and_size: None, is_optional: false,
1664 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1665 }],
1666 })
1667 ];
1668 let pb = process_and_validate_bitis(&bitis_values);
1669
1670 assert_eq!(pb.max_version_number, 2);
1671 assert_eq!(pb.msgs.len(), 3);
1672
1673 assert_eq!(pb.msgs[0].name, "TestMsg_Base".to_string());
1674 assert_eq!(pb.msgs[1].name, "TestMsg_V1".to_string());
1675 assert_eq!(pb.msgs[2].name, "TestMsg_V2".to_string());
1676
1677 assert_eq!(pb.msgs[0].attributes.len(), 1);
1678 assert_eq!(pb.msgs[0].attributes.get(0).unwrap().name, "a1".to_string());
1679 assert_eq!(pb.msgs[1].attributes.len(), 0);
1680 assert_eq!(pb.msgs[2].attributes.len(), 1);
1681 assert_eq!(pb.msgs[2].attributes.get(0).unwrap().name, "a2".to_string());
1682 }
1683
1684 #[rstest]
1685 #[ignore]
1686 fn msg_base_and_v2_and_add_msg() {
1687 let bitis_values = vec![
1688 Value::Message(Message{
1689 name: "TestMsgInner".to_string(),
1690 comment: Some("This is a test2".to_string()),
1692 parent: None,
1693 attributes: vec![Attribute{name: "lala".to_string(), comment: None,
1694 is_repeated_and_size: None, is_optional: false,
1695 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1696 }],
1697 }),
1698 Value::Message(Message{
1699 name: "TestMsgInner".to_string(),
1700 comment: Some("This is a test2".to_string()),
1702 parent: None,
1703 attributes: vec![
1704 Attribute{name: "lala".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1705 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),},
1706 Attribute{name: "lala2".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1707 specific_details: AttributeSimple(SimpleType::UIntFixed(3)),},
1708 ],
1709 }),
1710 Value::Message(Message{
1711 name: "TestMsg".to_string(),
1712 comment: Some("This is a test".to_string()),
1714 parent: None,
1715 attributes: vec![
1716 Attribute{ name: "a1".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1717 specific_details: AttributeSimple(SimpleType::UIntFixed(4)) },
1718 Attribute{ name: "lala_use".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1719 specific_details: AttributeEnumOrMsg("TestMsgInner".to_string()) },
1720 ],
1721 }),
1722 Value::Message(Message{
1723 name: "TestMsg".to_string(),
1724 comment: Some("This isa test".to_string()),
1726 parent: None,
1727 attributes: vec![Attribute{name: "a2".to_string(), comment: None,
1728 is_repeated_and_size: None, is_optional: false,
1729 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1730 }],
1731 }),
1732 ];
1733 let pb = process_and_validate_bitis(&bitis_values);
1734
1735 assert_eq!(pb.max_version_number, 2);
1736 assert_eq!(pb.msgs.len(), 4);
1737
1738}
1753}
1754