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