From c95cbe547fa0ec6f6a4e21a39b56dbe9dfadf277 Mon Sep 17 00:00:00 2001 From: Joseph Angelo Date: Wed, 6 Nov 2019 21:21:24 -0800 Subject: [PATCH 1/4] Added key words for when we publish to crates.io --- rust/sbp/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/sbp/Cargo.toml b/rust/sbp/Cargo.toml index d48b31166b..a298ea2c14 100644 --- a/rust/sbp/Cargo.toml +++ b/rust/sbp/Cargo.toml @@ -7,6 +7,7 @@ repository = "https://github.com/swift-nav/libsbp" license = "LGPL-3.0" categories = ["parsing"] edition = "2018" +keywords = ["encoding", "parsing"] [features] serialize = ["serde"] From 974bf1ef8df023c20529593c4b91febef3d5f417 Mon Sep 17 00:00:00 2001 From: Joseph Angelo Date: Wed, 6 Nov 2019 21:22:00 -0800 Subject: [PATCH 2/4] Fixed crashing example --- rust/example/src/main.rs | 7 ++++--- rust/sbp/src/parser/mod.rs | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/rust/example/src/main.rs b/rust/example/src/main.rs index 1c5489e5b5..056e9cc64b 100644 --- a/rust/example/src/main.rs +++ b/rust/example/src/main.rs @@ -19,16 +19,17 @@ fn main() { let mut port = serialport::open_with_settings("/dev/ttyUSB0", &s) .expect("open failed"); + let mut parser = sbp::parser::Parser::new(); loop { - match sbp::client::parser::parse(&mut port) { + match parser.parse(&mut port) { Ok(SBP::MsgLog(x)) => println!("{}", x.text), Ok(SBP::MsgPosLLH(x)) => println!("{} {} {}", x.lat, x.lon, x.height), Ok(_) => (), - Err(Error::InvalidPreamble) => (), - Err(Error::CRCMismatch) => (), + Err(Error::NotEnoughData) => (), + Err(Error::UnrecoverableFailure) => (), Err(Error::ParseError) => (), Err(Error::IoError(ref x)) if x.kind() == std::io::ErrorKind::TimedOut => (), diff --git a/rust/sbp/src/parser/mod.rs b/rust/sbp/src/parser/mod.rs index b10f9e6205..c525662003 100644 --- a/rust/sbp/src/parser/mod.rs +++ b/rust/sbp/src/parser/mod.rs @@ -85,7 +85,7 @@ impl Parser { self.read_more(input)?; } - let result = loop { + loop { match self.parse_remaining() { Ok(msg) => break Ok(msg), Err(crate::Error::NotEnoughData) => { @@ -95,14 +95,15 @@ impl Parser { } Err(e) => break Err(e), }; - }; - - result + } } fn read_more(&mut self, input: &mut R) -> Result { let mut local_buffer = vec![0; Parser::BUF_SIZE]; let read_bytes = input.read(local_buffer.as_mut())?; + if read_bytes == 0 { + return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "")); + } self.buffer.extend_from_slice(&local_buffer[..read_bytes]); Ok(read_bytes) } @@ -117,10 +118,18 @@ impl Parser { break Ok(msg); } (Err(crate::Error::ParseError), bytes_read) => { - self.buffer = self.buffer[bytes_read..].to_vec(); + if bytes_read >= self.buffer.len() { + self.buffer.clear() + } else { + self.buffer = self.buffer[bytes_read..].to_vec(); + } } (Err(e), _bytes_read) => break Err(e), } + + if self.buffer.is_empty() { + break Err(crate::Error::NotEnoughData) + } } } } From 3e2b684ce530faff9413e6e084604326dcf713e4 Mon Sep 17 00:00:00 2001 From: Joseph Angelo Date: Wed, 6 Nov 2019 21:56:33 -0800 Subject: [PATCH 3/4] Added very basic crate description --- rust/sbp/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/sbp/src/lib.rs b/rust/sbp/src/lib.rs index 6e1a65c51f..8e054c11d5 100644 --- a/rust/sbp/src/lib.rs +++ b/rust/sbp/src/lib.rs @@ -1,3 +1,7 @@ +//! Native implementation of decoding of SBP (Swift Binary Protocol) used by products +//! made by Swift Navigation. For language agnostic description of the protocol please +//! see the protocol specification documentation at https://github.com/swift-nav/libsbp/tree/master/docs + pub mod messages; pub mod parser; From 8c343b3f43391307e1056127039a25b6330b3837 Mon Sep 17 00:00:00 2001 From: Joseph Angelo Date: Wed, 6 Nov 2019 21:57:08 -0800 Subject: [PATCH 4/4] Added more formal Error and Result definitions --- rust/sbp/src/lib.rs | 34 +++++++++++++++++++++++++++++++++ rust/sbp/src/parser/mod.rs | 39 +++++++++++++++++--------------------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/rust/sbp/src/lib.rs b/rust/sbp/src/lib.rs index 8e054c11d5..a43f452397 100644 --- a/rust/sbp/src/lib.rs +++ b/rust/sbp/src/lib.rs @@ -5,6 +5,12 @@ pub mod messages; pub mod parser; +use std::result; +use std::error; +use std::fmt; + +pub type Result = result::Result; + #[derive(Debug)] pub enum Error { ParseError, @@ -13,6 +19,34 @@ pub enum Error { IoError(std::io::Error), } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::ParseError => write!(f, "Parse Error"), + Error::NotEnoughData => write!(f, "Not enough data"), + Error::UnrecoverableFailure => write!(f, "Unrecoverage Failure"), + Error::IoError(err) => write!(f, "IO Error: {}", err), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &str { + match self { + Error::ParseError => "An error occured during parsing", + Error::NotEnoughData => "Not enough data available to parse a message", + Error::UnrecoverableFailure => "An unrecoverage failure was encountered", + Error::IoError(err) => err.description(), + } + } +} + +impl From for Error { + fn from(err: std::io::Error) -> Error { + Error::IoError(err) + } +} + #[cfg(test)] mod tests { #[test] diff --git a/rust/sbp/src/parser/mod.rs b/rust/sbp/src/parser/mod.rs index c525662003..ae781bbd30 100644 --- a/rust/sbp/src/parser/mod.rs +++ b/rust/sbp/src/parser/mod.rs @@ -9,7 +9,8 @@ use self::nom::multi::length_data; use self::nom::number::complete::{le_u16, le_u8}; use self::nom::sequence::tuple; use crate::messages::SBP; -use std::io::{self, Read}; +use crate::Result; +use std::io::Read; /// Attempts to extract a single SBP message from a data /// slice @@ -21,7 +22,7 @@ use std::io::{self, Read}; /// removed from the slice before calling `frame()` again. /// If the result is a /// success then the SBP message has been fully validated. -pub fn frame(input: &[u8]) -> (Result, usize) { +pub fn frame(input: &[u8]) -> (Result, usize) { let original_size = input.len(); let preamble = is_a("\x55"); let payload = length_data(le_u8); @@ -80,7 +81,7 @@ impl Parser { /// as needed /// until either a message is successfully parsed or an /// error occurs - pub fn parse(&mut self, input: &mut R) -> Result { + pub fn parse(&mut self, input: &mut R) -> Result { if self.buffer.len() == 0 { self.read_more(input)?; } @@ -90,7 +91,7 @@ impl Parser { Ok(msg) => break Ok(msg), Err(crate::Error::NotEnoughData) => { if let Err(e) = self.read_more(input) { - break Err(crate::Error::IoError(e)); + break Err(e); } } Err(e) => break Err(e), @@ -98,17 +99,17 @@ impl Parser { } } - fn read_more(&mut self, input: &mut R) -> Result { + fn read_more(&mut self, input: &mut R) -> Result { let mut local_buffer = vec![0; Parser::BUF_SIZE]; let read_bytes = input.read(local_buffer.as_mut())?; if read_bytes == 0 { - return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "")); + return Err(crate::Error::IoError(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, ""))); } self.buffer.extend_from_slice(&local_buffer[..read_bytes]); Ok(read_bytes) } - fn parse_remaining(&mut self) -> Result { + fn parse_remaining(&mut self) -> Result { loop { let result = frame(&self.buffer); @@ -134,27 +135,21 @@ impl Parser { } } -impl From for crate::Error { - fn from(error: io::Error) -> Self { - crate::Error::IoError(error) - } -} - -pub fn read_string(buf: &mut dyn Read) -> Result { +pub fn read_string(buf: &mut dyn Read) -> Result { let mut s = String::new(); buf.read_to_string(&mut s)?; Ok(s) } -pub fn read_string_limit(buf: &mut dyn Read, n: u64) -> Result { +pub fn read_string_limit(buf: &mut dyn Read, n: u64) -> Result { read_string(&mut buf.take(n)) } -pub fn read_u8_array(buf: &mut &[u8]) -> Result, crate::Error> { +pub fn read_u8_array(buf: &mut &[u8]) -> Result> { Ok(buf.to_vec()) } -pub fn read_u8_array_limit(buf: &mut &[u8], n: usize) -> Result, crate::Error> { +pub fn read_u8_array_limit(buf: &mut &[u8], n: usize) -> Result> { let mut v = Vec::new(); for _ in 0..n { v.push(buf.read_u8()?); @@ -162,7 +157,7 @@ pub fn read_u8_array_limit(buf: &mut &[u8], n: usize) -> Result, crate:: Ok(v) } -pub fn read_s8_array_limit(buf: &mut &[u8], n: usize) -> Result, crate::Error> { +pub fn read_s8_array_limit(buf: &mut &[u8], n: usize) -> Result> { let mut v = Vec::new(); for _ in 0..n { v.push(buf.read_i8()?); @@ -170,7 +165,7 @@ pub fn read_s8_array_limit(buf: &mut &[u8], n: usize) -> Result, crate:: Ok(v) } -pub fn read_s16_array_limit(buf: &mut &[u8], n: usize) -> Result, crate::Error> { +pub fn read_s16_array_limit(buf: &mut &[u8], n: usize) -> Result> { let mut v = Vec::new(); for _ in 0..n { v.push(buf.read_i16::()?); @@ -178,7 +173,7 @@ pub fn read_s16_array_limit(buf: &mut &[u8], n: usize) -> Result, crate Ok(v) } -pub fn read_u16_array_limit(buf: &mut &[u8], n: usize) -> Result, crate::Error> { +pub fn read_u16_array_limit(buf: &mut &[u8], n: usize) -> Result> { let mut v = Vec::new(); for _ in 0..n { v.push(buf.read_u16::()?); @@ -186,7 +181,7 @@ pub fn read_u16_array_limit(buf: &mut &[u8], n: usize) -> Result, crate Ok(v) } -pub fn read_float_array_limit(buf: &mut &[u8], n: usize) -> Result, crate::Error> { +pub fn read_float_array_limit(buf: &mut &[u8], n: usize) -> Result> { let mut v = Vec::new(); for _ in 0..n { v.push(buf.read_f32::()?); @@ -194,7 +189,7 @@ pub fn read_float_array_limit(buf: &mut &[u8], n: usize) -> Result, cra Ok(v) } -pub fn read_double_array_limit(buf: &mut &[u8], n: usize) -> Result, crate::Error> { +pub fn read_double_array_limit(buf: &mut &[u8], n: usize) -> Result> { let mut v = Vec::new(); for _ in 0..n { v.push(buf.read_f64::()?);