use crate::{
parse::{parse_ros_message_file, ParsedMessageFile},
Error, Package,
};
use std::path::{Path, PathBuf};
#[derive(Clone, Debug)]
pub struct ParsedServiceFile {
pub name: String,
pub package: String,
pub request_type: ParsedMessageFile,
pub response_type: ParsedMessageFile,
pub source: String,
pub path: PathBuf,
}
impl ParsedServiceFile {
pub fn get_full_name(&self) -> String {
format!("{}/{}", self.package, self.name)
}
pub fn get_ros2_full_name(&self) -> String {
format!("{}/srv/{}", self.package, self.name)
}
pub fn get_ros2_dds_type_name(&self) -> String {
format!("{}::srv::dds_::{}_", self.package, self.name)
}
}
pub fn parse_ros_service_file(
data: &str,
name: &str,
package: &Package,
path: &Path,
) -> Result<ParsedServiceFile, Error> {
let mut dash_line_number = None;
for (line_num, line) in data.lines().enumerate() {
match (line.find("---"), line.find('#')) {
(Some(dash_idx), Some(cmt_idx)) => {
if dash_idx < cmt_idx {
dash_line_number = Some(line_num);
break;
}
}
(Some(_), None) => {
dash_line_number = Some(line_num);
break;
}
_ => continue,
}
}
let str_accumulator = |mut acc: String, line: &str| -> String {
acc.push_str(line);
acc.push('\n');
acc
};
let dash_line_number = dash_line_number.ok_or(Error::new(format!(
"Failed to find delimiter line '---' in {}/{name}",
&package.name
)))?;
let request_str = data
.lines()
.take(dash_line_number)
.fold(String::new(), str_accumulator);
let response_str = data
.lines()
.skip(dash_line_number + 1)
.fold(String::new(), str_accumulator);
Ok(ParsedServiceFile {
name: name.to_owned(),
package: package.name.clone(),
request_type: parse_ros_message_file(
&request_str,
format!("{name}Request").as_str(),
package,
path,
)?,
response_type: parse_ros_message_file(
&response_str,
format!("{name}Response").as_str(),
package,
path,
)?,
source: data.to_owned(),
path: path.to_owned(),
})
}