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/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"] diff --git a/rust/sbp/src/lib.rs b/rust/sbp/src/lib.rs index 6e1a65c51f..a43f452397 100644 --- a/rust/sbp/src/lib.rs +++ b/rust/sbp/src/lib.rs @@ -1,6 +1,16 @@ +//! 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; +use std::result; +use std::error; +use std::fmt; + +pub type Result = result::Result; + #[derive(Debug)] pub enum Error { ParseError, @@ -9,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 b10f9e6205..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,34 +81,35 @@ 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)?; } - let result = loop { + loop { match self.parse_remaining() { 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), }; - }; - - result + } } - 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(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); @@ -117,35 +119,37 @@ 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), } - } - } -} -impl From for crate::Error { - fn from(error: io::Error) -> Self { - crate::Error::IoError(error) + if self.buffer.is_empty() { + break Err(crate::Error::NotEnoughData) + } + } } } -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()?); @@ -153,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()?); @@ -161,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::()?); @@ -169,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::()?); @@ -177,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::()?); @@ -185,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::()?);