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}
45fn to_rust_attribute(attribute: &Attribute, msg_names: &Vec<String>) -> AttributeEx {
46 let (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val) = {
47 let mut is_py_wrapped = false;
48 let mut is_enum = false;
49 let mut is_msg = false;
50 let mut is_oo = false;
51 let mut add_val = false;
52
53 let (rtype, base_type) = match &attribute.specific_details {
54 AttributeDetails::AttributeSimple(a) => {
55 match a {
56 SimpleType::NoTypeSetYet => {
57 println!("Unexpected unspecified attribute type");
58 abort()
59 },
60 SimpleType::Bool => { ("bool".to_string(), "bool".to_string()) }
61 SimpleType::UIntFixed(b) => {
62 add_val = true;
63 let base = format!("u{}", integer_bit_size(&b));
64 (format!("VarWithGivenBitSize<{}, {}>", base.clone(), b), base) }
65 SimpleType::IntFixed(b) => {
66 add_val = true;
67 let base = format!("i{}", integer_bit_size(&b));
68 (format!("VarWithGivenBitSize<{}, {}>", base.clone(), b), base) }
69 SimpleType::UIntDyn(b) => {
70 add_val = true;
71 let base = format!("u{}", integer_bit_size(&b.0));
72 (format!("DynInteger<{}, {}>", base.clone(), b.1), base) }
73 SimpleType::IntDyn(b) => {
74 add_val = true;
75 let base = format!("i{}", integer_bit_size(&b.0));
76 (format!("DynInteger<{}, {}>", base.clone(), b.1), base) }
77 SimpleType::Float => {
78 add_val = true;
79 let base = "f32".to_string();
80 (base.clone(), base)
81 }
82 SimpleType::Double => {
83 let base = "f64".to_string();
84 (base.clone(), base) }
85 SimpleType::FixedPrecision(fpp) => {
86 add_val = true;
87 (format!("FixPrecisionMinMax<{}, {}, {}>", fpp.bits, fpp.min_val, fpp.max_val), "f64".to_string())
88 }
89 SimpleType::Binary(b) => {
90 add_val = true;
91 (format!("Binary<{}>", b), "Vec<u8>".to_string()) }
92 }
93 }
94 AttributeDetails::AttributeEnumOrMsg(em) => {
95 is_py_wrapped = true;
96 is_msg = msg_names.contains(&em);
97 is_enum = !is_msg.clone();
98 (em.clone(), em.clone()) }
99 AttributeDetails::AttributeOneOf(ooi) => {
100 is_py_wrapped=true; is_oo = true;
101 (ooi.name.clone(), ooi.name.clone()) }
102 };
103 (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val)
104 };
105 AttributeEx{base: attribute.clone(), rust_type_str: rtype, base_type_str: base_type,
106 is_py_wrapped, is_msg, is_enum, is_oo, add_val }
107}
108
109pub fn to_rust_messages(msgs: &Vec<Message>) -> Vec<MessageR> {
110 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
111
112 msgs.iter().map(|msg| {
113 let attrs_rust: Vec<_> = msg.attributes.iter().map(|attribute| {
114 to_rust_attribute(attribute, &msgs_names) }).collect();
115 MessageR{name: msg.name.clone(), comment: msg.comment.clone(), parent: msg.parent.clone(),
116 attributes: attrs_rust}
117 }).collect()
118}
119pub fn to_rust_oneofs(oos: &Vec<(String, OneOfInfo)>, msgs: &Vec<Message>) -> HashMap<String, OneOfInfoR> {
120 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
121
122 oos.iter().map(|(msg_name, oo)| {
123 let attrs_rust: Vec<_> = oo.attributes.iter().map(|attribute| {
124 to_rust_attribute(attribute, &msgs_names) }).collect();
125 (oo.name.clone(), OneOfInfoR{msg_name: msg_name.clone(), name: oo.name.clone(), dyn_bits: oo.dyn_bits, attributes: attrs_rust})
126 }).collect()
127}
128
129fn to_cpp_attribute(attribute: &Attribute, msg_names: &Vec<String>) -> AttributeEx {
130 let (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val) = {
131 let mut is_py_wrapped = false;
132 let mut is_enum = false;
133 let mut is_msg = false;
134 let mut is_oo = false;
135 let mut add_val = false;
136
137 let (rtype, base_type) = match &attribute.specific_details {
138 AttributeDetails::AttributeSimple(a) => {
139 match a {
140 SimpleType::NoTypeSetYet => {
141 println!("Unexpected unspecified attribute type");
142 abort()
143 },
144 SimpleType::Bool => { ("BitisBool".to_string(), "bool".to_string()) }
145 SimpleType::UIntFixed(b) => {
146 add_val = true;
147 let base = format!("uint{}_t", integer_bit_size(&b));
148 (format!("IntgralWithGivenBitSize<{}, {}>", base.clone(), b), base) }
149 SimpleType::IntFixed(b) => {
150 add_val = true;
151 let base = format!("int{}_t", integer_bit_size(&b));
152 (format!("IntgralWithGivenBitSize<{}, {}>", base.clone(), b), base) }
153 SimpleType::UIntDyn(b) => {
154 add_val = true;
155 let base = format!("uint{}_t", integer_bit_size(&b.0));
156 (format!("DynInteger<{}, {}>", base.clone(), b.1), base) }
157 SimpleType::IntDyn(b) => {
158 add_val = true;
159 let base = format!("int{}_t", integer_bit_size(&b.0));
160 (format!("DynInteger<{}, {}>", base.clone(), b.1), base) }
161 SimpleType::Float => {
162 add_val = true;
163 let base = "float".to_string();
164 (base.clone(), base)
165 }
166 SimpleType::Double => {
167 let base = "double".to_string();
168 (base.clone(), base) }
169 SimpleType::FixedPrecision(fpp) => {
170 add_val = true;
171 (format!("FixPrecisionMinMax<{}, {}, {}>", fpp.bits, fpp.min_val, fpp.max_val), "double".to_string())
172 }
173 SimpleType::Binary(b) => {
174 add_val = true;
175 (format!("Binary<{}>", b), "Vec<u8>".to_string()) }
176 }
177 }
178 AttributeDetails::AttributeEnumOrMsg(em) => {
179 is_py_wrapped = true;
180 is_msg = msg_names.contains(&em);
181 is_enum = !is_msg.clone();
182 (em.clone(), em.clone()) }
183 AttributeDetails::AttributeOneOf(ooi) => {
184 is_py_wrapped=true; is_oo = true;
185 (ooi.name.clone(), ooi.name.clone()) }
186 };
187 (rtype, base_type, is_py_wrapped, is_msg, is_enum, is_oo, add_val)
188 };
189 AttributeEx{base: attribute.clone(), rust_type_str: rtype, base_type_str: base_type,
190 is_py_wrapped, is_msg, is_enum, is_oo, add_val }
191}
192pub fn to_cpp_messages(msgs: &Vec<Message>) -> Vec<MessageR> {
193 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
194
195 msgs.iter().map(|msg| {
196 let attrs_rust: Vec<_> = msg.attributes.iter().map(|attribute| {
197 to_cpp_attribute(attribute, &msgs_names) }).collect();
198 MessageR{name: msg.name.clone(), comment: msg.comment.clone(), parent: msg.parent.clone(),
199 attributes: attrs_rust}
200 }).collect()
201}
202pub fn to_cpp_oneofs(oos: &Vec<(String, OneOfInfo)>, msgs: &Vec<Message>) -> HashMap<String, OneOfInfoR> {
203 let msgs_names: Vec<_> = msgs.iter().map(|m| {m.name.clone()}).collect();
204
205 oos.iter().map(|(msg_name, oo)| {
206 let attrs_cpp: Vec<_> = oo.attributes.iter().map(|attribute| {
207 to_cpp_attribute(attribute, &msgs_names) }).collect();
208 (oo.name.clone(), OneOfInfoR{msg_name: msg_name.clone(), name: oo.name.clone(), dyn_bits: oo.dyn_bits, attributes: attrs_cpp })
209 }).collect()
210}
211
212#[derive(Clone, Debug)]
213pub struct JinjaData {
214 pub enums: Vec<Enum>,
215 pub msgs: Vec<MessageR>,
216 pub oos: HashMap<String, OneOfInfoR>,
217}
218
219#[derive(Template, Clone, Debug)]
220#[template(path = "data_objects.rs.jinja")]
221pub struct RustDataObjects {
222 pub d: JinjaData
223}
224#[derive(Template, Clone, Debug)]
225#[template(path = "pyclasses.py.rs.jinja")]
226pub struct RustPyDataObjects {
227 pub d: JinjaData
228}
229#[derive(Template, Clone, Debug)]
230#[template(path = "pylib.py.rs.jinja")]
231pub struct RustPyLib {
232 pub d: JinjaData,
233 pub lib_name: String
234}
235#[derive(Template, Clone, Debug)]
236#[template(path = "py_type_hints.pyi.jinja")]
237pub struct PyTypeHints {
238 pub d: JinjaData
239}
240#[derive(Template, Clone, Debug)]
241#[template(path = "data_objects.cpp.jinja")]
242pub struct CppDataObjects {
243 pub d: JinjaData,
244 pub object_order: Vec<String>,
245}
246
247
248mod filters {
249 #[allow(dead_code)]
250 pub fn snake_case<T: std::fmt::Display>(s: T, _: &dyn askama::Values) -> ::askama::Result<String> {
251 Ok(stringcase::snake_case(s.to_string().as_str()))
252 }
253 #[allow(dead_code)]
254 pub fn camel_case<T: std::fmt::Display>(s: T, _: &dyn askama::Values,) -> ::askama::Result<String> {
255 Ok(stringcase::camel_case(s.to_string().as_str()))
256 }
257 #[allow(dead_code)]
258 pub fn pascal_case<T: std::fmt::Display>(s: T, _: &dyn askama::Values,) -> ::askama::Result<String> {
259 Ok(stringcase::pascal_case(s.to_string().as_str()))
260 }
261 #[allow(dead_code)]
262 pub fn to_py_type<T: std::fmt::Display>(s: T, _: &dyn askama::Values,) -> ::askama::Result<String> {
263 if ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64"].contains(&s.to_string().as_str()) {
264 Ok("int".to_string()) }
265 else if ["f32", "f64"].contains(&s.to_string().as_str()) {
266 Ok("float".to_string())
267 }
268 else { Ok(s.to_string()) }
269 }
270}
271
272type Error = (String, Span);
274
275type Result<T> = std::result::Result<T, Error>;
276
277#[derive(Debug, Clone)]
278pub enum DynOrFixedType {
279 Dyn(u8),
280 Fixed(u8)
281}
282#[derive(Debug, PartialEq, Eq, Clone, Copy)]
283pub struct FixedPrecisionProperties {
284 bits: u8, min_val: i64, max_val: i64
285}
286#[derive(Debug, PartialEq, Eq, Clone, Copy)]
287pub enum SimpleType {
288 NoTypeSetYet,
289 Bool,
290 UIntFixed(u8), IntFixed(u8),
291 UIntDyn((u8,u8)), IntDyn((u8,u8)),
292 Float, Double,
293 FixedPrecision(FixedPrecisionProperties),
294 Binary(u8),
295}
296#[derive(Debug, Clone )]
328pub struct OneOfInfo {
329 name: String,
330 dyn_bits: u8,
331 attributes: Vec<Attribute>,
332}
333#[derive(Debug, Clone )]
334pub enum AttributeDetails {
335 AttributeSimple(SimpleType),
336 AttributeEnumOrMsg(String),
337 AttributeOneOf(OneOfInfo),
338}
339#[derive(Debug, Clone )]
340pub struct Attribute {
341 name: String,
342 comment: Option<String>,
343 is_repeated_and_size: Option<DynOrFixedType>,
344 is_optional: bool,
345 specific_details: AttributeDetails
346}
347#[derive(Debug, Clone)]
353pub struct Message {
354 pub name: String,
355 pub comment: Option<String>,
357 pub parent: Option<String>,
358 pub attributes: Vec<Attribute>,
359}
360
361#[derive(Debug, Clone)]
363pub struct Enum {
364 pub name: String,
365 pub comment: Option<String>,
367 pub bit_size: u8,
368 pub values: Vec<String>,
369 pub default: String
370}
371
372pub fn get_suffix_number(lex: &mut Lexer<Token>) -> Option<u8> {
373 let slice = lex.slice();
374 let re = Regex::new(r".*_d?([0-9]+)$").unwrap();
375 let num_str = re.captures(slice)?.get(1)?;
376 num_str.as_str().parse().ok()
377}
378pub fn get_d_suffix_numbers(lex: &mut Lexer<Token>) -> Option<(u8,u8)> {
379 let slice = lex.slice();
380 let re = Regex::new(r".*_([0-9]+)d([0-9]+)$").unwrap();
381 let first_num_str = re.captures(slice)?.get(1)?.as_str().parse().ok()?;
382 let second_num_str = re.captures(slice)?.get(2)?.as_str().parse().ok()?;
383 Some((first_num_str, second_num_str))
384}
385pub fn get_fp_properties_number(lex: &mut Lexer<Token>) -> Option<FixedPrecisionProperties> {
386 let slice = lex.slice();
387 let re = Regex::new(r"fp_([0-9]+)\[ *(-?[0-9]+) *, *(-?[0-9]+) *]").unwrap();
388 let bits = re.captures(slice)?.get(1)?.as_str().parse::<u8>().ok()?;
389 let min_val = re.captures(slice)?.get(2)?.as_str().parse::<i64>().ok()?;
390 let max_val = re.captures(slice)?.get(3)?.as_str().parse::<i64>().ok()?;
391 Some(FixedPrecisionProperties {bits, min_val, max_val})
392}
393pub fn get_enum_bit_size(lex: &mut Lexer<Token>) -> Option<u8> {
406 let slice = lex.slice();
407 let re = Regex::new(r"\( *([0-9]+) *\)").unwrap();
408 let bits = re.captures(slice)?.get(1)?.as_str().parse::<u8>().ok()?;
409 Some(bits)
410}
411pub fn get_version(lex: &mut Lexer<Token>) -> Option<u16> {
412 let slice = lex.slice();
413 let re = Regex::new(r"\[.* +(v[0-9]+) *]").unwrap();
414 let ver_str = re.captures(slice)?.get(1)?.as_str();
415 Some(ver_str.parse::<u16>().ok()?)
416}
417
418#[derive(Debug, Logos)]
419#[logos(skip r"[ \t\r\n\f]+")]
420#[logos(extras = u16)]
421#[allow(dead_code)]
422pub enum Token{
423 #[regex(r"//[^\n]*\n?", priority=40)] Comment,
424 #[regex(r"//\|[^\n]*\n?", |lex| lex.slice()[3..].to_owned(), priority=41)] SpecificComment(String),
425 #[token("msg", priority=20)] Msg,
426 #[token("enum", priority=20)] Enum,
427 #[token("oneof", priority=20)] OneOf,
428 #[token("{")] CBraceOpen,
429 #[token("}")] CBraceClose,
430 #[token("(")] BraceOpen,
431 #[token(")")] BraceClose,
432 #[token(":")] Colon,
433 #[token(";")] SemiColon,
434 #[token(",")] Comma,
435 #[token("*")] Star,
436 #[regex(r"\[ *base +use +starting +with +v[0-9]+ *\]", get_version, priority=35)] MsgBaseInfoToken(u16),
439 #[regex(r"\[ *version +v[0-9]+ *\]", get_version, priority=35)] MsgVersionToken(u16),
440 #[regex("[0-9]+", |lex| lex.slice().parse::<isize>().unwrap(), priority=1)] IntegerVal(isize),
442 #[regex(r"-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?",
443 |lex| lex.slice().parse::<f64>().unwrap(), priority=2)] Number(f64),
444 #[token("bool", priority=30)] Bool,
445 #[token("msg_size_type", priority=30)] MsgSizeType,
446 #[regex(r"uint_[0-9]+", get_suffix_number, priority=30)] UIntFixed(u8),
447 #[regex(r"int_[0-9]+", get_suffix_number, priority=30)] IntFixed(u8),
448 #[regex(r"uint_[0-9]+d[0-9]+", get_d_suffix_numbers, priority=31)] UIntDyn((u8,u8)),
449 #[regex(r"int_[0-9]+d[0-9]+", get_d_suffix_numbers, priority=31)] IntDyn((u8,u8)),
450 #[token("float", priority=30)] Float,
451 #[token("double", priority=30)] Double,
452 #[regex(r"fp_[0-9]+\[ *-?[0-9]+ *, *-?[0-9]+ *]", get_fp_properties_number, priority=30)] FixedPoint(FixedPrecisionProperties),
453 #[token("binary_d[0-9]+", get_suffix_number, priority=30)] Binary(u8),
456 #[regex(r"repeated_dyn_[0-9]+", get_suffix_number, priority=30)] RepeatedDyn(u8),
457 #[regex(r"repeated_fixed_[0-9]+", get_suffix_number, priority=30)] RepeatedFixed(u8),
458 #[token("optional", priority=30)] Optional,
459 #[regex(r"[A-Za-z][A-Za-z0-9_-]+", |lex| lex.slice().to_owned(), priority=11)] StringVal(String),
460 #[token("false", |_| false, priority=20)]
461 #[token("true", |_| true, priority=20)] BoolVal(bool),
462 #[regex(r"\( *([0-9]+) *\)", get_enum_bit_size, priority=40)] EnumDynSize(u8),
463}
464
465#[derive(Debug, Clone)]
466pub enum Value {
467 Message(Message),
469 Enum(Enum)
471}
472
473macro_rules! parse_one_token {
474 ($token_enum: path, $lexer: expr, $error_msg_or_empty: expr) => {
475 loop {
476 let rv = $lexer.next();
477 if let Some(token) = rv {
478 match token {
479 Ok($token_enum) => {
480 break Ok(Ok(()));
481 },
482 Ok(Token::Comment) => (),
483 _ => {
484 if let Some(err_str) = $error_msg_or_empty {
485 break Err((format!("{err_str}\nToken: {token:?}").to_owned(), $lexer.span()));
486 }
487 else {
488 break Ok(Err($lexer.span()));
489 }
490 }
491 }
492 }
493 else {
494 break Err((format!("Unexpected end or text {rv:?}").to_owned(), $lexer.span()));
495 }
496 }
497 }
498}
499macro_rules! parse_one_token_with_arg {
500 ($token_enum: path, $lexer: expr, $error_msg_or_empty: expr) => {
501 loop {
502 let rv = $lexer.next();
503 if let Some(token) = rv {
504 match token {
505 Ok($token_enum(s)) => {
506 break Ok(Ok(s));
507 },
508 Ok(Token::Comment) => (),
509 _ => {
510 if let Some(err_str) = $error_msg_or_empty {
511 break Err((format!("{}\nFound token: {:?}.",
512 err_str, token).to_owned(), $lexer.span()));
513 }
514 else {
515 break Ok(Err($lexer.span()));
516 }
517 }
518 }
519 }
520 else {
521 break Err((format!("Unexpected end or text {rv:?}").to_owned(), $lexer.span()));
522 }
523 }
524 }
525}
526
527pub fn parse_root(lexer: &mut Lexer<'_, Token>) -> Result<Vec<Value>> {
528 let mut list: Vec<Value> = Vec::new();
529 let mut specific_comment: Option<String> = None;
530 loop {
531 if let Some(token) = lexer.next() {
532 let rv = match token {
533 Ok(Token::Msg) => Some(parse_msg(lexer, specific_comment.clone())),
534 Ok(Token::Enum) => Some(parse_enum(lexer, specific_comment.clone())),
535 Ok(Token::Comment) => None,
536 Ok(Token::SpecificComment(s)) => {
537 specific_comment = Some(s); None },
538 _ => Some(Err((format!("Unexpected token {:?}", token).to_owned(), lexer.span()))),
539 };
540 match rv {
541 None => (),
542 Some(Ok(value)) => { list.push(value); specific_comment = None; },
543 Some(Err(err)) => return Err(err)
544 }
545 }
546 else { break; }
547 }
548 Ok(list)
549}
550
551pub fn parse_msg(lexer: &mut Lexer<'_, Token>, comment_for_msg: Option<String>) -> Result<Value> {
552 let mut attributes = Vec::new();
553
554 let name = match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name but received:"))? {
555 Ok(s) => s,
556 Err(s) => { return Err(("Code should not be reached".into(), s)); }
557 };
558
559 let parent = {
573 let has_parent; let p;
574 if let Some(token) = lexer.next() {
575 match token {
576 Ok(Token::Colon) => has_parent = true,
577 Ok(Token::CBraceOpen) => has_parent = false,
578 _ => { return Err((format!("Unexpected text for msg '{name}'.").into(), lexer.span())) },
579 }
580 if has_parent {
581 match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name."))? {
582 Ok(s) => p = Some(s),
583 Err(s) => { return Err((format!("For msg '{name} colon found but no parent name").into(), s)); }
584 };
585 parse_one_token!(Token::CBraceOpen, lexer, Some(format!("Expected curly bracket open for msg '{name}'")))?.unwrap();
586 }
587 else {
588 p = None
589 }
590 }
591 else { return Err(("Unexpected end of file".into(), lexer.span())); }
592 p
593 };
594
595 loop {
596 if let Some(token) = lexer.next() {
597 match token {
598 Ok(Token::CBraceClose) => break,
599 Ok(Token::Comment) => (),
600 Ok(ctoken) => match parse_attribute(ctoken, lexer, name.clone(), false) {
601 Ok(a) => { attributes.push(a); },
602 Err(e) => { return Err(e); }
603 },
604 _ => { return Err((format!("Error: Unexpected text found for msg '{name}'.").into(), lexer.span())) },
605 };
606 }
607 else { return Err(("Unexpected end of file".into(), lexer.span())); }
608 }
609
610 Ok(Value::Message(Message{name, comment: comment_for_msg, parent, attributes}))
611}
612
613pub fn parse_attribute(last_token: Token, lexer: &mut Lexer<'_, Token>,
614 parent_name: String, attributes_for_oneof: bool) -> Result<Attribute> {
615 let mut is_optional = false;
616 let mut is_repeated_and_size: Option<DynOrFixedType> = None;
617 let mut attr_type = SimpleType::NoTypeSetYet;
618 let mut ctoken = last_token;
619 let mut enum_or_msg_str = None;
620 let mut oneof_infos = None;
621 let lexer_span_start = lexer.span();
622 let mut specific_comment: Option<String> = None;
623
624 loop {
625 match ctoken {
626 Token::SpecificComment(s) => {
627 specific_comment = Some(s); () },
628 Token::Optional if is_repeated_and_size.is_some() =>
629 return Err(("Error: Optional and repeated not allowed together".to_owned(), lexer.span())),
630 Token::RepeatedFixed(_) | Token::RepeatedDyn(_) if is_optional =>
631 return Err(("Error: Optional and repeated are not allowed together".to_owned(), lexer.span())),
632
633 Token::Optional | Token::RepeatedDyn(_) | Token::RepeatedFixed(_) if attributes_for_oneof =>
634 return Err(("Error: Optional and repeated are not allowed in oneof".to_owned(), lexer.span())),
635
636 Token::Optional => is_optional = true,
637 Token::RepeatedDyn(b) => is_repeated_and_size = Some(DynOrFixedType::Dyn(b)),
638 Token::RepeatedFixed(b) => is_repeated_and_size = Some(DynOrFixedType::Fixed(b)),
639 Token::Bool => { attr_type = SimpleType::Bool; break; },
640 Token::UIntFixed(s) => { attr_type = SimpleType::UIntFixed(s); break; },
641 Token::UIntDyn((m,s)) if m < s =>
642 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())),
643 Token::UIntDyn((m,_)) if (m & 3) != 0 =>
644 return Err(("Error: Unsigned dyn integer bit size of integer type must be a multiple of 8".to_owned(), lexer.span())),
645 Token::UIntDyn((m,s)) => { attr_type = SimpleType::UIntDyn((m, s)); break; },
646 Token::IntFixed(s) => { attr_type = SimpleType::IntFixed(s); break; },
647 Token::IntDyn((m,s)) if m < s =>
648 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())),
649 Token::IntDyn((m,_)) if (m & 3) != 0 =>
650 return Err(("Error: Unsigned dyn integer bit size of integer type must be a multiple of 8".to_owned(), lexer.span())),
651 Token::IntDyn((m,s)) => {
652 attr_type = SimpleType::IntDyn((m,s)); break;
653 },
654 Token::Float => { attr_type = SimpleType::Float; break; },
656 Token::Double => { attr_type = SimpleType::Double; break; },
657 Token::FixedPoint(s) => { attr_type = SimpleType::FixedPrecision(s); break; },
658 Token::Binary(b) => { attr_type = SimpleType::Binary(b); break; },
659 Token::StringVal(s) => { enum_or_msg_str = Some(s); break; }
660 Token::OneOf => {
661 oneof_infos = match parse_oneof(lexer, parent_name.clone(), specific_comment.clone(),
662 is_repeated_and_size.clone(), is_optional.clone()) {
663 Ok(oo) => Some(oo),
664 Err(s) => { return Err(s); }
665 };
666 break;
667 }
668 _ => { return Err((format!("Error: Expected attribute type or modifier (got {ctoken:?}) when parsing msg or oneof '{parent_name}'")
669 .to_owned(), lexer.span())); }
670 }
671 if let Some(token) = lexer.next() {
672 match token {
673 Ok(t) => ctoken = t,
674 Err(_) => { return Err((format!("Error: Unexpected text found for msg '{parent_name}'.").to_owned(), lexer.span())); }
675 }
676 } else {
677 return Err(("Unexpected end of file".to_string(), lexer.span()));
678 }
679 }
680
681 let mut name= "".to_owned();
682 if oneof_infos.is_none() {
683 name = parse_one_token_with_arg!(
684 Token::StringVal, lexer, Some(format!("Error: Expected attribute name for msg '{parent_name}' (type: {attr_type:?}/{enum_or_msg_str:?})")))?.unwrap();
685
686 parse_one_token!(Token::SemiColon, lexer, Some(format!(
687 "Error: Expected semicolon to end line of attribute '{name}' of msg or oneof '{parent_name}'")))?.unwrap();
688 }
689 let num_of_set_types_or_opts = vec![(attr_type != SimpleType::NoTypeSetYet), enum_or_msg_str.is_some(), oneof_infos.is_some()]
690 .iter().map(|&x| if x { 1_u8 } else { 0_u8 }).sum::<u8>();
691 if num_of_set_types_or_opts > 1 {
692 let mut span = lexer_span_start.clone();
693 span.end = lexer.span().end;
694 return Err(("Error: Attribute contains inconsistent optional, simple types and messages or Enums".to_string(), span));
695 }
696
697 if let Some(oo) = oneof_infos {
698 Ok(oo)
699 }
700 else if let Some(t) = enum_or_msg_str {
701 Ok(Attribute{name, comment: specific_comment, is_repeated_and_size, is_optional,
702 specific_details: AttributeDetails::AttributeEnumOrMsg(t)})
703 }
704 else {
705 Ok(Attribute{name, comment: specific_comment, is_repeated_and_size, is_optional,
706 specific_details: AttributeDetails::AttributeSimple(attr_type)})
707 }
708}
709
710pub fn parse_oneof(lexer: &mut Lexer<'_, Token>, parent_name: String, comment: Option<String>,
711 is_repeated_and_size: Option<DynOrFixedType>, is_optional: bool) -> Result<Attribute> {
712 let oo_name = parse_one_token_with_arg!(
713 Token::StringVal, lexer, Some(format!("Error: Expected name for oneof in parent '{parent_name}'")))?.unwrap();
714
715 let bit_size = match parse_one_token_with_arg!(Token::EnumDynSize, lexer, Some("Expected oneof properties for dyn size, e.g. (4)."))? {
716 Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
717 };
718
719 parse_one_token!(Token::CBraceOpen, lexer, Some("Error: Expected open curly bracket to enclose oneof elements"))?.unwrap();
720
721 let mut oo_attribs = Vec::new();
722 loop {
723 if let Some(token) = lexer.next() {
724 match token {
725 Ok(Token::CBraceClose) => break,
726 Ok(last_token) => {
727 match parse_attribute(last_token, lexer, oo_name.clone(), true) {
728 Ok(o) => oo_attribs.push(o),
729 Err(s) => return Err(s),
730 }
731 }
732 Err(_) => { return Err((format!("Error: Unexpected text when decoding oneof ({token:?})").to_owned(), lexer.span())); },
733 }
734 }
735 }
736 Ok(Attribute{name: oo_name.clone(), comment, is_repeated_and_size, is_optional,
737 specific_details: AttributeDetails::AttributeOneOf(OneOfInfo{
738 name: format!("OO_{}_{}", parent_name.to_pascal_case(), oo_name.to_pascal_case()),
739 dyn_bits: bit_size, attributes: oo_attribs})})
740}
741
742pub fn parse_enum(lexer: &mut Lexer<'_, Token>, comment: Option<String>) -> Result<Value> {
743 let name = match parse_one_token_with_arg!(Token::StringVal, lexer, Some("Expected msg name but received."))? {
744 Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
745 };
746
747 let bit_size = match parse_one_token_with_arg!(Token::EnumDynSize, lexer, Some("Expected enum properties for dyn size, e.g. (4)."))? {
748 Ok(s) => s, Err(s) => { return Err(("Code should not be reached".into(), s)); }
749 };
750
751 parse_one_token!(Token::CBraceOpen, lexer, Some(format!("Expected open curly bracket for enum '{name}'")))?.unwrap();
765
766 let mut values = Vec::new();
767 let (mut value_found, mut is_default) = (false, false);
768 let mut default_val = None;
769 loop {
770 if let Some(token) = lexer.next() {
771 match token {
772 Ok(Token::CBraceClose) => break,
773 Ok(Token::StringVal(s)) => {
774 values.push(s.clone()); value_found=true;
775 if is_default { default_val = Some(s); }
776 is_default = false;
777 },
778 Ok(Token::Comma) => {
779 if !value_found { return Err(("Error: found comma but no enum value.".to_string(), lexer.span())) }
780 value_found=false },
781 Ok(Token::Comment) => (),
782 Ok(Token::Star) => {
783 if default_val.is_some() || value_found {
784 return Err(("Error: found default value marker (*) but default already set or marker not preceding value.".to_string(), lexer.span()))}
785 is_default = true;
786 }
787 _ => { return Err((format!("Error: Unexpected text found for enum '{name}'."), lexer.span())) },
788 }
789 } else { return Err(("Unexpected end of file".into(), lexer.span())); }
790 }
791 if default_val.is_none() { return Err(("Error: missing default value marker.".to_string(), lexer.span())); }
792
793 Ok(Value::Enum(Enum{name, comment, bit_size, values, default: default_val.unwrap() }))
794}
795
796
797#[derive(Debug, Clone)]
876pub struct Dependencies {
877 pub in_deps: Vec<String>,
878 pub out_deps: Vec<String>,
879}
880#[derive(Debug, Clone)]
881pub struct BitisProcessed {
882 pub max_version_number: u16,
883 pub msgs: Vec<Message>,
884 pub enums: Vec<Enum>,
885 pub oo_enums: Vec<(String, OneOfInfo)>,
886}
887
888pub fn process_and_validate_bitis(parsed_bitis: &Vec<Value>) -> BitisProcessed {
890 let msgs: Vec<_> = parsed_bitis.iter().filter_map(|v| {
1015 match v { Value::Message(msg) => Some(msg.clone()), _ => None }
1016 }).collect();
1017 let enums: Vec<_> = parsed_bitis.iter().filter_map(|v| {
1018 match v { Value::Enum(enm) => Some(enm.clone()), _ => None }
1019 }).collect();
1020
1021 fn get_oneofs(msg_name: String, attrs: &Vec<Attribute>) -> Option<Vec<(String, OneOfInfo)>> {
1022 let direct_oos = attrs.iter().filter_map(|attr| {
1023 match &attr.specific_details {
1024 AttributeDetails::AttributeOneOf(oo) => Some(vec![(msg_name.clone(), oo.clone())]),
1025 _ => None
1026 }
1027 }).collect::<Vec<Vec<(String, OneOfInfo)>>>().concat();
1028
1029 let inner_oos = direct_oos.iter().filter_map(|(_, doo)| {
1030 get_oneofs(msg_name.clone(), &doo.attributes)
1031 }).collect::<Vec<Vec<_>>>().concat();
1032
1033 let all_oos = vec![direct_oos, inner_oos].concat();
1034 if all_oos.len() == 0 { None }
1035 else { Some(all_oos) }
1036 }
1037 let oo_enums: Vec<_> = msgs.iter().filter_map(|msg| {
1038 get_oneofs(msg.name.clone(), &msg.attributes)
1039 }).collect::<Vec<_>>().concat();
1040
1041 { let msg_names = msgs.iter().map(|msg| &msg.name).collect::<Vec<_>>();
1045 msg_names.iter().for_each(|name| {
1046 if msg_names.iter().filter(|cname| **cname == *name).count() > 1 {
1048 println!("Error: Multiple instances of msg '{}' found.", name);
1049 abort()
1050 }
1051 });
1052 let enum_names = enums.iter().map(|enm| &enm.name).collect::<Vec<_>>();
1053 enum_names.iter().for_each(|name| {
1054 if enum_names.iter().filter(|cname| **cname == *name).count() > 1 {
1055 println!("Error: Multiple instances of enum '{}' found.", name); abort()
1056 }
1057 });
1058
1059 }
1062
1063
1064 BitisProcessed { max_version_number: 0, msgs, enums, oo_enums}
1065}
1066
1067pub fn dependencies_process(jd: JinjaData) -> Vec<String>{
1068 let mut dependencies = HashMap::new();
1069
1070 for msgs in jd.msgs.clone() {
1071 dependencies.insert(
1072 msgs.name.clone(), Dependencies{in_deps: vec![], out_deps: vec![]});
1073 }
1074 for enm in jd.enums {
1075 dependencies.insert(
1076 enm.name.clone(), Dependencies{in_deps: vec![], out_deps: vec![]});
1077 }
1078 for (_, oos) in jd.oos.clone() {
1079 dependencies.insert(
1080 oos.name.clone(), Dependencies{in_deps: vec![], out_deps: vec![]});
1081 }
1082
1083 for msgs in jd.msgs {
1085 for attr in msgs.attributes {
1086 if attr.is_enum || attr.is_msg || attr.is_oo {
1087 dependencies.get_mut(&attr.rust_type_str).unwrap().out_deps.push(msgs.name.clone());
1088 dependencies.get_mut(&msgs.name).unwrap().in_deps.push(attr.rust_type_str.clone());
1089 }
1090 }
1091 }
1092 for (_, msgs) in jd.oos {
1093 for attr in msgs.attributes {
1094 if attr.is_enum || attr.is_msg || attr.is_oo {
1095 dependencies.get_mut(&attr.rust_type_str).unwrap().out_deps.push(msgs.name.clone());
1096 dependencies.get_mut(&msgs.name).unwrap().in_deps.push(attr.rust_type_str.clone());
1097 }
1098 }
1099 }
1100 println!("{:#?}", dependencies.clone());
1101
1102 let mut object_order = Vec::new();
1103 while dependencies.len() > 0 {
1104 let mut cobjs: Vec<_> = dependencies.clone().iter().filter_map(|(obj_name, deps)| {
1105 if deps.in_deps.len() == 0 { Some(obj_name.clone()) }
1106 else { None }
1107 }).collect();
1108
1109 for co in cobjs.clone() {
1110 dependencies.remove(&co);
1111 }
1112 for co in cobjs.clone() {
1113 for (_, deps) in &mut dependencies {
1114 deps.in_deps.retain(|x| *x != co);
1115 }
1116 }
1117 object_order.append(&mut cobjs);
1118 }
1119 println!("{:?}", object_order);
1120
1121 object_order
1122}
1123#[cfg(test)]
1126mod bitis_semantic {
1127 use rstest::rstest;
1128 use super::*;
1129
1130 #[rstest]
1131 fn msg_empty_msg() {
1132 let test_empty_msg = "msg Lala { }";
1133
1134 let mut lexer = Token::lexer(test_empty_msg);
1135 lexer.extras = 0;
1136
1137 let parsed_bitis = parse_root(&mut lexer);
1138 if let Err(s) = parsed_bitis.clone() {
1139 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1140 }
1141 assert_eq!(parsed_bitis.is_ok(), true);
1142
1143 let parsed_bitis = parsed_bitis.unwrap();
1144 assert_eq!(parsed_bitis.len(), 1);
1145
1146 assert!(if let Value::Message(_) = parsed_bitis[0].clone() { true } else { false });
1147
1148 if let Value::Message(msg) = parsed_bitis[0].clone() {
1149 assert_eq!(msg.name, "Lala".to_string());
1150 }
1151
1152 let process_result = process_and_validate_bitis(&parsed_bitis);
1156 println!("process_result {:?}", process_result);
1157
1158 assert_eq!(process_result.msgs.len(), 1);
1159 assert_eq!(process_result.enums.len(), 0);
1160 }
1161
1162 #[rstest]
1163 fn msg_simple_msg() {
1164 let test_empty_msg = "msg Lala { uint_7 a1; }";
1165
1166 let mut lexer = Token::lexer(test_empty_msg);
1167 lexer.extras = 0;
1168
1169 let parsed_bitis = parse_root(&mut lexer);
1170 if let Err(s) = parsed_bitis.clone() {
1171 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1172 }
1173 assert_eq!(parsed_bitis.is_ok(), true);
1174
1175 let parsed_bitis = parsed_bitis.unwrap();
1176 assert_eq!(parsed_bitis.len(), 1);
1177
1178 if let Value::Message(msg) = parsed_bitis[0].clone() {
1179 assert_eq!(msg.attributes.len(), 1);
1180 assert_eq!(msg.attributes[0].name, "a1".to_string());
1181 if let AttributeDetails::AttributeSimple(s) = msg.attributes[0].specific_details.clone() {
1182 assert_eq!(s, SimpleType::UIntFixed(7));
1183 }
1184 else { assert!(false, "Attribute type must be AttributeSimple."); }
1185 }
1186 else { assert!(false, "Value must be a message."); }
1187 }
1188
1189 #[rstest]
1190 fn msg_simple_enum() {
1191 let test_empty_msg = "enum Lala(4) { one, two }";
1192
1193 let mut lexer = Token::lexer(test_empty_msg);
1194 lexer.extras = 0;
1195
1196 let parsed_bitis = parse_root(&mut lexer);
1197 if let Err(s) = parsed_bitis.clone() {
1198 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1199 }
1200 assert_eq!(parsed_bitis.is_ok(), true);
1201
1202 let parsed_bitis = parsed_bitis.unwrap();
1203 assert_eq!(parsed_bitis.len(), 1);
1204
1205 if let Value::Enum(enm) = parsed_bitis[0].clone() {
1206 assert_eq!(enm.values.len(), 2);
1207 assert_eq!(enm.values[0], "one".to_string());
1208 assert_eq!(enm.values[1], "two".to_string());
1209 }
1210 else { assert!(false, "Value must be a message."); }
1211 }
1212
1213
1214 }
1251
1252#[cfg(test)]
1253mod bitis_generate_rust {
1254 use rstest::rstest;
1255 use super::*;
1256
1257 const HEADER: &str = "use bitis_lib::*;\n\n";
1258 const ENUMS_HEADER: &str = "// Enums\n";
1259 const OO_HEADER: &str = "// Enums for oneof\n";
1260 const MSG_HEADER: &str = "// Messages\n";
1261 const PER_ENUM_HEADER: &str = "#[derive(BiserdiEnum, Debug, Clone, PartialEq)]\n#[biserdi_enum_id_dynbits(3)]\n#[allow(nonstandard_style)]\n";
1262 const PER_OO_HEADER: &str = "#[derive(BiserdiOneOf, Debug, Clone, PartialEq)]\n#[biserdi_enum_id_dynbits(3)]\n#[allow(nonstandard_style)]\n";
1263 const PER_MSG_HEADER: &str = "#[derive(BiserdiMsg, Debug, Clone, PartialEq)]\n#[allow(nonstandard_style)]\n";
1264
1265 #[rstest]
1266 fn msg_empty_msg() {
1267 let test_empty_msg = "msg Lala { }";
1268
1269 let mut lexer = Token::lexer(test_empty_msg);
1270 lexer.extras = 0;
1271
1272 let parsed_bitis = parse_root(&mut lexer);
1273 if let Err(s) = parsed_bitis.clone() {
1274 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1275 }
1276 assert_eq!(parsed_bitis.is_ok(), true);
1277
1278 let parsed_bitis = parsed_bitis.unwrap();
1279 assert_eq!(parsed_bitis.len(), 1);
1280
1281 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1282 let rdo = RustDataObjects{ d: JinjaData{
1283 enums: processed_bitis.enums,
1284 msgs: to_rust_messages(&processed_bitis.msgs),
1285 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1286
1287 let rendered = rdo.render().unwrap();
1288 let lala_empty = "pub struct Lala {\n}\n";
1289 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + "\n\n" +
1290 MSG_HEADER + PER_MSG_HEADER +lala_empty).to_string());
1291 }
1292
1293 #[rstest]
1294 fn msg_simple_msg() {
1295 let test_empty_msg = "//| comment for Lala\nmsg Lala { int_5 a1; repeated_fixed_4 bool bool_array; }";
1296 println!("Input code:\n{}", test_empty_msg);
1297
1298 let mut lexer = Token::lexer(test_empty_msg);
1299 lexer.extras = 0;
1300
1301 let parsed_bitis = parse_root(&mut lexer);
1302 if let Err(s) = parsed_bitis.clone() {
1303 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_empty_msg[s.1.clone()], s.1);
1304 }
1305 assert_eq!(parsed_bitis.is_ok(), true);
1306
1307 let parsed_bitis = parsed_bitis.unwrap();
1308 assert_eq!(parsed_bitis.len(), 1);
1309
1310 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1311 let rdo = RustDataObjects{ d: JinjaData{
1312 enums: processed_bitis.enums, msgs: to_rust_messages(&processed_bitis.msgs),
1313 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1314
1315 let rendered = rdo.render().unwrap();
1316 let lala_commment = "/// comment for Lala\n";
1317 let lala_empty = "pub struct Lala {\n pub a1: VarWithGivenBitSize<i8, 5>,\n pub bool_array: FixedArray<bool,4>,\n}\n";
1318 println!("rendered:\n{}",rendered);
1319 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + "\n\n" +
1320 MSG_HEADER + lala_commment + PER_MSG_HEADER +lala_empty).to_string());
1321 }
1322
1323 #[rstest]
1324 fn msg_simple_enum() {
1325 let test_enum_msg = "//| comment for Numbers\nenum Numbers(3) {\n // Comment for One\n One,\n Two,\n Three\n}";
1326 println!("Input code:\n{}", test_enum_msg);
1327
1328 let mut lexer = Token::lexer(test_enum_msg);
1329 lexer.extras = 0;
1330
1331 let parsed_bitis = parse_root(&mut lexer);
1332 if let Err(s) = parsed_bitis.clone() {
1333 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_enum_msg[s.1.clone()], s.1);
1334 }
1335 assert_eq!(parsed_bitis.is_ok(), true);
1336
1337 let parsed_bitis = parsed_bitis.unwrap();
1338 assert_eq!(parsed_bitis.len(), 1);
1339
1340 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1341 let rdo = RustDataObjects{ d: JinjaData{ enums: processed_bitis.enums,
1342 msgs: to_rust_messages(&processed_bitis.msgs),
1343 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1344
1345 let rendered = rdo.render().unwrap();
1346 let lala_commment = "/// comment for Numbers\n";
1347 let lala_enum = "pub enum Numbers {\n One,\n Two,\n Three,\n}\n\n";
1348 println!("*rendered:\n{}",rendered);
1349 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + lala_commment + PER_ENUM_HEADER + lala_enum + OO_HEADER +
1350 "\n\n" + MSG_HEADER ).to_string());
1351 }
1352
1353 #[rstest]
1354 fn msg_simple_oneof() {
1355 let test_enum_msg = "//| comment for Oneof\nmsg TestOO {\n oneof oo_li(3) { uint_3 test1; float test2; }\n bool b1;\n}";
1356 println!("Input code:\n{}", test_enum_msg);
1357
1358 let mut lexer = Token::lexer(test_enum_msg);
1359 lexer.extras = 0;
1360
1361 let parsed_bitis = parse_root(&mut lexer);
1362 if let Err(s) = parsed_bitis.clone() {
1363 panic!("Error: {} ('{}' ,span: {:?})", s.0, &test_enum_msg[s.1.clone()], s.1);
1364 }
1365 assert_eq!(parsed_bitis.is_ok(), true);
1366
1367 let parsed_bitis = parsed_bitis.unwrap();
1368 assert_eq!(parsed_bitis.len(), 1);
1369
1370 let processed_bitis = process_and_validate_bitis(&parsed_bitis);
1371 let rdo = RustDataObjects{ d: JinjaData{ enums: processed_bitis.enums,
1372 msgs: to_rust_messages(&processed_bitis.msgs),
1373 oos: to_rust_oneofs(&processed_bitis.oo_enums, &processed_bitis.msgs) } };
1374
1375 let rendered = rdo.render().unwrap();
1376 let testoo_commment = "/// comment for Oneof\n";
1377 let testoo_enum = "pub enum OO_TestOo_OoLi {\n Test1(VarWithGivenBitSize<u8, 3>),\n Test2(f32),\n}\n\n";
1378 let testoo_msg = "pub struct TestOo {\n pub oo_li: OO_TestOo_OoLi,\n pub b1: bool,\n}\n";
1379 println!("*rendered:\n{}",rendered);
1380 assert_eq!(rendered, (HEADER.to_owned() + ENUMS_HEADER + "\n\n" + OO_HEADER + PER_OO_HEADER
1381 + testoo_enum + MSG_HEADER + testoo_commment + PER_MSG_HEADER + testoo_msg).to_string());
1382 }
1383}
1384
1385#[cfg(test)]
1386mod bitis_compile {
1387 use std::fs;
1388 use std::path::Path;
1389 use rstest::rstest;
1390 use super::*;
1391
1392 fn compile(content: &str) -> BitisProcessed {
1393 let mut lexer = Token::lexer(content);
1394 lexer.extras = 0;
1395 println!("*** content:\n{}", content);
1396 let bitis_parsed = match parse_root(&mut lexer) {
1397 Ok(v) => v,
1398 Err(e) => {
1399 let (err_str, err_span) = e.clone();
1400 let content_err = &content[err_span];
1401 println!("Error: {}\n -> Source: '{}'", err_str, content_err);
1402 abort()
1403 }
1404 };
1405 println!("** content:\n{:?}", bitis_parsed);
1406 process_and_validate_bitis(&bitis_parsed)
1407 }
1408 fn render(d: JinjaData) {
1409 let rdo = RustDataObjects{ d: d.clone() };
1410 let rendered_rust = rdo.render().unwrap();
1411 println!("*** rendered DO:\n{}", rendered_rust);
1412 fs::write(Path::new("./test_data/test_py/bitis/src/messages_test.rs"), rendered_rust).expect("Unable to write file");
1413
1414 let rdo = RustPyDataObjects{ d: d.clone() };
1415 let rendered_rust = rdo.render().unwrap();
1416 println!("*** rendered PyDO:\n{}", rendered_rust);
1417 fs::write(Path::new("./test_data/test_py/bitis/src/pyrust_test.rs"), rendered_rust).expect("Unable to write file");
1418
1419 let rdo = RustPyLib{ d: d.clone(), lib_name: "bitis_msgs".into() };
1420 let rendered_rust = rdo.render().unwrap();
1421 println!("*** rendered pyLib:\n{}", rendered_rust);
1422 fs::write(Path::new("./test_data/test_py/bitis/src/lib_test.rs"), rendered_rust).expect("Unable to write file");
1423
1424 let rdo = PyTypeHints{ d };
1425 let rendered_rust = rdo.render().unwrap();
1426 println!("*** rendered py_type_hints:\n{}", rendered_rust);
1427 fs::write(Path::new("./test_data/test_py/bitis/bitis_msgs/bitis_msgs.pyi"), rendered_rust).expect("Unable to write file");
1428 }
1429
1430 #[rstest]
1431 #[ignore]
1432 fn simple_rust_py() {
1433 let bitis_str = "msg ParamTestSimple { uint_4 param_1; bool param_2; }";
1434
1435 let bitis_processed_org = compile(bitis_str);
1436
1437 let bitis_processed = bitis_processed_org.clone();
1438 let d = JinjaData{
1439 enums: bitis_processed.enums,
1440 msgs: to_rust_messages(&bitis_processed.msgs),
1441 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1442 };
1443 render(d);
1444 }
1445
1446 #[rstest]
1447 #[ignore]
1448 fn nested_rust_py() {
1449 let bitis_str = "msg Inner { uint_2 val; }\nmsg ParamTestWithInner { uint_4 param_1; bool param_2; Inner inner; }";
1450
1451 let bitis_processed_org = compile(bitis_str);
1452
1453 let bitis_processed = bitis_processed_org.clone();
1454
1455 let d = JinjaData{
1456 enums: bitis_processed.enums,
1457 msgs: to_rust_messages(&bitis_processed.msgs),
1458 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1459 };
1460 render(d);
1461 }
1462 #[test]
1463 #[ignore]
1464 fn nested_and_enum_rust_py() {
1465 let bitis_str = [
1466 "enum Numbers(4) { one, two, three, four }\n/// Test comment for Inner\nmsg Inner { uint_3 val; Numbers num; }\n",
1467 "msg ParamTestWithInner { uint_4 param_1; bool param_2; Inner inner; } }"
1468 ].join("");
1469
1470 let bitis_processed_org = compile(bitis_str.as_str());
1471
1472 let bitis_processed = bitis_processed_org.clone();
1473
1474 let d = JinjaData{
1475 enums: bitis_processed.enums,
1476 msgs: to_rust_messages(&bitis_processed.msgs),
1477 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1478 };
1479 render(d);
1480 }
1481 #[rstest]
1482 fn oneof_nested_and_enum_rust_py() {
1483 let bitis_str = [
1484 "//| 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",
1485 "msg ParamTestWithInner { uint_4 param_1; bool param_2; oneof action(4) { Inner inner; uint_3 val; } }"
1486 ].join("");
1487
1488 let bitis_processed_org = compile(bitis_str.as_str());
1489
1490 let bitis_processed = bitis_processed_org.clone();
1491
1492 let d = JinjaData{
1493 enums: bitis_processed.enums,
1494 msgs: to_rust_messages(&bitis_processed.msgs),
1495 oos: to_rust_oneofs(&bitis_processed.oo_enums, &bitis_processed.msgs)
1496 };
1497 render(d);
1498 }
1499}
1500
1501#[cfg(test)]
1502mod bitis_serialization {
1503 use rstest::rstest;
1505 use super::*;
1506
1507 #[rstest]
1509 fn msg_simple_msg_compile() {
1510 let test_empty_msg = "msg Lala { repeated_fixed_10 bool data_bool; uint_4 data1_uint; uint_12 data2_uint; }";
1511
1512 let mut lexer = Token::lexer(test_empty_msg);
1513 lexer.extras = 0;
1514
1515 let parsed_bitis = parse_root(&mut lexer);
1516 assert_eq!(parsed_bitis.is_ok(), true);
1517
1518 let _parsed_bitis = parsed_bitis.unwrap();
1519
1520 }
1545}
1546
1547#[cfg(test)]
1548mod bitis_processing {
1549 use rstest::rstest;
1550 use crate::AttributeDetails::{AttributeEnumOrMsg, AttributeSimple};
1551 use super::*;
1552
1553 #[rstest]
1554 #[ignore]
1555 fn msg_base_and_v2() {
1556 let bitis_values = vec![
1557 Value::Message(Message{
1558 name: "TestMsg".to_string(),
1559 comment: Some("This is a test".to_string()),
1561 parent: None,
1562 attributes: vec![Attribute{name: "a1".to_string(), comment: None,
1563 is_repeated_and_size: None, is_optional: false,
1564 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1565 }],
1566 }),
1567 Value::Message(Message{
1568 name: "TestMsg".to_string(),
1569 comment: Some("This is a test".to_string()),
1571 parent: None,
1572 attributes: vec![Attribute{name: "a2".to_string(), comment: None,
1573 is_repeated_and_size: None, is_optional: false,
1574 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1575 }],
1576 })
1577 ];
1578 let pb = process_and_validate_bitis(&bitis_values);
1579
1580 assert_eq!(pb.max_version_number, 2);
1581 assert_eq!(pb.msgs.len(), 3);
1582
1583 assert_eq!(pb.msgs[0].name, "TestMsg_Base".to_string());
1584 assert_eq!(pb.msgs[1].name, "TestMsg_V1".to_string());
1585 assert_eq!(pb.msgs[2].name, "TestMsg_V2".to_string());
1586
1587 assert_eq!(pb.msgs[0].attributes.len(), 1);
1588 assert_eq!(pb.msgs[0].attributes.get(0).unwrap().name, "a1".to_string());
1589 assert_eq!(pb.msgs[1].attributes.len(), 0);
1590 assert_eq!(pb.msgs[2].attributes.len(), 1);
1591 assert_eq!(pb.msgs[2].attributes.get(0).unwrap().name, "a2".to_string());
1592 }
1593
1594 #[rstest]
1595 #[ignore]
1596 fn msg_base_and_v2_and_add_msg() {
1597 let bitis_values = vec![
1598 Value::Message(Message{
1599 name: "TestMsgInner".to_string(),
1600 comment: Some("This is a test2".to_string()),
1602 parent: None,
1603 attributes: vec![Attribute{name: "lala".to_string(), comment: None,
1604 is_repeated_and_size: None, is_optional: false,
1605 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1606 }],
1607 }),
1608 Value::Message(Message{
1609 name: "TestMsgInner".to_string(),
1610 comment: Some("This is a test2".to_string()),
1612 parent: None,
1613 attributes: vec![
1614 Attribute{name: "lala".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1615 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),},
1616 Attribute{name: "lala2".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1617 specific_details: AttributeSimple(SimpleType::UIntFixed(3)),},
1618 ],
1619 }),
1620 Value::Message(Message{
1621 name: "TestMsg".to_string(),
1622 comment: Some("This is a test".to_string()),
1624 parent: None,
1625 attributes: vec![
1626 Attribute{ name: "a1".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1627 specific_details: AttributeSimple(SimpleType::UIntFixed(4)) },
1628 Attribute{ name: "lala_use".to_string(), comment: None, is_repeated_and_size: None, is_optional: false,
1629 specific_details: AttributeEnumOrMsg("TestMsgInner".to_string()) },
1630 ],
1631 }),
1632 Value::Message(Message{
1633 name: "TestMsg".to_string(),
1634 comment: Some("This isa test".to_string()),
1636 parent: None,
1637 attributes: vec![Attribute{name: "a2".to_string(), comment: None,
1638 is_repeated_and_size: None, is_optional: false,
1639 specific_details: AttributeSimple(SimpleType::UIntFixed(4)),
1640 }],
1641 }),
1642 ];
1643 let pb = process_and_validate_bitis(&bitis_values);
1644
1645 assert_eq!(pb.max_version_number, 2);
1646 assert_eq!(pb.msgs.len(), 4);
1647
1648}
1663}
1664