r2r/
error.rs

1#![allow(non_camel_case_types)]
2use r2r_actions::*;
3use r2r_rcl::*;
4use thiserror::Error;
5
6/// r2r Result type.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// r2r Error type.
10///
11/// These values are mostly copied straight from the RCL headers, but
12/// some are specific to r2r, such as `GoalCancelRejected` which does
13/// not have an analogue in the rcl.
14#[derive(Error, Clone, Debug)]
15pub enum Error {
16    #[error("RCL_RET_OK")]
17    RCL_RET_OK,
18    #[error("RCL_RET_ERROR")]
19    RCL_RET_ERROR,
20    #[error("RCL_RET_TIMEOUT")]
21    RCL_RET_TIMEOUT,
22    #[error("RCL_RET_BAD_ALLOC")]
23    RCL_RET_BAD_ALLOC,
24    #[error("RCL_RET_INVALID_ARGUMENT")]
25    RCL_RET_INVALID_ARGUMENT,
26    #[error("RCL_RET_UNSUPPORTED")]
27    RCL_RET_UNSUPPORTED,
28    #[error("RCL_RET_ALREADY_INIT")]
29    RCL_RET_ALREADY_INIT,
30    #[error("RCL_RET_NOT_INIT")]
31    RCL_RET_NOT_INIT,
32    #[error("RCL_RET_MISMATCHED_RMW_ID")]
33    RCL_RET_MISMATCHED_RMW_ID,
34    #[error("RCL_RET_TOPIC_NAME_INVALID")]
35    RCL_RET_TOPIC_NAME_INVALID,
36    #[error("RCL_RET_SERVICE_NAME_INVALID")]
37    RCL_RET_SERVICE_NAME_INVALID,
38    #[error("RCL_RET_UNKNOWN_SUBSTITUTION")]
39    RCL_RET_UNKNOWN_SUBSTITUTION,
40    #[error("RCL_RET_ALREADY_SHUTDOWN")]
41    RCL_RET_ALREADY_SHUTDOWN,
42    #[error("RCL_RET_NODE_INVALID")]
43    RCL_RET_NODE_INVALID,
44    #[error("RCL_RET_NODE_INVALID_NAME")]
45    RCL_RET_NODE_INVALID_NAME,
46    #[error("RCL_RET_NODE_INVALID_NAMESPACE")]
47    RCL_RET_NODE_INVALID_NAMESPACE,
48    #[error("RCL_RET_PUBLISHER_INVALID")]
49    RCL_RET_PUBLISHER_INVALID,
50    #[error("RCL_RET_SUBSCRIPTION_INVALID")]
51    RCL_RET_SUBSCRIPTION_INVALID,
52    #[error("RCL_RET_SUBSCRIPTION_TAKE_FAILED")]
53    RCL_RET_SUBSCRIPTION_TAKE_FAILED,
54    #[error("RCL_RET_CLIENT_INVALID")]
55    RCL_RET_CLIENT_INVALID,
56    #[error("RCL_RET_CLIENT_TAKE_FAILED")]
57    RCL_RET_CLIENT_TAKE_FAILED,
58    #[error("RCL_RET_SERVICE_INVALID")]
59    RCL_RET_SERVICE_INVALID,
60    #[error("RCL_RET_SERVICE_TAKE_FAILED")]
61    RCL_RET_SERVICE_TAKE_FAILED,
62    #[error("RCL_RET_TIMER_INVALID")]
63    RCL_RET_TIMER_INVALID,
64    #[error("RCL_RET_TIMER_CANCELED")]
65    RCL_RET_TIMER_CANCELED,
66    #[error("RCL_RET_WAIT_SET_INVALID")]
67    RCL_RET_WAIT_SET_INVALID,
68    #[error("RCL_RET_WAIT_SET_EMPTY")]
69    RCL_RET_WAIT_SET_EMPTY,
70    #[error("RCL_RET_WAIT_SET_FULL")]
71    RCL_RET_WAIT_SET_FULL,
72    #[error("RCL_RET_INVALID_REMAP_RULE")]
73    RCL_RET_INVALID_REMAP_RULE,
74    #[error("RCL_RET_WRONG_LEXEME")]
75    RCL_RET_WRONG_LEXEME,
76    #[error("RCL_RET_INVALID_PARAM_RULE")]
77    RCL_RET_INVALID_PARAM_RULE,
78    #[error("RCL_RET_INVALID_LOG_LEVEL_RULE")]
79    RCL_RET_INVALID_LOG_LEVEL_RULE,
80    #[error("RCL_RET_EVENT_INVALID")]
81    RCL_RET_EVENT_INVALID,
82    #[error("RCL_RET_EVENT_TAKE_FAILED")]
83    RCL_RET_EVENT_TAKE_FAILED,
84
85    // Our own errors
86    #[error("Clock type is not RosTime")]
87    ClockTypeNotRosTime,
88    #[error("No typesupport built for the message type: {}", msgtype)]
89    InvalidMessageType { msgtype: String },
90    #[error("Serde error: {}", err)]
91    SerdeError { err: String },
92
93    // action errors.
94    #[error("RCL_RET_ACTION_NAME_INVALID")]
95    RCL_RET_ACTION_NAME_INVALID,
96    #[error("RCL_RET_ACTION_GOAL_ACCEPTED")]
97    RCL_RET_ACTION_GOAL_ACCEPTED,
98    #[error("RCL_RET_ACTION_GOAL_REJECTED")]
99    RCL_RET_ACTION_GOAL_REJECTED,
100    #[error("RCL_RET_ACTION_CLIENT_INVALID")]
101    RCL_RET_ACTION_CLIENT_INVALID,
102    #[error("RCL_RET_ACTION_CLIENT_TAKE_FAILED")]
103    RCL_RET_ACTION_CLIENT_TAKE_FAILED,
104    #[error("RCL_RET_ACTION_SERVER_INVALID")]
105    RCL_RET_ACTION_SERVER_INVALID,
106    #[error("RCL_RET_ACTION_SERVER_TAKE_FAILED")]
107    RCL_RET_ACTION_SERVER_TAKE_FAILED,
108    #[error("RCL_RET_ACTION_GOAL_HANDLE_INVALID")]
109    RCL_RET_ACTION_GOAL_HANDLE_INVALID,
110    #[error("RCL_RET_ACTION_GOAL_EVENT_INVALID")]
111    RCL_RET_ACTION_GOAL_EVENT_INVALID,
112
113    #[error("Goal cancel request rejected by server.")]
114    GoalCancelRejected,
115
116    #[error("Unknown goal id.")]
117    GoalCancelUnknownGoalID,
118
119    #[error("Goal already in a terminal state.")]
120    GoalCancelAlreadyTerminated,
121
122    #[error("Invalid parameter name: {name}")]
123    InvalidParameterName { name: String },
124
125    #[error("Invalid type for parameter {name} (should be {ty})")]
126    InvalidParameterType { name: String, ty: &'static str },
127
128    #[error("Parameter {name} conversion failed: {msg}")]
129    ParameterValueConv { name: String, msg: String },
130
131    #[error(
132        "Parameter {name} was expected to be of type {expected_type} but was of type {actual_type}"
133    )]
134    ParameterWrongType {
135        name: String,
136        expected_type: &'static str,
137        actual_type: &'static str,
138    },
139}
140
141impl Error {
142    pub fn from_rcl_error(e: i32) -> Self {
143        let e = e as u32;
144        match e {
145            _ if e == RCL_RET_OK => Error::RCL_RET_OK,
146            _ if e == RCL_RET_ERROR => Error::RCL_RET_ERROR,
147            _ if e == RCL_RET_TIMEOUT => Error::RCL_RET_TIMEOUT,
148            _ if e == RCL_RET_BAD_ALLOC => Error::RCL_RET_BAD_ALLOC,
149            _ if e == RCL_RET_INVALID_ARGUMENT => Error::RCL_RET_INVALID_ARGUMENT,
150            _ if e == RCL_RET_UNSUPPORTED => Error::RCL_RET_UNSUPPORTED,
151            _ if e == RCL_RET_ALREADY_INIT => Error::RCL_RET_ALREADY_INIT,
152            _ if e == RCL_RET_NOT_INIT => Error::RCL_RET_NOT_INIT,
153            _ if e == RCL_RET_MISMATCHED_RMW_ID => Error::RCL_RET_MISMATCHED_RMW_ID,
154            _ if e == RCL_RET_TOPIC_NAME_INVALID => Error::RCL_RET_TOPIC_NAME_INVALID,
155            _ if e == RCL_RET_SERVICE_NAME_INVALID => Error::RCL_RET_SERVICE_NAME_INVALID,
156            _ if e == RCL_RET_UNKNOWN_SUBSTITUTION => Error::RCL_RET_UNKNOWN_SUBSTITUTION,
157            _ if e == RCL_RET_ALREADY_SHUTDOWN => Error::RCL_RET_ALREADY_SHUTDOWN,
158            _ if e == RCL_RET_NODE_INVALID => Error::RCL_RET_NODE_INVALID,
159            _ if e == RCL_RET_NODE_INVALID_NAME => Error::RCL_RET_NODE_INVALID_NAME,
160            _ if e == RCL_RET_NODE_INVALID_NAMESPACE => Error::RCL_RET_NODE_INVALID_NAMESPACE,
161            _ if e == RCL_RET_PUBLISHER_INVALID => Error::RCL_RET_PUBLISHER_INVALID,
162            _ if e == RCL_RET_SUBSCRIPTION_INVALID => Error::RCL_RET_SUBSCRIPTION_INVALID,
163            _ if e == RCL_RET_SUBSCRIPTION_TAKE_FAILED => Error::RCL_RET_SUBSCRIPTION_TAKE_FAILED,
164            _ if e == RCL_RET_CLIENT_INVALID => Error::RCL_RET_CLIENT_INVALID,
165            _ if e == RCL_RET_CLIENT_TAKE_FAILED => Error::RCL_RET_CLIENT_TAKE_FAILED,
166            _ if e == RCL_RET_SERVICE_INVALID => Error::RCL_RET_SERVICE_INVALID,
167            _ if e == RCL_RET_SERVICE_TAKE_FAILED => Error::RCL_RET_SERVICE_TAKE_FAILED,
168            _ if e == RCL_RET_TIMER_INVALID => Error::RCL_RET_TIMER_INVALID,
169            _ if e == RCL_RET_TIMER_CANCELED => Error::RCL_RET_TIMER_CANCELED,
170            _ if e == RCL_RET_WAIT_SET_INVALID => Error::RCL_RET_WAIT_SET_INVALID,
171            _ if e == RCL_RET_WAIT_SET_EMPTY => Error::RCL_RET_WAIT_SET_EMPTY,
172            _ if e == RCL_RET_WAIT_SET_FULL => Error::RCL_RET_WAIT_SET_FULL,
173            _ if e == RCL_RET_INVALID_REMAP_RULE => Error::RCL_RET_INVALID_REMAP_RULE,
174            _ if e == RCL_RET_WRONG_LEXEME => Error::RCL_RET_WRONG_LEXEME,
175            _ if e == RCL_RET_INVALID_PARAM_RULE => Error::RCL_RET_INVALID_PARAM_RULE,
176            _ if e == RCL_RET_INVALID_LOG_LEVEL_RULE => Error::RCL_RET_INVALID_LOG_LEVEL_RULE,
177            _ if e == RCL_RET_EVENT_INVALID => Error::RCL_RET_EVENT_INVALID,
178            _ if e == RCL_RET_EVENT_TAKE_FAILED => Error::RCL_RET_EVENT_TAKE_FAILED,
179            _ if e == RCL_RET_ACTION_NAME_INVALID => Error::RCL_RET_ACTION_NAME_INVALID,
180            _ if e == RCL_RET_ACTION_GOAL_ACCEPTED => Error::RCL_RET_ACTION_GOAL_ACCEPTED,
181            _ if e == RCL_RET_ACTION_GOAL_REJECTED => Error::RCL_RET_ACTION_GOAL_REJECTED,
182            _ if e == RCL_RET_ACTION_CLIENT_INVALID => Error::RCL_RET_ACTION_CLIENT_INVALID,
183            _ if e == RCL_RET_ACTION_CLIENT_TAKE_FAILED => Error::RCL_RET_ACTION_CLIENT_TAKE_FAILED,
184            _ if e == RCL_RET_ACTION_SERVER_INVALID => Error::RCL_RET_ACTION_SERVER_INVALID,
185            _ if e == RCL_RET_ACTION_SERVER_TAKE_FAILED => Error::RCL_RET_ACTION_SERVER_TAKE_FAILED,
186            _ if e == RCL_RET_ACTION_GOAL_HANDLE_INVALID => {
187                Error::RCL_RET_ACTION_GOAL_HANDLE_INVALID
188            }
189            _ if e == RCL_RET_ACTION_GOAL_EVENT_INVALID => Error::RCL_RET_ACTION_GOAL_EVENT_INVALID,
190            _ => panic!("TODO: add error code {}", e),
191        }
192    }
193
194    /// Internal function used by code derived for the RosParams trait.
195    pub fn update_param_name(self, param_name: &str) -> Error {
196        match self {
197            Error::InvalidParameterName { name: _ } => Error::InvalidParameterName {
198                name: param_name.to_string(),
199            },
200            Error::InvalidParameterType { name: _, ty } => Error::InvalidParameterType {
201                name: param_name.to_string(),
202                ty,
203            },
204            Error::ParameterValueConv { name: _, msg } => Error::ParameterValueConv {
205                name: param_name.to_string(),
206                msg,
207            },
208            _ => self,
209        }
210    }
211}