Skip to content

Commit 5f3909c

Browse files
adrian-kongJason Mobarakpcrumleysilverjam
authored
Parse error falls back to Invalid (#1312)
# Description This PR makes it so that if at any point in the parsing of sbp messages the parsing fails, it has the option of falling back to an InvalidMessage which can then be written to the output. The way this PR acheives this goal is through some major breaking changes. The idea is that when errors are thrown throughout the process, we store all that local information in the constructed error. That way, choosing how to write the output can become as simple as matching on the thrown error and then basically writing `SbpMessage::from(error)`. This enables us to keep the previous behavior of skipping errors or returning on errors simply by refusing to handle the errors. `sbp2json`, `json2sbp` & `json2json` now have a new optional arg `--error_handler` which allows the following options `skip`, `return` or `ToInvalid`. that skip and return are the equivalent of the false and true passed to fatal-errors arg which as been removed. Care was taken to remove some panics in the parsing of SBP which could cause some types of invalid messages to be lost. Finally this PR does not do things like try to recover from being passed in malformed json or given an I/O error. In case of those error, if the `ToInvalid` option is passed, the code will panic. Some issues with this PR -- 1) it has a lot of breaking changes, and it kind of does a lot. Just want to make sure people like the direction i went in. 2) the lack of recovering from malformed json means I left json2json to panic if given ToInvalid as an option. 3) It has no unit tests. I wanted some eyes on this code and proposed solution before totally getting it over the finish line. # JIRA Reference https://swift-nav.atlassian.net/browse/DEVINFRA-1220 --------- Co-authored-by: Jason Mobarak <[email protected]> Co-authored-by: Patrick Crumley <[email protected]> Co-authored-by: Patrick Crumley <[email protected]> Co-authored-by: Jason Mobarak <[email protected]>
1 parent ac9e865 commit 5f3909c

File tree

156 files changed

+6485
-4241
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

156 files changed

+6485
-4241
lines changed

generator/sbpg/targets/resources/rust/sbp_messages_mod.rs

Lines changed: 155 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,27 @@
99
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
1010
//! SBP message definitions.
1111
12+
//****************************************************************************
13+
// Automatically generated from
14+
// 'generator/sbpg/targets/resources/rust/sbp_messages_mod.rs'
15+
//
16+
// Please do not hand edit!
17+
//****************************************************************************/
18+
19+
1220
((*- for m in mods *))
1321
pub mod (((m)));
1422
((*- endfor *))
1523
pub mod unknown;
24+
pub mod invalid;
1625

1726
((*- for m in msgs *))
1827
((*- if m.is_real_message *))
1928
use self::(((m.parent_mod_name)))::(((m.mod_name)))::(((m.msg_name)));
2029
((*- endif *))
2130
((*- endfor *))
2231
use self::unknown::Unknown;
32+
use self::invalid::Invalid;
2333

2434
mod lib {
2535
//! Common imports so we can just `use super::lib::*` in all the message files
@@ -69,11 +79,11 @@ mod lib {
6979
use lib::*;
7080

7181
/// Common functionality available to all SBP messages.
72-
pub trait SbpMessage: WireFormat + Clone + Sized {
82+
pub trait SbpMessage: WireFormat + Clone {
7383
/// Get the message name.
7484
fn message_name(&self) -> &'static str;
7585
/// Get the message type.
76-
fn message_type(&self) -> u16;
86+
fn message_type(&self) -> Option<u16>;
7787
/// Get the sender_id if it is set.
7888
fn sender_id(&self) -> Option<u16>;
7989
/// Set the sender id.
@@ -89,6 +99,10 @@ pub trait SbpMessage: WireFormat + Clone + Sized {
8999
fn friendly_name(&self) -> &'static str {
90100
""
91101
}
102+
/// Tells you if the message is valid or if it is not a valid message and may need to be
103+
/// special cased at certain points.
104+
fn is_valid(&self) -> bool;
105+
fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid>;
92106
}
93107

94108
/// Implemented by messages who's message name and type are known at compile time.
@@ -130,6 +144,8 @@ pub enum Sbp {
130144
((*- endfor *))
131145
/// Unknown message type
132146
Unknown( Unknown ),
147+
/// Invalid message type.
148+
Invalid( Invalid )
133149
}
134150

135151
#[cfg(feature = "serde_json")]
@@ -145,13 +161,57 @@ impl<'de> serde::Deserialize<'de> for Sbp {
145161
serde_json::from_value::<(((m.msg_name)))>(value).map(Sbp::(((m.msg_name))) )
146162
},
147163
((*- endfor *))
148-
_ => {
149-
serde_json::from_value::<Unknown>(value).map(Sbp::Unknown)
164+
msg_id @ Some(_) => {
165+
serde_json::from_value::<Unknown>(value)
166+
.map(|msg| Unknown {
167+
msg_id,
168+
..msg
169+
})
170+
.map(Sbp::Unknown)
150171
},
172+
None => {
173+
serde_json::from_value::<Invalid>(value)
174+
.map(|msg| Invalid {
175+
..msg
176+
})
177+
.map(Sbp::Invalid)
178+
}
151179
}.map_err(serde::de::Error::custom)
152180
}
153181
}
154182

183+
#[derive(Debug, Clone)]
184+
pub struct SbpMsgParseError {
185+
/// the message type
186+
pub msg_type: u16,
187+
/// the sender_id
188+
pub sender_id: u16,
189+
/// A vec that just contains the invalid payload bytes
190+
pub invalid_payload: Vec<u8>,
191+
}
192+
193+
impl From<SbpMsgParseError> for PayloadParseError {
194+
fn from(
195+
SbpMsgParseError {
196+
invalid_payload,
197+
..
198+
}: SbpMsgParseError,
199+
) -> Self {
200+
Self {
201+
invalid_payload,
202+
}
203+
}
204+
}
205+
206+
impl std::fmt::Display for SbpMsgParseError {
207+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208+
write!(f, "error parsing payload")
209+
}
210+
}
211+
212+
impl std::error::Error for SbpMsgParseError {}
213+
214+
155215
impl Sbp {
156216
/// Parse a message from given fields.
157217
///
@@ -176,20 +236,34 @@ impl Sbp {
176236
/// Ok(())
177237
/// }
178238
/// ```
179-
pub fn from_parts<B: bytes::Buf>(msg_type: u16, sender_id: u16, mut payload: B) -> Result<Sbp, PayloadParseError> {
180-
match msg_type {
239+
pub fn from_parts<B: bytes::Buf>(msg_type: u16, sender_id: u16, mut payload: B) -> Result<Sbp, SbpMsgParseError> {
240+
let sbp_msg = match msg_type {
181241
((*- for m in msgs *))
182242
(((m.msg_name)))::MESSAGE_TYPE => {
183-
let mut msg = (((m.msg_name)))::parse(&mut payload)?;
184-
msg.set_sender_id(sender_id);
185-
Ok(Sbp::(((m.msg_name)))(msg))
243+
(((m.msg_name)))::parse(&mut payload)
244+
.map(Sbp::(((m.msg_name))) )
186245
},
187246
((*- endfor *))
188-
_ => {
189-
let mut msg = Unknown::parse(&mut payload)?;
247+
msg_type => {
248+
Unknown::parse(&mut payload)
249+
// keep the msg ID we originally saw
250+
.map(|msg| Unknown { msg_id: Some(msg_type), ..msg })
251+
.map(Sbp::Unknown)
252+
}
253+
};
254+
// Inject sender_id, handle error
255+
match sbp_msg {
256+
Ok(mut msg) => {
190257
msg.set_sender_id(sender_id);
191-
Ok(Sbp::Unknown(msg))
258+
Ok(msg)
192259
}
260+
Err(PayloadParseError {
261+
invalid_payload,
262+
}) => Err(SbpMsgParseError {
263+
msg_type,
264+
sender_id,
265+
invalid_payload,
266+
}),
193267
}
194268
}
195269
}
@@ -205,10 +279,13 @@ impl SbpMessage for Sbp {
205279
Sbp::Unknown(msg) => {
206280
msg.message_name()
207281
},
282+
Sbp::Invalid(msg) => {
283+
msg.message_name()
284+
},
208285
}
209286
}
210287

211-
fn message_type(&self) -> u16 {
288+
fn message_type(&self) -> Option<u16> {
212289
match self {
213290
((*- for m in msgs *))
214291
Sbp::(((m.msg_name)))(msg) => {
@@ -218,6 +295,9 @@ impl SbpMessage for Sbp {
218295
Sbp::Unknown(msg) => {
219296
msg.message_type()
220297
},
298+
Sbp::Invalid(msg) => {
299+
msg.message_type()
300+
},
221301
}
222302
}
223303

@@ -231,6 +311,9 @@ impl SbpMessage for Sbp {
231311
Sbp::Unknown(msg) => {
232312
msg.sender_id()
233313
},
314+
Sbp::Invalid(msg) => {
315+
msg.sender_id()
316+
},
234317
}
235318
}
236319

@@ -244,6 +327,9 @@ impl SbpMessage for Sbp {
244327
Sbp::Unknown(msg) => {
245328
msg.set_sender_id(new_id)
246329
},
330+
Sbp::Invalid(msg) => {
331+
msg.set_sender_id(new_id)
332+
},
247333
}
248334
}
249335

@@ -257,6 +343,9 @@ impl SbpMessage for Sbp {
257343
Sbp::Unknown(msg) => {
258344
msg.encoded_len()
259345
},
346+
Sbp::Invalid(msg) => {
347+
msg.encoded_len()
348+
},
260349
}
261350
}
262351

@@ -271,6 +360,9 @@ impl SbpMessage for Sbp {
271360
Sbp::Unknown(msg) => {
272361
msg.gps_time()
273362
},
363+
Sbp::Invalid(msg) => {
364+
msg.gps_time()
365+
},
274366
}
275367
}
276368

@@ -284,15 +376,53 @@ impl SbpMessage for Sbp {
284376
Sbp::Unknown(msg) => {
285377
msg.friendly_name()
286378
},
379+
Sbp::Invalid(msg) => {
380+
msg.friendly_name()
381+
},
382+
}
383+
}
384+
385+
fn is_valid(&self) -> bool {
386+
match self {
387+
((*- for m in msgs *))
388+
Sbp::(((m.msg_name)))(msg) => {
389+
msg.is_valid()
390+
},
391+
((*- endfor -*))
392+
Sbp::Unknown(msg) => {
393+
msg.is_valid()
394+
},
395+
Sbp::Invalid(msg) => {
396+
msg.is_valid()
397+
},
287398
}
288399
}
400+
fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
401+
match self {
402+
((*- for m in msgs *))
403+
Sbp::(((m.msg_name)))(msg) => {
404+
Ok(Sbp::(((m.msg_name)))(msg.into_valid_msg()?))
405+
},
406+
((*- endfor -*))
407+
Sbp::Unknown(msg) => {
408+
Ok(Sbp::Unknown(msg.into_valid_msg()?))
409+
},
410+
Sbp::Invalid(msg) => {
411+
// should never pass
412+
let res = msg.into_valid_msg();
413+
debug_assert!(res.is_err(), "invalid messages may never be valid");
414+
Ok(Sbp::Invalid(res?))
415+
},
416+
}
417+
}
418+
289419
}
290420

