Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions rust/example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => (),

Expand Down
1 change: 1 addition & 0 deletions rust/sbp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
38 changes: 38 additions & 0 deletions rust/sbp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
ParseError,
Expand All @@ -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<std::io::Error> for Error {
fn from(err: std::io::Error) -> Error {
Error::IoError(err)
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
56 changes: 30 additions & 26 deletions rust/sbp/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<SBP, crate::Error>, usize) {
pub fn frame(input: &[u8]) -> (Result<SBP>, usize) {
let original_size = input.len();
let preamble = is_a("\x55");
let payload = length_data(le_u8);
Expand Down Expand Up @@ -80,34 +81,35 @@ impl Parser {
/// as needed
/// until either a message is successfully parsed or an
/// error occurs
pub fn parse<R: Read>(&mut self, input: &mut R) -> Result<SBP, crate::Error> {
pub fn parse<R: Read>(&mut self, input: &mut R) -> Result<SBP> {
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<R: Read>(&mut self, input: &mut R) -> Result<usize, std::io::Error> {
fn read_more<R: Read>(&mut self, input: &mut R) -> Result<usize> {
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<SBP, crate::Error> {
fn parse_remaining(&mut self) -> Result<SBP> {
loop {
let result = frame(&self.buffer);

Expand All @@ -117,75 +119,77 @@ 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<io::Error> 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<String, crate::Error> {
pub fn read_string(buf: &mut dyn Read) -> Result<String> {
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<String, crate::Error> {
pub fn read_string_limit(buf: &mut dyn Read, n: u64) -> Result<String> {
read_string(&mut buf.take(n))
}

pub fn read_u8_array(buf: &mut &[u8]) -> Result<Vec<u8>, crate::Error> {
pub fn read_u8_array(buf: &mut &[u8]) -> Result<Vec<u8>> {
Ok(buf.to_vec())
}

pub fn read_u8_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<u8>, crate::Error> {
pub fn read_u8_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<u8>> {
let mut v = Vec::new();
for _ in 0..n {
v.push(buf.read_u8()?);
}
Ok(v)
}

pub fn read_s8_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<i8>, crate::Error> {
pub fn read_s8_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<i8>> {
let mut v = Vec::new();
for _ in 0..n {
v.push(buf.read_i8()?);
}
Ok(v)
}

pub fn read_s16_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<i16>, crate::Error> {
pub fn read_s16_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<i16>> {
let mut v = Vec::new();
for _ in 0..n {
v.push(buf.read_i16::<LittleEndian>()?);
}
Ok(v)
}

pub fn read_u16_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<u16>, crate::Error> {
pub fn read_u16_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<u16>> {
let mut v = Vec::new();
for _ in 0..n {
v.push(buf.read_u16::<LittleEndian>()?);
}
Ok(v)
}

pub fn read_float_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<f32>, crate::Error> {
pub fn read_float_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<f32>> {
let mut v = Vec::new();
for _ in 0..n {
v.push(buf.read_f32::<LittleEndian>()?);
}
Ok(v)
}

pub fn read_double_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<f64>, crate::Error> {
pub fn read_double_array_limit(buf: &mut &[u8], n: usize) -> Result<Vec<f64>> {
let mut v = Vec::new();
for _ in 0..n {
v.push(buf.read_f64::<LittleEndian>()?);
Expand Down