1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::backtrace::Backtrace;
use crate::{FieldInfo, MessagePath, Msg};
/// Enumeration of all errors that can be returned.
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// Message doesn't have a valid format.
///
/// Message names must follow the `package_name/MessageName` format.
///
/// Packages must follow [REP 144](https://www.ros.org/reps/rep-0144.html) rules.
#[error("message path `{name}` is invalid, {reason}")]
InvalidMessagePath {
/// Full name of the message we are trying to parse.
name: String,
/// Reason for the failure.
reason: String,
},
/// Field in the `msg` or `srv` file has a name that doesn't fit any data type category.
#[error("data type `{name}` is invalid, {reason}")]
UnsupportedDataType {
/// Full name of the data type we are trying to parse.
name: String,
/// Reason for the failure.
reason: String,
},
/// The `msg` or `srv` file being parsed has invalid content.
#[error("bad content in message: `{0}`")]
BadMessageContent(String),
/// Certain operations on a `msg` or `srv` file require first handling all messages it depends upon.
///
/// For example, to calculate an MD5 sum for a message, you first need to calculate it for
/// all messages it depends upon, and passing them into the calculation call.
#[error("message dependency missing: {package}/{name}")]
MessageDependencyMissing {
/// Package that the message is located in.
package: String,
/// Name of the missing message.
name: String,
},
/// Passed in constant value is not parsable as its data type.
#[error("bad constant value `{value}` of type {datatype} in field {name}")]
BadConstant {
/// Name of the constant.
name: String,
/// Type of the invalid value.
datatype: String,
/// The invalid value provided.
value: String,
},
/// The provided message data is either invalid or unsupported.
///
/// This can happen if an incorrect message definition was used to decode a message.
#[error("failed to decode field:\n\n\"{field}\"\n\nGot `{err}` at byte {offset}\n\n{msg}")]
DecodingError {
/// The associated message definition that was used to decode the data
msg: Msg,
/// The field that the decoder failed at
field: FieldInfo,
/// The byte offset the deocder failed at
offset: usize,
/// The underlying io error
err: std::io::Error,
},
}
impl From<std::io::Error> for Error {
fn from(value: std::io::Error) -> Self {
let trace = Backtrace::force_capture();
// TODO!: this probably isn't wanted behaviour but left in for debugging purposes for now
eprintln!("{}", trace);
let default_msg = Msg::new(
MessagePath::new("placeholder", "PlaceholderMessage").unwrap(),
"",
)
.unwrap();
let default_field =
FieldInfo::new("uint8", "error_placeholder_field", crate::FieldCase::Unit).unwrap();
Error::DecodingError {
msg: default_msg,
field: default_field,
offset: 0,
err: value,
}
}
}
/// Convenience type for shorter return value syntax of this crate's errors.
pub type Result<T> = std::result::Result<T, Error>;