1#[macro_use]
48extern crate nom;
49
50#[macro_use]
51extern crate log;
52
53use std::io::Read;
54
55use std::fs;
56
57use std::path::Path;
58
59use std::str;
60use std::str::FromStr;
61
62use std::collections::HashMap;
63
64use nom::IResult;
65
66mod parse;
67mod display;
68mod normalize;
69mod crc;
70
71use crc::CRC64WE as CRC;
72
73pub use normalize::NormalizedFile;
74
75#[derive(Debug, PartialEq, Eq)]
77pub struct DSDL {
78 files: HashMap<String, File>,
79}
80
81impl DSDL {
82 pub fn read<P: AsRef<Path>>(path: P) -> std::io::Result<DSDL> {
92 let mut dsdl = DSDL{files: HashMap::new()};
93
94 if path.as_ref().is_dir() {
95 for entry in fs::read_dir(path)? {
96 let current_path = entry?.path();
97 DSDL::read_uavcan_files(current_path.as_ref(), String::new(), &mut dsdl.files)?;
98 }
99 } else {
100 DSDL::read_uavcan_files(path.as_ref(), String::new(), &mut dsdl.files)?;
101 }
102
103 Ok(dsdl)
104 }
105
106 fn read_uavcan_files(path: &Path, namespace: String, files: &mut HashMap<String, File>) -> std::io::Result<()> {
107 let uavcan_path = if namespace.as_str() == "" {
108 String::from(path.file_name().unwrap().to_str().unwrap())
109 } else {
110 namespace.clone() + "." + path.file_name().unwrap().to_str().unwrap()
111 };
112 if path.is_dir() {
113 for entry in fs::read_dir(path)? {
114 let current_path = entry?.path();
115 DSDL::read_uavcan_files(¤t_path, uavcan_path.clone(), files)?;
116 }
117 } else if let IResult::Done(_i, file_name) = parse::file_name(uavcan_path.as_bytes()) {
118 let mut file = fs::File::open(path)?;
119 let mut bytes = Vec::new();
120 file.read_to_end(&mut bytes)?;
121 let bytes_slice = bytes.into_boxed_slice();
122 let (remaining, definition) = parse::type_definition(&bytes_slice).unwrap();
123
124 assert!(remaining == &b""[..], "Parsing failed at file: {}, with the following data remaining: {}", uavcan_path, str::from_utf8(remaining).unwrap());
125
126 let qualified_name = if file_name.namespace.as_str() == "" {
127 file_name.name.clone()
128 } else {
129 file_name.namespace.clone() + "." + file_name.name.as_str()
130 };
131 files.insert(qualified_name, File{name: file_name, definition: definition});
132 } else {
133 warn!("The file, {}, was not recognized as a DSDL file. DSDL files need to have the .uavcan extension", uavcan_path);
134 }
135
136 Ok(())
137 }
138
139 pub fn get_file<T: AsRef<str>>(&self, name: T) -> Option<&File> {
151 self.files.get(name.as_ref())
152 }
153
154 pub fn files(&self) -> Vec<&File> {
166 self.files.values().collect()
167 }
168
169 pub fn data_type_signature<T: AsRef<str>>(&self, name: T) -> Option<u64> {
181 let normalized_file = match self.get_file(name) {
182 Some(file) => file.clone().normalize(),
183 None => return None,
184 };
185 let current_namespace = normalized_file.as_file().clone().name.namespace;
186 let mut crc = CRC::from_value(normalized_file.dsdl_signature());
187
188 let lines = match normalized_file.as_file().definition {
189 TypeDefinition::Message(MessageDefinition(ref lines)) => lines.clone(),
190 TypeDefinition::Service(ServiceDefinition{request: MessageDefinition(ref request), response: MessageDefinition(ref response)}) => {let mut lines = request.clone(); lines.append(&mut response.clone()); lines},
191 };
192
193 for line in lines {
194 match line {
195 Line::Definition(
196 AttributeDefinition::Field(
197 FieldDefinition{field_type: Ty::Composite(
198 CompositeType{namespace: None, ref name}), ..}), _)
199 => crc.extend(self.data_type_signature((String::from(current_namespace.clone()) + "." + name.as_ref()).as_str()).unwrap()),
200 Line::Definition(
201 AttributeDefinition::Field(
202 FieldDefinition{field_type: Ty::Composite(
203 CompositeType{namespace: Some(ref namespace), ref name}), .. }), _)
204 => crc.extend(self.data_type_signature(String::from(namespace.clone()) + "." + name.as_ref()).unwrap()),
205 _ => (),
206 }
207
208 }
209 Some(crc.value())
210
211 }
212
213}
214
215#[derive(Clone, Debug, PartialEq, Eq)]
217pub struct FileName {
218 pub id: Option<String>,
219 pub namespace: String,
220 pub name: String,
221 pub version: Option<Version>,
222}
223
224impl FileName {
225 pub fn split_namespace(&self) -> Vec<String> {
242 if self.namespace == String::new() {
243 Vec::new()
244 } else {
245 self.namespace.split('.').map(|x| String::from(x)).collect()
246 }
247 }
248
249 pub fn rsplit_namespace(&self) -> Vec<String> {
266 if self.namespace == String::new() {
267 Vec::new()
268 } else {
269 self.namespace.rsplit('.').map(|x| String::from(x)).collect()
270 }
271 }
272
273}
274
275
276#[derive(Clone, Debug, PartialEq, Eq)]
277pub enum ParseFileNameError {
278 Extension,
279 Format,
280 VersionFormat,
281}
282
283impl FromStr for FileName {
284 type Err = ParseFileNameError;
285
286 fn from_str(s: &str) -> Result<FileName, Self::Err> {
287 let mut split = s.rsplit('.').peekable();
288
289 if let Some("uavcan") = split.next() {
290 } else {
291 return Err(ParseFileNameError::Extension);
292 }
293
294 let version = match u32::from_str(split.peek().ok_or(ParseFileNameError::Format)?) {
295 Ok(minor_version) => {
296 split.next().unwrap(); let major_version = u32::from_str(split.next().ok_or(ParseFileNameError::Format)?).map_err(|_| ParseFileNameError::VersionFormat)?;
298 Some(Version{major: major_version, minor: minor_version})
299 },
300 Err(_) => None,
301 };
302
303 let name = String::from(split.next().unwrap());
304
305 let id = if let IResult::Done(_i, o) = parse::id(split.peek().unwrap_or(&"").as_bytes()) {
306 split.next().unwrap();
307 Some(o)
308 } else {
309 None
310 };
311
312 let mut namespace = String::from(split.next().unwrap_or(""));
313 while let Some(namespace_part) = split.next() {
314 namespace = String::from(namespace_part) + "." + namespace.as_str();
315 }
316
317 Ok(FileName{id: id, namespace: namespace, name: name, version: version})
318 }
319}
320
321
322#[derive(Clone, Debug, PartialEq, Eq)]
324pub struct Version {
325 pub major: u32,
326 pub minor: u32,
327}
328
329#[derive(Clone, Debug, PartialEq, Eq)]
331pub struct File {
332 pub name: FileName,
333 pub definition: TypeDefinition,
334}
335
336#[derive(Clone, Debug, PartialEq, Eq)]
341pub enum TypeDefinition {
342 Message(MessageDefinition),
343 Service(ServiceDefinition),
344}
345
346impl From<MessageDefinition> for TypeDefinition {
347 fn from(d: MessageDefinition) -> Self {
348 TypeDefinition::Message(d)
349 }
350}
351
352impl From<ServiceDefinition> for TypeDefinition {
353 fn from(d: ServiceDefinition) -> Self {
354 TypeDefinition::Service(d)
355 }
356}
357
358
359
360#[derive(Clone, Debug, PartialEq, Eq)]
362pub struct MessageDefinition(pub Vec<Line>);
363
364#[derive(Clone, Debug, PartialEq, Eq)]
372pub struct ServiceDefinition{
373 pub request: MessageDefinition,
375 pub response: MessageDefinition,
377}
378
379#[derive(Clone, Debug, PartialEq, Eq)]
385pub enum Line {
386 Empty,
387 Comment(Comment),
388 Definition(AttributeDefinition, Option<Comment>),
389 Directive(Directive, Option<Comment>),
390}
391
392impl Line {
393 pub fn is_empty(&self) -> bool {
395 match *self {
396 Line::Empty => true,
397 _ => false,
398 }
399 }
400
401 pub fn is_directive(&self) -> bool {
403 match *self {
404 Line::Directive(_,_) => true,
405 _ => false,
406 }
407 }
408
409 pub fn is_definition(&self) -> bool {
411 match *self {
412 Line::Definition(_,_) => true,
413 _ => false,
414 }
415 }
416
417 pub fn is_comment(&self) -> bool {
419 match *self {
420 Line::Comment(_) => true,
421 _ => false,
422 }
423 }
424
425 pub fn has_comment(&self) -> bool {
427 match *self {
428 Line::Comment(_) => true,
429 Line::Directive(_,Some(_)) => true,
430 Line::Definition(_,Some(_)) => true,
431 _ => false,
432 }
433 }
434
435}
436
437#[derive(Clone, Debug, PartialEq, Eq)]
441pub struct CompositeType {
442 pub namespace: Option<Ident>,
443 pub name: Ident,
444}
445
446impl FromStr for CompositeType {
447 type Err = ();
448
449 fn from_str(s: &str) -> Result<CompositeType, Self::Err> {
450 if s.contains('.') {
451 let mut split = s.rsplitn(2, '.');
452 let name = Ident(String::from(split.next().unwrap()));
453 let namespace = match split.next() {
454 Some(x) => Some(Ident(String::from(x))),
455 None => None,
456 };
457 Ok(CompositeType {
458 namespace: namespace,
459 name: name,
460 })
461 } else {
462 Ok(CompositeType {
463 namespace: None,
464 name: Ident(String::from(s))
465 })
466 }
467 }
468}
469
470#[derive(Clone, Debug, PartialEq, Eq)]
472pub struct Comment(String);
473
474impl<'a> From<&'a str> for Comment {
475 fn from(s: &'a str) -> Comment {
476 Comment(String::from(s))
477 }
478}
479
480impl FromStr for Comment {
481 type Err = ();
482
483 fn from_str(s: &str) -> Result<Comment, Self::Err> {
484 Ok(Comment::from(s))
485 }
486}
487
488impl AsRef<str> for Comment {
489 fn as_ref(&self) -> &str {
490 self.0.as_ref()
491 }
492}
493
494#[derive(Clone, Copy, Debug, PartialEq, Eq)]
499pub enum Directive {
500 Union,
505}
506
507#[derive(Clone, Debug, PartialEq, Eq)]
508pub enum ParseDirectiveError {
509 NotDirective(String),
510}
511
512impl FromStr for Directive {
513 type Err = ParseDirectiveError;
514
515 fn from_str(s: &str) -> Result<Directive, Self::Err> {
516 match s {
517 "@union" => Ok(Directive::Union),
518 "union" => Ok(Directive::Union),
519 _ => Err(ParseDirectiveError::NotDirective(String::from(s))),
520 }
521 }
522}
523
524#[derive(Clone, Debug, PartialEq, Eq)]
525struct ServiceResponseMarker {}
526
527#[derive(Clone, Debug, PartialEq, Eq)]
529pub struct Ident(String);
530
531impl<'a> From<&'a str> for Ident {
532 fn from(s: &'a str) -> Ident {
533 Ident(String::from(s))
534 }
535}
536
537impl FromStr for Ident {
538 type Err = ();
539
540 fn from_str(s: &str) -> Result<Ident, Self::Err> {
541 Ok(Ident(String::from(s)))
542 }
543}
544
545impl AsRef<str> for Ident {
546 fn as_ref(&self) -> &str {
547 self.0.as_ref()
548 }
549}
550
551impl From<Ident> for String {
552 fn from(i: Ident) -> String {
553 i.0
554 }
555}
556
557impl From<String> for Ident {
558 fn from(s: String) -> Ident {
559 Ident(s)
560 }
561}
562
563#[derive(Clone, Copy, Debug, PartialEq, Eq)]
565pub struct Size(u64);
566
567impl FromStr for Size {
568 type Err = std::num::ParseIntError;
569
570 fn from_str(s: &str) -> Result<Self, Self::Err> {
571 Ok(Size(u64::from_str(s)?))
572 }
573}
574
575impl From<Size> for u64 {
576 fn from(i: Size) -> u64 {
577 i.0
578 }
579}
580
581impl From<u8> for Size {
582 fn from(i: u8) -> Size {
583 Size(u64::from(i))
584 }
585}
586
587impl From<u16> for Size {
588 fn from(i: u16) -> Size {
589 Size(u64::from(i))
590 }
591}
592
593impl From<u32> for Size {
594 fn from(i: u32) -> Size {
595 Size(u64::from(i))
596 }
597}
598
599impl From<u64> for Size {
600 fn from(i: u64) -> Size {
601 Size(i)
602 }
603}
604
605#[derive(Clone, Debug, PartialEq, Eq)]
607pub enum Const {
608
609 Dec(String),
611
612 Hex(String),
614
615 Oct(String),
617
618 Bin(String),
620
621 Bool(bool),
623
624 Char(String),
626
627 Float(String),
629}
630
631#[derive(Clone, Copy, Debug, PartialEq, Eq)]
635pub enum CastMode {
636 Saturated,
642
643 Truncated,
646}
647
648#[derive(Clone, Debug, PartialEq, Eq)]
649pub enum ParseCastModeError {
650 NotCastMode(String),
651}
652
653impl FromStr for CastMode {
654 type Err = ParseCastModeError;
655
656 fn from_str(s: &str) -> Result<Self, Self::Err> {
657 match s {
658 "saturated" => Ok(CastMode::Saturated),
659 "truncated" => Ok(CastMode::Truncated),
660 _ => Err(ParseCastModeError::NotCastMode(String::from(s))),
661 }
662 }
663}
664
665#[derive(Clone, Debug, PartialEq, Eq)]
667pub enum ArrayInfo {
668 Single,
670 DynamicLess(Size),
672 DynamicLeq(Size),
674 Static(Size),
676}
677
678
679#[derive(Clone, Debug, PartialEq, Eq)]
688pub struct FieldDefinition {
689 pub cast_mode: Option<CastMode>,
690 pub field_type: Ty,
691 pub array: ArrayInfo,
692 pub name: Option<Ident>,
693}
694
695#[derive(Clone, Debug, PartialEq, Eq)]
700pub struct ConstDefinition {
701 pub cast_mode: Option<CastMode>,
702 pub field_type: Ty,
703 pub name: Ident,
704 pub constant: Const,
705}
706
707#[derive(Clone, Debug, PartialEq, Eq)]
709pub enum AttributeDefinition {
710 Field(FieldDefinition),
711 Const(ConstDefinition),
712}
713
714impl From<FieldDefinition> for AttributeDefinition {
715 fn from(d: FieldDefinition) -> Self {
716 AttributeDefinition::Field(d)
717 }
718}
719
720impl From<ConstDefinition> for AttributeDefinition {
721 fn from(d: ConstDefinition) -> Self {
722 AttributeDefinition::Const(d)
723 }
724}
725
726#[derive(Clone, Debug, PartialEq, Eq)]
728pub enum Ty{
729 Primitive(PrimitiveType),
730 Composite(CompositeType),
731}
732
733impl Ty {
734 pub fn is_void(&self) -> bool {
735 match *self{
736 Ty::Primitive(ref x) => x.is_void(),
737 Ty::Composite(_) => false,
738 }
739 }
740}
741
742impl From<PrimitiveType> for Ty {
743 fn from(t: PrimitiveType) -> Ty {
744 Ty::Primitive(t)
745 }
746}
747
748impl From<CompositeType> for Ty {
749 fn from(t: CompositeType) -> Ty {
750 Ty::Composite(t)
751 }
752}
753
754#[derive(Clone, Copy, Debug, PartialEq, Eq)]
759pub enum PrimitiveType {
760 Bool,
761
762 Uint2, Uint3, Uint4, Uint5, Uint6, Uint7, Uint8,
763 Uint9, Uint10, Uint11, Uint12, Uint13, Uint14, Uint15, Uint16,
764 Uint17, Uint18, Uint19, Uint20, Uint21, Uint22, Uint23, Uint24,
765 Uint25, Uint26, Uint27, Uint28, Uint29, Uint30, Uint31, Uint32,
766 Uint33, Uint34, Uint35, Uint36, Uint37, Uint38, Uint39, Uint40,
767 Uint41, Uint42, Uint43, Uint44, Uint45, Uint46, Uint47, Uint48,
768 Uint49, Uint50, Uint51, Uint52, Uint53, Uint54, Uint55, Uint56,
769 Uint57, Uint58, Uint59, Uint60, Uint61, Uint62, Uint63, Uint64,
770
771 Int2, Int3, Int4, Int5, Int6, Int7, Int8,
772 Int9, Int10, Int11, Int12, Int13, Int14, Int15, Int16,
773 Int17, Int18, Int19, Int20, Int21, Int22, Int23, Int24,
774 Int25, Int26, Int27, Int28, Int29, Int30, Int31, Int32,
775 Int33, Int34, Int35, Int36, Int37, Int38, Int39, Int40,
776 Int41, Int42, Int43, Int44, Int45, Int46, Int47, Int48,
777 Int49, Int50, Int51, Int52, Int53, Int54, Int55, Int56,
778 Int57, Int58, Int59, Int60, Int61, Int62, Int63, Int64,
779
780 Float16, Float32, Float64,
781
782 Void1, Void2, Void3, Void4, Void5, Void6, Void7, Void8,
783 Void9, Void10, Void11, Void12, Void13, Void14, Void15, Void16,
784 Void17, Void18, Void19, Void20, Void21, Void22, Void23, Void24,
785 Void25, Void26, Void27, Void28, Void29, Void30, Void31, Void32,
786 Void33, Void34, Void35, Void36, Void37, Void38, Void39, Void40,
787 Void41, Void42, Void43, Void44, Void45, Void46, Void47, Void48,
788 Void49, Void50, Void51, Void52, Void53, Void54, Void55, Void56,
789 Void57, Void58, Void59, Void60, Void61, Void62, Void63, Void64,
790}
791
792#[derive(Clone, Debug, PartialEq, Eq)]
793pub enum ParsePrimitiveTypeError {
794 NotPrimitiveType(String),
795}
796
797impl FromStr for PrimitiveType {
798 type Err = ParsePrimitiveTypeError;
799
800 fn from_str(s: &str) -> Result<PrimitiveType, Self::Err> {
801 match s {
802 "bool" => Ok(PrimitiveType::Bool),
803
804 "uint2" => Ok(PrimitiveType::Uint2),
805 "uint3" => Ok(PrimitiveType::Uint3),
806 "uint4" => Ok(PrimitiveType::Uint4),
807 "uint5" => Ok(PrimitiveType::Uint5),
808 "uint6" => Ok(PrimitiveType::Uint6),
809 "uint7" => Ok(PrimitiveType::Uint7),
810 "uint8" => Ok(PrimitiveType::Uint8),
811 "uint9" => Ok(PrimitiveType::Uint9),
812 "uint10" => Ok(PrimitiveType::Uint10),
813 "uint11" => Ok(PrimitiveType::Uint11),
814 "uint12" => Ok(PrimitiveType::Uint12),
815 "uint13" => Ok(PrimitiveType::Uint13),
816 "uint14" => Ok(PrimitiveType::Uint14),
817 "uint15" => Ok(PrimitiveType::Uint15),
818 "uint16" => Ok(PrimitiveType::Uint16),
819 "uint17" => Ok(PrimitiveType::Uint17),
820 "uint18" => Ok(PrimitiveType::Uint18),
821 "uint19" => Ok(PrimitiveType::Uint19),
822 "uint20" => Ok(PrimitiveType::Uint20),
823 "uint21" => Ok(PrimitiveType::Uint21),
824 "uint22" => Ok(PrimitiveType::Uint22),
825 "uint23" => Ok(PrimitiveType::Uint23),
826 "uint24" => Ok(PrimitiveType::Uint24),
827 "uint25" => Ok(PrimitiveType::Uint25),
828 "uint26" => Ok(PrimitiveType::Uint26),
829 "uint27" => Ok(PrimitiveType::Uint27),
830 "uint28" => Ok(PrimitiveType::Uint28),
831 "uint29" => Ok(PrimitiveType::Uint29),
832 "uint30" => Ok(PrimitiveType::Uint30),
833 "uint31" => Ok(PrimitiveType::Uint31),
834 "uint32" => Ok(PrimitiveType::Uint32),
835
836 "uint33" => Ok(PrimitiveType::Uint33),
837 "uint34" => Ok(PrimitiveType::Uint34),
838 "uint35" => Ok(PrimitiveType::Uint35),
839 "uint36" => Ok(PrimitiveType::Uint36),
840 "uint37" => Ok(PrimitiveType::Uint37),
841 "uint38" => Ok(PrimitiveType::Uint38),
842 "uint39" => Ok(PrimitiveType::Uint39),
843 "uint40" => Ok(PrimitiveType::Uint40),
844 "uint41" => Ok(PrimitiveType::Uint41),
845 "uint42" => Ok(PrimitiveType::Uint42),
846 "uint43" => Ok(PrimitiveType::Uint43),
847 "uint44" => Ok(PrimitiveType::Uint44),
848 "uint45" => Ok(PrimitiveType::Uint45),
849 "uint46" => Ok(PrimitiveType::Uint46),
850 "uint47" => Ok(PrimitiveType::Uint47),
851 "uint48" => Ok(PrimitiveType::Uint48),
852 "uint49" => Ok(PrimitiveType::Uint49),
853 "uint50" => Ok(PrimitiveType::Uint50),
854 "uint51" => Ok(PrimitiveType::Uint51),
855 "uint52" => Ok(PrimitiveType::Uint52),
856 "uint53" => Ok(PrimitiveType::Uint53),
857 "uint54" => Ok(PrimitiveType::Uint54),
858 "uint55" => Ok(PrimitiveType::Uint55),
859 "uint56" => Ok(PrimitiveType::Uint56),
860 "uint57" => Ok(PrimitiveType::Uint57),
861 "uint58" => Ok(PrimitiveType::Uint58),
862 "uint59" => Ok(PrimitiveType::Uint59),
863 "uint60" => Ok(PrimitiveType::Uint60),
864 "uint61" => Ok(PrimitiveType::Uint61),
865 "uint62" => Ok(PrimitiveType::Uint62),
866 "uint63" => Ok(PrimitiveType::Uint63),
867 "uint64" => Ok(PrimitiveType::Uint64),
868
869 "int2" => Ok(PrimitiveType::Int2),
870 "int3" => Ok(PrimitiveType::Int3),
871 "int4" => Ok(PrimitiveType::Int4),
872 "int5" => Ok(PrimitiveType::Int5),
873 "int6" => Ok(PrimitiveType::Int6),
874 "int7" => Ok(PrimitiveType::Int7),
875 "int8" => Ok(PrimitiveType::Int8),
876 "int9" => Ok(PrimitiveType::Int9),
877 "int10" => Ok(PrimitiveType::Int10),
878 "int11" => Ok(PrimitiveType::Int11),
879 "int12" => Ok(PrimitiveType::Int12),
880 "int13" => Ok(PrimitiveType::Int13),
881 "int14" => Ok(PrimitiveType::Int14),
882 "int15" => Ok(PrimitiveType::Int15),
883 "int16" => Ok(PrimitiveType::Int16),
884 "int17" => Ok(PrimitiveType::Int17),
885 "int18" => Ok(PrimitiveType::Int18),
886 "int19" => Ok(PrimitiveType::Int19),
887 "int20" => Ok(PrimitiveType::Int20),
888 "int21" => Ok(PrimitiveType::Int21),
889 "int22" => Ok(PrimitiveType::Int22),
890 "int23" => Ok(PrimitiveType::Int23),
891 "int24" => Ok(PrimitiveType::Int24),
892 "int25" => Ok(PrimitiveType::Int25),
893 "int26" => Ok(PrimitiveType::Int26),
894 "int27" => Ok(PrimitiveType::Int27),
895 "int28" => Ok(PrimitiveType::Int28),
896 "int29" => Ok(PrimitiveType::Int29),
897 "int30" => Ok(PrimitiveType::Int30),
898 "int31" => Ok(PrimitiveType::Int31),
899 "int32" => Ok(PrimitiveType::Int32),
900
901 "int33" => Ok(PrimitiveType::Int33),
902 "int34" => Ok(PrimitiveType::Int34),
903 "int35" => Ok(PrimitiveType::Int35),
904 "int36" => Ok(PrimitiveType::Int36),
905 "int37" => Ok(PrimitiveType::Int37),
906 "int38" => Ok(PrimitiveType::Int38),
907 "int39" => Ok(PrimitiveType::Int39),
908 "int40" => Ok(PrimitiveType::Int40),
909 "int41" => Ok(PrimitiveType::Int41),
910 "int42" => Ok(PrimitiveType::Int42),
911 "int43" => Ok(PrimitiveType::Int43),
912 "int44" => Ok(PrimitiveType::Int44),
913 "int45" => Ok(PrimitiveType::Int45),
914 "int46" => Ok(PrimitiveType::Int46),
915 "int47" => Ok(PrimitiveType::Int47),
916 "int48" => Ok(PrimitiveType::Int48),
917 "int49" => Ok(PrimitiveType::Int49),
918 "int50" => Ok(PrimitiveType::Int50),
919 "int51" => Ok(PrimitiveType::Int51),
920 "int52" => Ok(PrimitiveType::Int52),
921 "int53" => Ok(PrimitiveType::Int53),
922 "int54" => Ok(PrimitiveType::Int54),
923 "int55" => Ok(PrimitiveType::Int55),
924 "int56" => Ok(PrimitiveType::Int56),
925 "int57" => Ok(PrimitiveType::Int57),
926 "int58" => Ok(PrimitiveType::Int58),
927 "int59" => Ok(PrimitiveType::Int59),
928 "int60" => Ok(PrimitiveType::Int60),
929 "int61" => Ok(PrimitiveType::Int61),
930 "int62" => Ok(PrimitiveType::Int62),
931 "int63" => Ok(PrimitiveType::Int63),
932 "int64" => Ok(PrimitiveType::Int64),
933
934 "void1" => Ok(PrimitiveType::Void1),
935 "void2" => Ok(PrimitiveType::Void2),
936 "void3" => Ok(PrimitiveType::Void3),
937 "void4" => Ok(PrimitiveType::Void4),
938 "void5" => Ok(PrimitiveType::Void5),
939 "void6" => Ok(PrimitiveType::Void6),
940 "void7" => Ok(PrimitiveType::Void7),
941 "void8" => Ok(PrimitiveType::Void8),
942 "void9" => Ok(PrimitiveType::Void9),
943 "void10" => Ok(PrimitiveType::Void10),
944 "void11" => Ok(PrimitiveType::Void11),
945 "void12" => Ok(PrimitiveType::Void12),
946 "void13" => Ok(PrimitiveType::Void13),
947 "void14" => Ok(PrimitiveType::Void14),
948 "void15" => Ok(PrimitiveType::Void15),
949 "void16" => Ok(PrimitiveType::Void16),
950 "void17" => Ok(PrimitiveType::Void17),
951 "void18" => Ok(PrimitiveType::Void18),
952 "void19" => Ok(PrimitiveType::Void19),
953 "void20" => Ok(PrimitiveType::Void20),
954 "void21" => Ok(PrimitiveType::Void21),
955 "void22" => Ok(PrimitiveType::Void22),
956 "void23" => Ok(PrimitiveType::Void23),
957 "void24" => Ok(PrimitiveType::Void24),
958 "void25" => Ok(PrimitiveType::Void25),
959 "void26" => Ok(PrimitiveType::Void26),
960 "void27" => Ok(PrimitiveType::Void27),
961 "void28" => Ok(PrimitiveType::Void28),
962 "void29" => Ok(PrimitiveType::Void29),
963 "void30" => Ok(PrimitiveType::Void30),
964 "void31" => Ok(PrimitiveType::Void31),
965 "void32" => Ok(PrimitiveType::Void32),
966
967 "void33" => Ok(PrimitiveType::Void33),
968 "void34" => Ok(PrimitiveType::Void34),
969 "void35" => Ok(PrimitiveType::Void35),
970 "void36" => Ok(PrimitiveType::Void36),
971 "void37" => Ok(PrimitiveType::Void37),
972 "void38" => Ok(PrimitiveType::Void38),
973 "void39" => Ok(PrimitiveType::Void39),
974 "void40" => Ok(PrimitiveType::Void40),
975 "void41" => Ok(PrimitiveType::Void41),
976 "void42" => Ok(PrimitiveType::Void42),
977 "void43" => Ok(PrimitiveType::Void43),
978 "void44" => Ok(PrimitiveType::Void44),
979 "void45" => Ok(PrimitiveType::Void45),
980 "void46" => Ok(PrimitiveType::Void46),
981 "void47" => Ok(PrimitiveType::Void47),
982 "void48" => Ok(PrimitiveType::Void48),
983 "void49" => Ok(PrimitiveType::Void49),
984 "void50" => Ok(PrimitiveType::Void50),
985 "void51" => Ok(PrimitiveType::Void51),
986 "void52" => Ok(PrimitiveType::Void52),
987 "void53" => Ok(PrimitiveType::Void53),
988 "void54" => Ok(PrimitiveType::Void54),
989 "void55" => Ok(PrimitiveType::Void55),
990 "void56" => Ok(PrimitiveType::Void56),
991 "void57" => Ok(PrimitiveType::Void57),
992 "void58" => Ok(PrimitiveType::Void58),
993 "void59" => Ok(PrimitiveType::Void59),
994 "void60" => Ok(PrimitiveType::Void60),
995 "void61" => Ok(PrimitiveType::Void61),
996 "void62" => Ok(PrimitiveType::Void62),
997 "void63" => Ok(PrimitiveType::Void63),
998 "void64" => Ok(PrimitiveType::Void64),
999
1000 "float16" => Ok(PrimitiveType::Float16),
1001 "float32" => Ok(PrimitiveType::Float32),
1002 "float64" => Ok(PrimitiveType::Float64),
1003 _ => Err(ParsePrimitiveTypeError::NotPrimitiveType(String::from(s))),
1004 }
1005 }
1006}
1007
1008impl PrimitiveType {
1009 pub fn is_void(&self) -> bool {
1010 match *self {
1011 PrimitiveType::Void1 => true,
1012 PrimitiveType::Void2 => true,
1013 PrimitiveType::Void3 => true,
1014 PrimitiveType::Void4 => true,
1015 PrimitiveType::Void5 => true,
1016 PrimitiveType::Void6 => true,
1017 PrimitiveType::Void7 => true,
1018 PrimitiveType::Void8 => true,
1019 PrimitiveType::Void9 => true,
1020 PrimitiveType::Void10 => true,
1021 PrimitiveType::Void11 => true,
1022 PrimitiveType::Void12 => true,
1023 PrimitiveType::Void13 => true,
1024 PrimitiveType::Void14 => true,
1025 PrimitiveType::Void15 => true,
1026 PrimitiveType::Void16 => true,
1027 PrimitiveType::Void17 => true,
1028 PrimitiveType::Void18 => true,
1029 PrimitiveType::Void19 => true,
1030 PrimitiveType::Void20 => true,
1031 PrimitiveType::Void21 => true,
1032 PrimitiveType::Void22 => true,
1033 PrimitiveType::Void23 => true,
1034 PrimitiveType::Void24 => true,
1035 PrimitiveType::Void25 => true,
1036 PrimitiveType::Void26 => true,
1037 PrimitiveType::Void27 => true,
1038 PrimitiveType::Void28 => true,
1039 PrimitiveType::Void29 => true,
1040 PrimitiveType::Void30 => true,
1041 PrimitiveType::Void31 => true,
1042 PrimitiveType::Void32 => true,
1043 PrimitiveType::Void33 => true,
1044 PrimitiveType::Void34 => true,
1045 PrimitiveType::Void35 => true,
1046 PrimitiveType::Void36 => true,
1047 PrimitiveType::Void37 => true,
1048 PrimitiveType::Void38 => true,
1049 PrimitiveType::Void39 => true,
1050 PrimitiveType::Void40 => true,
1051 PrimitiveType::Void41 => true,
1052 PrimitiveType::Void42 => true,
1053 PrimitiveType::Void43 => true,
1054 PrimitiveType::Void44 => true,
1055 PrimitiveType::Void45 => true,
1056 PrimitiveType::Void46 => true,
1057 PrimitiveType::Void47 => true,
1058 PrimitiveType::Void48 => true,
1059 PrimitiveType::Void49 => true,
1060 PrimitiveType::Void50 => true,
1061 PrimitiveType::Void51 => true,
1062 PrimitiveType::Void52 => true,
1063 PrimitiveType::Void53 => true,
1064 PrimitiveType::Void54 => true,
1065 PrimitiveType::Void55 => true,
1066 PrimitiveType::Void56 => true,
1067 PrimitiveType::Void57 => true,
1068 PrimitiveType::Void58 => true,
1069 PrimitiveType::Void59 => true,
1070 PrimitiveType::Void60 => true,
1071 PrimitiveType::Void61 => true,
1072 PrimitiveType::Void62 => true,
1073 PrimitiveType::Void63 => true,
1074 PrimitiveType::Void64 => true,
1075 _ => false,
1076 }
1077 }
1078}
1079
1080
1081#[cfg(test)]
1082mod tests {
1083 use super::*;
1084
1085 #[test]
1086 fn read_node_status() {
1087 let dsdl = DSDL::read("tests/dsdl/uavcan/protocol/341.NodeStatus.uavcan").unwrap();
1088
1089 assert_eq!(dsdl.files.get(&String::from("NodeStatus")).unwrap(),
1090 &File {
1091 name: FileName {
1092 id: Some(String::from("341")),
1093 namespace: String::from(""),
1094 name: String::from("NodeStatus"),
1095 version: None,
1096 },
1097 definition: TypeDefinition::Message(MessageDefinition(vec!(
1098 Line::Comment(Comment(String::new())),
1099 Line::Comment(Comment(String::from(" Abstract node status information."))),
1100 Line::Comment(Comment(String::new())),
1101 Line::Comment(Comment(String::from(" Any UAVCAN node is required to publish this message periodically."))),
1102 Line::Comment(Comment(String::new())),
1103 Line::Empty,
1104 Line::Comment(Comment(String::from(""))),
1105 Line::Comment(Comment(String::from(" Publication period may vary within these limits."))),
1106 Line::Comment(Comment(String::from(" It is NOT recommended to change it at run time."))),
1107 Line::Comment(Comment(String::new())),
1108 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint16), name: Ident(String::from("MAX_BROADCASTING_PERIOD_MS")), constant: Const::Dec(String::from("1000")) }), None),
1109 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint16), name: Ident(String::from("MIN_BROADCASTING_PERIOD_MS")), constant: Const::Dec(String::from("2")) }), None),
1110 Line::Empty,
1111 Line::Comment(Comment(String::new())),
1112 Line::Comment(Comment(String::from(" If a node fails to publish this message in this amount of time, it should be considered offline."))),
1113 Line::Comment(Comment(String::new())),
1114 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint16), name: Ident(String::from("OFFLINE_TIMEOUT_MS")), constant: Const::Dec(String::from("3000")) }), None),
1115 Line::Empty,
1116 Line::Comment(Comment(String::new())),
1117 Line::Comment(Comment(String::from(" Uptime counter should never overflow."))),
1118 Line::Comment(Comment(String::from(" Other nodes may detect that a remote node has restarted when this value goes backwards."))),
1119 Line::Comment(Comment(String::new())),
1120 Line::Definition(AttributeDefinition::Field(FieldDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint32), array: ArrayInfo::Single, name: Some(Ident(String::from("uptime_sec"))) }), None),
1121 Line::Empty,
1122 Line::Comment(Comment(String::new())),
1123 Line::Comment(Comment(String::from(" Abstract node health."))),
1124 Line::Comment(Comment(String::from(""))),
1125 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint2), name: Ident(String::from("HEALTH_OK")), constant: Const::Dec(String::from("0")) }), Some(Comment(String::from(" The node is functioning properly.")))),
1126 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint2), name: Ident(String::from("HEALTH_WARNING")), constant: Const::Dec(String::from("1")) }), Some(Comment(String::from(" A critical parameter went out of range or the node encountered a minor failure.")))),
1127 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint2), name: Ident(String::from("HEALTH_ERROR")), constant: Const::Dec(String::from("2")) }), Some(Comment(String::from(" The node encountered a major failure.")))),
1128 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint2), name: Ident(String::from("HEALTH_CRITICAL")), constant: Const::Dec(String::from("3")) }), Some(Comment(String::from(" The node suffered a fatal malfunction.")))),
1129 Line::Definition(AttributeDefinition::Field(FieldDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint2), array: ArrayInfo::Single, name: Some(Ident(String::from("health"))) }), None),
1130 Line::Empty,
1131 Line::Comment(Comment(String::from(""))),
1132 Line::Comment(Comment(String::from(" Current mode."))),
1133 Line::Comment(Comment(String::new())),
1134 Line::Comment(Comment(String::from(" Mode OFFLINE can be actually reported by the node to explicitly inform other network"))),
1135 Line::Comment(Comment(String::from(" participants that the sending node is about to shutdown. In this case other nodes will not"))),
1136 Line::Comment(Comment(String::from(" have to wait OFFLINE_TIMEOUT_MS before they detect that the node is no longer available."))),
1137 Line::Comment(Comment(String::new())),
1138 Line::Comment(Comment(String::from(" Reserved values can be used in future revisions of the specification."))),
1139 Line::Comment(Comment(String::new())),
1140 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), name: Ident(String::from("MODE_OPERATIONAL")), constant: Const::Dec(String::from("0")) }), Some(Comment(String::from(" Normal operating mode.")))),
1141 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), name: Ident(String::from("MODE_INITIALIZATION")), constant: Const::Dec(String::from("1")) }), Some(Comment(String::from(" Initialization is in progress; this mode is entered immediately after startup.")))),
1142 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), name: Ident(String::from("MODE_MAINTENANCE")), constant: Const::Dec(String::from("2")) }), Some(Comment(String::from(" E.g. calibration, the bootloader is running, etc.")))),
1143 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), name: Ident(String::from("MODE_SOFTWARE_UPDATE")), constant: Const::Dec(String::from("3")) }), Some(Comment(String::from(" New software/firmware is being loaded.")))),
1144 Line::Definition(AttributeDefinition::Const(ConstDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), name: Ident(String::from("MODE_OFFLINE")), constant: Const::Dec(String::from("7")) }), Some(Comment(String::from(" The node is no longer available.")))),
1145 Line::Definition(AttributeDefinition::Field(FieldDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), array: ArrayInfo::Single, name: Some(Ident(String::from("mode"))) }), None),
1146 Line::Empty,
1147 Line::Comment(Comment(String::new())),
1148 Line::Comment(Comment(String::from(" Not used currently, keep zero when publishing, ignore when receiving."))),
1149 Line::Comment(Comment(String::new())),
1150 Line::Definition(AttributeDefinition::Field(FieldDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint3), array: ArrayInfo::Single, name: Some(Ident(String::from("sub_mode"))) }), None),
1151 Line::Empty,
1152 Line::Comment(Comment(String::new())),
1153 Line::Comment(Comment(String::from(" Optional, vendor-specific node status code, e.g. a fault code or a status bitmask."))),
1154 Line::Comment(Comment(String::new())),
1155 Line::Definition(AttributeDefinition::Field(FieldDefinition { cast_mode: None, field_type: Ty::Primitive(PrimitiveType::Uint16), array: ArrayInfo::Single, name: Some(Ident(String::from("vendor_specific_status_code"))) }), None),
1156 ))),}
1157 );
1158 }
1159}
1160