Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d62957b
commit ff91ad7
Showing
42 changed files
with
1,408 additions
and
1,135 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
use crate::{Error, MessagePath, Result}; | ||
use std::collections::HashMap; | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub enum DataType { | ||
Bool, | ||
I8(bool), | ||
I16, | ||
I32, | ||
I64, | ||
U8(bool), | ||
U16, | ||
U32, | ||
U64, | ||
F32, | ||
F64, | ||
String, | ||
Time, | ||
Duration, | ||
LocalStruct(String), | ||
RemoteStruct(MessagePath), | ||
} | ||
|
||
const BOOL_KEY: &str = "bool"; | ||
const INT8_KEY: &str = "int8"; | ||
const BYTE_KEY: &str = "byte"; | ||
const INT16_KEY: &str = "int16"; | ||
const INT32_KEY: &str = "int32"; | ||
const INT64_KEY: &str = "int64"; | ||
const UINT8_KEY: &str = "uint8"; | ||
const CHAR_KEY: &str = "char"; | ||
const UINT16_KEY: &str = "uint16"; | ||
const UINT32_KEY: &str = "uint32"; | ||
const UINT64_KEY: &str = "uint64"; | ||
const FLOAT32_KEY: &str = "float32"; | ||
const FLOAT64_KEY: &str = "float64"; | ||
const STRING_KEY: &str = "string"; | ||
const TIME_KEY: &str = "time"; | ||
const DURATION_KEY: &str = "duration"; | ||
|
||
impl DataType { | ||
pub fn parse(datatype: &str) -> Result<Self> { | ||
Ok(match datatype { | ||
BOOL_KEY => DataType::Bool, | ||
INT8_KEY => DataType::I8(true), | ||
BYTE_KEY => DataType::I8(false), | ||
INT16_KEY => DataType::I16, | ||
INT32_KEY => DataType::I32, | ||
INT64_KEY => DataType::I64, | ||
UINT8_KEY => DataType::U8(true), | ||
CHAR_KEY => DataType::U8(false), | ||
UINT16_KEY => DataType::U16, | ||
UINT32_KEY => DataType::U32, | ||
UINT64_KEY => DataType::U64, | ||
FLOAT32_KEY => DataType::F32, | ||
FLOAT64_KEY => DataType::F64, | ||
STRING_KEY => DataType::String, | ||
TIME_KEY => DataType::Time, | ||
DURATION_KEY => DataType::Duration, | ||
"Header" => DataType::RemoteStruct(MessagePath::new("std_msgs", "Header")?), | ||
_ => { | ||
let parts = datatype.splitn(2, '/').collect::<Vec<&str>>(); | ||
match parts[..] { | ||
[name] => DataType::LocalStruct(name.into()), | ||
[package, name] => DataType::RemoteStruct(MessagePath::new(package, name)?), | ||
_ => { | ||
return Err(Error::UnsupportedDataType { | ||
name: datatype.into(), | ||
reason: "string needs to be in `name` or `package/name` format".into(), | ||
}) | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
|
||
pub fn is_builtin(&self) -> bool { | ||
match *self { | ||
DataType::Bool | ||
| DataType::I8(_) | ||
| DataType::I16 | ||
| DataType::I32 | ||
| DataType::I64 | ||
| DataType::U8(_) | ||
| DataType::U16 | ||
| DataType::U32 | ||
| DataType::U64 | ||
| DataType::F32 | ||
| DataType::F64 | ||
| DataType::String | ||
| DataType::Time | ||
| DataType::Duration => true, | ||
DataType::LocalStruct(_) | DataType::RemoteStruct(_) => false, | ||
} | ||
} | ||
|
||
pub fn md5_string( | ||
&self, | ||
package: &str, | ||
hashes: &HashMap<MessagePath, String>, | ||
) -> Result<String> { | ||
Ok(match *self { | ||
DataType::Bool => BOOL_KEY, | ||
DataType::I8(true) => INT8_KEY, | ||
DataType::I8(false) => BYTE_KEY, | ||
DataType::I16 => INT16_KEY, | ||
DataType::I32 => INT32_KEY, | ||
DataType::I64 => INT64_KEY, | ||
DataType::U8(true) => UINT8_KEY, | ||
DataType::U8(false) => CHAR_KEY, | ||
DataType::U16 => UINT16_KEY, | ||
DataType::U32 => UINT32_KEY, | ||
DataType::U64 => UINT64_KEY, | ||
DataType::F32 => FLOAT32_KEY, | ||
DataType::F64 => FLOAT64_KEY, | ||
DataType::String => STRING_KEY, | ||
DataType::Time => TIME_KEY, | ||
DataType::Duration => DURATION_KEY, | ||
DataType::LocalStruct(ref name) => hashes | ||
.get(&MessagePath::new(package, name)?) | ||
.ok_or_else(|| Error::MessageDependencyMissing { | ||
package: package.into(), | ||
name: name.into(), | ||
})? | ||
.as_str(), | ||
DataType::RemoteStruct(ref message) => hashes | ||
.get(message) | ||
.ok_or_else(|| Error::MessageDependencyMissing { | ||
package: message.package().into(), | ||
name: message.name().into(), | ||
})? | ||
.as_str(), | ||
} | ||
.into()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use crate::{DataType, MessagePath, Result}; | ||
use std::collections::HashMap; | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub enum FieldCase { | ||
Unit, | ||
Vector, | ||
Array(usize), | ||
Const(String), | ||
} | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub struct FieldInfo { | ||
pub datatype: DataType, | ||
pub name: String, | ||
pub case: FieldCase, | ||
} | ||
|
||
impl FieldInfo { | ||
pub fn new(datatype: &str, name: &str, case: FieldCase) -> Result<FieldInfo> { | ||
Ok(FieldInfo { | ||
datatype: DataType::parse(datatype)?, | ||
name: name.into(), | ||
case, | ||
}) | ||
} | ||
|
||
pub fn is_constant(&self) -> bool { | ||
matches!(self.case, FieldCase::Const(..)) | ||
} | ||
|
||
pub fn md5_string( | ||
&self, | ||
package: &str, | ||
hashes: &HashMap<MessagePath, String>, | ||
) -> Result<String> { | ||
let datatype = self.datatype.md5_string(package, hashes)?; | ||
Ok(match (self.datatype.is_builtin(), &self.case) { | ||
(_, &FieldCase::Const(ref v)) => format!("{} {}={}", datatype, self.name, v), | ||
(false, _) | (_, &FieldCase::Unit) => format!("{} {}", datatype, self.name), | ||
(true, &FieldCase::Vector) => format!("{}[] {}", datatype, self.name), | ||
(true, &FieldCase::Array(l)) => format!("{}[{}] {}", datatype, l, self.name), | ||
}) | ||
} | ||
|
||
pub fn is_header(&self) -> bool { | ||
if self.case != FieldCase::Unit || self.name != "header" { | ||
return false; | ||
} | ||
match &self.datatype { | ||
DataType::RemoteStruct(msg) => msg.package() == "std_msgs" && msg.name() == "Header", | ||
_ => false, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,16 @@ | ||
mod data_type; | ||
mod error; | ||
mod field_info; | ||
mod message_path; | ||
mod msg; | ||
mod parse_msg; | ||
mod srv; | ||
#[cfg(test)] | ||
mod tests; | ||
|
||
pub use data_type::DataType; | ||
pub use error::{Error, Result}; | ||
pub use field_info::{FieldCase, FieldInfo}; | ||
pub use message_path::MessagePath; | ||
pub use msg::Msg; | ||
pub use srv::Srv; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use std::collections::HashMap; | ||
|
||
use crate::{parse_msg::match_lines, DataType, FieldInfo, MessagePath, Result}; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct Msg { | ||
pub path: MessagePath, | ||
pub fields: Vec<FieldInfo>, | ||
pub source: String, | ||
} | ||
|
||
impl Msg { | ||
pub fn new(path: MessagePath, source: &str) -> Result<Msg> { | ||
let fields = match_lines(source)?; | ||
Ok(Msg { | ||
path, | ||
fields, | ||
source: source.trim().into(), | ||
}) | ||
} | ||
|
||
pub fn get_type(&self) -> String { | ||
format!("{}/{}", self.path.package(), self.path.name()) | ||
} | ||
|
||
pub fn dependencies(&self) -> Result<Vec<MessagePath>> { | ||
self.fields | ||
.iter() | ||
.filter_map(|field| match field.datatype { | ||
DataType::LocalStruct(ref name) => { | ||
Some(MessagePath::new(self.path.package(), name)) | ||
} | ||
DataType::RemoteStruct(ref message) => Some(Ok(message.clone())), | ||
_ => None, | ||
}) | ||
.collect() | ||
} | ||
|
||
#[cfg(test)] | ||
pub fn calculate_md5(&self, hashes: &HashMap<MessagePath, String>) -> Result<String> { | ||
use md5::{Digest, Md5}; | ||
|
||
let mut hasher = Md5::new(); | ||
hasher.update(&self.get_md5_representation(hashes)?); | ||
Ok(hex::encode(hasher.finalize())) | ||
} | ||
|
||
pub fn get_md5_representation(&self, hashes: &HashMap<MessagePath, String>) -> Result<String> { | ||
let constants = self | ||
.fields | ||
.iter() | ||
.filter(|v| v.is_constant()) | ||
.map(|v| v.md5_string(self.path.package(), hashes)) | ||
.collect::<Result<Vec<String>>>()?; | ||
let fields = self | ||
.fields | ||
.iter() | ||
.filter(|v| !v.is_constant()) | ||
.map(|v| v.md5_string(self.path.package(), hashes)) | ||
.collect::<Result<Vec<String>>>()?; | ||
let representation = constants | ||
.into_iter() | ||
.chain(fields) | ||
.collect::<Vec<_>>() | ||
.join("\n"); | ||
Ok(representation) | ||
} | ||
|
||
pub fn has_header(&self) -> bool { | ||
self.fields.iter().any(FieldInfo::is_header) | ||
} | ||
} |
Oops, something went wrong.