291421
impl WireFormat for Sbp {
292422
const MIN_LEN: usize = crate::MAX_FRAME_LEN;
293423

294424
fn parse_unchecked<B: Buf>(_: &mut B) -> Self {
295-
unimplemented!("Sbp must be parsed with Sbp::from_frame");
425+
unimplemented!("Sbp must be parsed with Sbp::from_parts");
296426
}
297427

298428
fn write<B: BufMut>(&self, buf: &mut B) {
@@ -305,6 +435,9 @@ impl WireFormat for Sbp {
305435
Sbp::Unknown(msg) => {
306436
WireFormat::write(msg, buf)
307437
},
438+
Sbp::Invalid(msg) => {
439+
WireFormat::write(msg, buf)
440+
},
308441
}
309442
}
310443

@@ -318,6 +451,9 @@ impl WireFormat for Sbp {
318451
Sbp::Unknown(msg) => {
319452
WireFormat::len(msg)
320453
},
454+
Sbp::Invalid(msg) => {
455+
WireFormat::len(msg)
456+
},
321457
}
322458
}
323459
}
@@ -335,3 +471,8 @@ impl From<Unknown> for Sbp {
335471
Sbp::Unknown(msg)
336472
}
337473
}
474+
impl From<Invalid> for Sbp {
475+
fn from(msg: Invalid) -> Self {
476+
Sbp::Invalid(msg)
477+
}
478+
}

