roslibrust_codegen/parse/
msg.rs1use crate::parse::{parse_constant_field, parse_field, strip_comments};
2use crate::Error;
3use crate::{ConstantInfo, FieldInfo, Package, RosVersion};
4use std::path::{Path, PathBuf};
5
6#[derive(Clone, PartialEq, Debug)]
8pub struct ParsedMessageFile {
9 pub name: String,
10 pub package: String,
11 pub fields: Vec<FieldInfo>,
12 pub constants: Vec<ConstantInfo>,
13 pub version: Option<RosVersion>,
14 pub source: String,
16 pub path: PathBuf,
18}
19
20impl ParsedMessageFile {
21 pub fn has_header(&self) -> bool {
22 self.fields.iter().any(|field| {
23 field.field_type.field_type.as_str() == "Header"
24 && (field.field_type.package_name.is_none()
25 || field.field_type.package_name == Some(String::from("std_msgs")))
26 })
27 }
28
29 pub fn get_full_name(&self) -> String {
30 format!("{}/{}", self.package, self.name)
31 }
32}
33
34pub fn parse_ros_message_file(
40 data: &str,
41 name: &str,
42 package: &Package,
43 path: &Path,
44) -> Result<ParsedMessageFile, Error> {
45 let mut fields = vec![];
46 let mut constants = vec![];
47
48 for line in data.lines() {
49 let line = strip_comments(line).trim();
50 if line.is_empty() {
51 continue;
53 }
54 let sep = line.find(' ').ok_or(
56 Error::new(
57 format!("Found an invalid ros field line, no space delinting type from name: {line} in {}\n{data}",
58 path.display())
59 )
60 )?;
61 let equal_after_sep = line[sep..].find('=');
62 if equal_after_sep.is_some() {
63 constants.push(parse_constant_field(line, package)?)
65 } else {
66 fields.push(parse_field(line, package, name)?);
68 }
69 }
70 Ok(ParsedMessageFile {
71 fields,
72 constants,
73 name: name.to_owned(),
74 package: package.name.clone(),
75 version: package.version,
76 source: data.to_owned(),
77 path: path.to_owned(),
78 })
79}