generator/sbpg/targets/resources/rust/sbp_messages_template.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ impl SbpMessage for (((m.msg_name))) {
125125
fn message_name(&self) -> &'static str {
126126
<Self as ConcreteMessage>::MESSAGE_NAME
127127
}
128-
fn message_type(&self) -> u16 {
129-
<Self as ConcreteMessage>::MESSAGE_TYPE
128+
fn message_type(&self) -> Option<u16> {
129+
Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
130130
}
131131
fn sender_id(&self) -> Option<u16> {
132132
self.sender_id
@@ -137,6 +137,13 @@ impl SbpMessage for (((m.msg_name))) {
137137
fn encoded_len(&self) -> usize {
138138
WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
139139
}
140+
fn is_valid(&self) -> bool {
141+
true
142+
}
143+
fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
144+
Ok(self)
145+
}
146+
140147
(((m.gps_time_fn)))
141148
}
142149

generator/sbpg/targets/resources/rust/test/sbp_tests_template.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ fn test_(((s.suite_name|snake_case)))()
5050
};
5151
match &sbp_msg {
5252
sbp::messages::Sbp::(((t.msg.name|lower_acronyms)))(msg) => {
53-
assert_eq!( msg.message_type(), (((t.msg_type))), "Incorrect message type, expected (((t.msg_type))), is {}", msg.message_type());
53+
let msg_type = msg.message_type().unwrap();
54+
assert_eq!( msg_type, (((t.msg_type))), "Incorrect message type, expected (((t.msg_type))), is {}", msg_type);
5455
let sender_id = msg.sender_id().unwrap();
5556
assert_eq!(sender_id, (((t.sbp.sender))), "incorrect sender id, expected (((t.sbp.sender))), is {sender_id}");
5657
((*- for f in t.fieldskeys *))(((compare_value( (((f))), (((t.fields[f]))) ))))((*- endfor *))
@@ -96,7 +97,8 @@ fn test_json2sbp_(((s.suite_name|snake_case)))()
9697
};
9798
match &sbp_msg {
9899
sbp::messages::Sbp::(((t.msg.name|lower_acronyms)))(msg) => {
99-
assert_eq!( msg.message_type(), (((t.msg_type))), "Incorrect message type, expected (((t.msg_type))), is {}", msg.message_type());
100+
let msg_type = msg.message_type().unwrap();
101+
assert_eq!( msg_type, (((t.msg_type))), "Incorrect message type, expected (((t.msg_type))), is {}", msg_type);
100102
let sender_id = msg.sender_id().unwrap();
101103
assert_eq!(sender_id, (((t.sbp.sender))), "incorrect sender id, expected (((t.sbp.sender))), is {sender_id}");
102104
((*- for f in t.fieldskeys *))(((compare_value( (((f))), (((t.fields[f]))) ))))((*- endfor *))
@@ -139,7 +141,8 @@ fn test_sbp2json_(((s.suite_name|snake_case)))()
139141
let sbp_msg = sbp::messages::Sbp::(((t.msg.name|lower_acronyms)))(serde_json::from_str(std::str::from_utf8(json_buffer.as_slice()).unwrap().to_string().as_str()).unwrap());
140142
match &sbp_msg {
141143
sbp::messages::Sbp::(((t.msg.name|lower_acronyms)))(msg) => {
142-
assert_eq!( msg.message_type(), (((t.msg_type))), "Incorrect message type, expected (((t.msg_type))), is {}", msg.message_type());
144+
let msg_type = msg.message_type().unwrap();
145+
assert_eq!( msg_type, (((t.msg_type))), "Incorrect message type, expected (((t.msg_type))), is {}", msg_type);
143146
let sender_id = msg.sender_id().unwrap();
144147
assert_eq!(sender_id, (((t.sbp.sender))), "incorrect sender id, expected (((t.sbp.sender))), is {sender_id}");
145148
((*- for f in t.fieldskeys *))(((compare_value( (((f))), (((t.fields[f]))) ))))((*- endfor *))

0 commit comments

Comments
 (0)