#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use crate::{
error::ParserError,
ubx_packets::{match_packet, PacketRef, MAX_PAYLOAD_LEN, SYNC_CHAR_1, SYNC_CHAR_2},
};
pub trait UnderlyingBuffer:
core::ops::Index<core::ops::Range<usize>, Output = [u8]> + core::ops::Index<usize, Output = u8>
{
fn clear(&mut self);
fn len(&self) -> usize;
fn max_capacity(&self) -> usize;
fn extend_from_slice(&mut self, other: &[u8]) -> usize;
fn drain(&mut self, count: usize);
fn find(&self, value: u8) -> Option<usize> {
for i in 0..self.len() {
if self[i] == value {
return Some(i);
}
}
None
}
fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl UnderlyingBuffer for Vec<u8> {
fn clear(&mut self) {
self.clear();
}
fn len(&self) -> usize {
self.len()
}
fn max_capacity(&self) -> usize {
core::usize::MAX
}
fn extend_from_slice(&mut self, other: &[u8]) -> usize {
self.extend_from_slice(other);
0
}
fn drain(&mut self, count: usize) {
self.drain(0..count);
}
fn find(&self, value: u8) -> Option<usize> {
self.iter().position(|elem| *elem == value)
}
}
pub struct FixedLinearBuffer<'a> {
buffer: &'a mut [u8],
len: usize,
}
impl<'a> FixedLinearBuffer<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
Self {
buffer: buf,
len: 0,
}
}
}
impl<'a> core::ops::Index<core::ops::Range<usize>> for FixedLinearBuffer<'a> {
type Output = [u8];
fn index(&self, index: core::ops::Range<usize>) -> &Self::Output {
if index.end > self.len {
panic!("Index {} is outside of our length {}", index.end, self.len);
}
self.buffer.index(index)
}
}
impl<'a> core::ops::Index<usize> for FixedLinearBuffer<'a> {
type Output = u8;
fn index(&self, index: usize) -> &Self::Output {
&self.buffer[index]
}
}
impl<'a> UnderlyingBuffer for FixedLinearBuffer<'a> {
fn clear(&mut self) {
self.len = 0;
}
fn len(&self) -> usize {
self.len
}
fn max_capacity(&self) -> usize {
self.buffer.len()
}
fn extend_from_slice(&mut self, other: &[u8]) -> usize {
let to_copy = core::cmp::min(other.len(), self.buffer.len() - self.len);
let uncopyable = other.len() - to_copy;
self.buffer[self.len..self.len + to_copy].copy_from_slice(&other[..to_copy]);
self.len += to_copy;
uncopyable
}
fn drain(&mut self, count: usize) {
if count >= self.len {
self.len = 0;
return;
}
let new_size = self.len - count;
{
let bufptr = self.buffer.as_mut_ptr();
unsafe {
core::ptr::copy(bufptr.add(count), bufptr, new_size);
}
}
self.len = new_size;
}
fn find(&self, value: u8) -> Option<usize> {
for i in 0..self.len {
if self.buffer[i] == value {
return Some(i);
}
}
None
}
}
pub struct Parser<T>
where
T: UnderlyingBuffer,
{
buf: T,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl core::default::Default for Parser<Vec<u8>> {
fn default() -> Self {
Self { buf: Vec::new() }
}
}
impl<T: UnderlyingBuffer> Parser<T> {
pub fn new(underlying: T) -> Self {
Self { buf: underlying }
}
pub fn is_buffer_empty(&self) -> bool {
self.buf.is_empty()
}
pub fn buffer_len(&self) -> usize {
self.buf.len()
}
pub fn consume<'a>(&'a mut self, new_data: &'a [u8]) -> ParserIter<'a, T> {
let mut buf = DualBuffer::new(&mut self.buf, new_data);
for i in 0..buf.len() {
if buf[i] == SYNC_CHAR_1 {
buf.drain(i);
break;
}
}
ParserIter { buf }
}
}
struct DualBuffer<'a, T: UnderlyingBuffer> {
buf: &'a mut T,
off: usize,
new_buf: &'a [u8],
new_buf_offset: usize,
}
impl<'a, T: UnderlyingBuffer> core::ops::Index<usize> for DualBuffer<'a, T> {
type Output = u8;
fn index(&self, index: usize) -> &u8 {
if self.off + index < self.buf.len() {
&self.buf[index + self.off]
} else {
&self.new_buf[self.new_buf_offset + index - (self.buf.len() - self.off)]
}
}
}
impl<'a, T: UnderlyingBuffer> DualBuffer<'a, T> {
fn new(buf: &'a mut T, new_buf: &'a [u8]) -> Self {
Self {
buf,
off: 0,
new_buf,
new_buf_offset: 0,
}
}
fn clear(&mut self) {
self.drain(self.len());
}
fn drain(&mut self, count: usize) {
let underlying_bytes = core::cmp::min(self.buf.len() - self.off, count);
let new_bytes = count.saturating_sub(underlying_bytes);
self.off += underlying_bytes;
self.new_buf_offset += new_bytes;
}
fn len(&self) -> usize {
self.buf.len() - self.off + self.new_buf.len() - self.new_buf_offset
}
fn potential_lost_bytes(&self) -> usize {
if self.len() <= self.buf.max_capacity() {
0
} else {
self.len() - self.buf.max_capacity()
}
}
fn can_drain_and_take(&self, drain: usize, take: usize) -> bool {
let underlying_bytes = core::cmp::min(self.buf.len() - self.off, drain);
let new_bytes = drain.saturating_sub(underlying_bytes);
let drained_off = self.off + underlying_bytes;
let drained_new_off = self.new_buf_offset + new_bytes;
if take > self.buf.len() - drained_off + self.new_buf.len() - drained_new_off {
return false;
}
let underlying_bytes = core::cmp::min(self.buf.len() - drained_off, take);
let new_bytes = take.saturating_sub(underlying_bytes);
if underlying_bytes == 0 {
return true;
}
if new_bytes == 0 {
return true;
}
if new_bytes > self.buf.max_capacity() - (self.buf.len() - drained_off) {
return false;
}
true
}
fn peek_raw(&self, range: core::ops::Range<usize>) -> (&[u8], &[u8]) {
let split = self.buf.len() - self.off;
let a = if range.start >= split {
&[]
} else {
&self.buf[range.start + self.off..core::cmp::min(self.buf.len(), range.end + self.off)]
};
let b = if range.end <= split {
&[]
} else {
&self.new_buf[self.new_buf_offset + range.start.saturating_sub(split)
..range.end - split + self.new_buf_offset]
};
(a, b)
}
fn take(&mut self, count: usize) -> Result<&[u8], ParserError> {
let underlying_bytes = core::cmp::min(self.buf.len() - self.off, count);
let new_bytes = count.saturating_sub(underlying_bytes);
if new_bytes > self.new_buf.len() - self.new_buf_offset {
panic!(
"Cannot pull {} bytes from a buffer with {}-{}",
new_bytes,
self.new_buf.len(),
self.new_buf_offset
);
}
if underlying_bytes == 0 {
let offset = self.new_buf_offset;
self.new_buf_offset += count;
return Ok(&self.new_buf[offset..offset + count]);
}
if new_bytes == 0 {
let offset = self.off;
self.off += count;
return Ok(&self.buf[offset..offset + count]);
}
if self.buf.max_capacity() < count {
return Err(ParserError::OutOfMemory {
required_size: count,
});
}
if new_bytes < self.buf.max_capacity() - self.buf.len() {
let bytes_not_moved = self
.buf
.extend_from_slice(&self.new_buf[self.new_buf_offset..]);
self.new_buf_offset += self.new_buf.len() - self.new_buf_offset - bytes_not_moved;
let off = self.off;
self.off += count;
return Ok(&self.buf[off..off + count]);
}
self.buf.drain(self.off);
self.off = 0;
self.buf
.extend_from_slice(&self.new_buf[self.new_buf_offset..self.new_buf_offset + new_bytes]);
self.new_buf_offset += new_bytes;
self.off += count;
Ok(&self.buf[0..count])
}
}
impl<'a, T: UnderlyingBuffer> Drop for DualBuffer<'a, T> {
fn drop(&mut self) {
self.buf.drain(self.off);
self.buf
.extend_from_slice(&self.new_buf[self.new_buf_offset..]);
}
}
#[derive(Default)]
struct UbxChecksumCalc {
ck_a: u8,
ck_b: u8,
}
impl UbxChecksumCalc {
fn new() -> Self {
Self { ck_a: 0, ck_b: 0 }
}
fn update(&mut self, bytes: &[u8]) {
let mut a = self.ck_a;
let mut b = self.ck_b;
for byte in bytes.iter() {
a = a.overflowing_add(*byte).0;
b = b.overflowing_add(a).0;
}
self.ck_a = a;
self.ck_b = b;
}
fn result(self) -> (u8, u8) {
(self.ck_a, self.ck_b)
}
}
pub struct ParserIter<'a, T: UnderlyingBuffer> {
buf: DualBuffer<'a, T>,
}
impl<'a, T: UnderlyingBuffer> ParserIter<'a, T> {
fn find_sync(&self) -> Option<usize> {
for i in 0..self.buf.len() {
if self.buf[i] == SYNC_CHAR_1 {
return Some(i);
}
}
None
}
fn extract_packet(&mut self, pack_len: usize) -> Option<Result<PacketRef, ParserError>> {
if !self.buf.can_drain_and_take(6, pack_len + 2) {
if self.buf.potential_lost_bytes() > 0 {
self.buf.drain(2);
return Some(Err(ParserError::OutOfMemory {
required_size: pack_len + 2,
}));
}
return None;
}
let mut checksummer = UbxChecksumCalc::new();
let (a, b) = self.buf.peek_raw(2..(4 + pack_len + 2));
checksummer.update(a);
checksummer.update(b);
let (ck_a, ck_b) = checksummer.result();
let (expect_ck_a, expect_ck_b) = (self.buf[6 + pack_len], self.buf[6 + pack_len + 1]);
if (ck_a, ck_b) != (expect_ck_a, expect_ck_b) {
self.buf.drain(2);
return Some(Err(ParserError::InvalidChecksum {
expect: u16::from_le_bytes([expect_ck_a, expect_ck_b]),
got: u16::from_le_bytes([ck_a, ck_b]),
}));
}
let class_id = self.buf[2];
let msg_id = self.buf[3];
self.buf.drain(6);
let msg_data = match self.buf.take(pack_len + 2) {
Ok(x) => x,
Err(e) => {
return Some(Err(e));
}
};
return Some(match_packet(
class_id,
msg_id,
&msg_data[..msg_data.len() - 2], ));
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<Result<PacketRef, ParserError>> {
while self.buf.len() > 0 {
let pos = match self.find_sync() {
Some(x) => x,
None => {
self.buf.clear();
return None;
}
};
self.buf.drain(pos);
if self.buf.len() < 2 {
return None;
}
if self.buf[1] != SYNC_CHAR_2 {
self.buf.drain(1);
continue;
}
if self.buf.len() < 6 {
return None;
}
let pack_len: usize = u16::from_le_bytes([self.buf[4], self.buf[5]]).into();
if pack_len > usize::from(MAX_PAYLOAD_LEN) {
self.buf.drain(2);
continue;
}
return self.extract_packet(pack_len);
}
None
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::ubx_packets::*;
#[cfg(feature = "alloc")]
use alloc::vec;
#[cfg(feature = "alloc")]
#[test]
fn dl_split_indexing() {
let mut buf = vec![1, 2, 3, 4];
let new = [5, 6, 7, 8];
let dual = DualBuffer::new(&mut buf, &new[..]);
for i in 0..8 {
assert_eq!(dual[i], i as u8 + 1);
}
}
#[cfg(feature = "alloc")]
#[test]
#[should_panic]
fn dl_take_too_many() {
let mut buf = vec![1, 2, 3, 4];
let new = [];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
let _ = dual.take(6);
}
}
#[cfg(feature = "alloc")]
#[test]
fn dl_take_range_underlying() {
let mut buf = vec![1, 2, 3, 4];
let new = [];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
let x = dual.take(3).unwrap();
assert_eq!(x, &[1, 2, 3]);
}
assert_eq!(buf, &[4]);
}
#[cfg(feature = "alloc")]
#[test]
fn dl_take_range_new() {
let mut buf = vec![];
let new = [1, 2, 3, 4];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
let x = dual.take(3).unwrap();
assert_eq!(x, &[1, 2, 3]);
}
assert_eq!(buf, &[4]);
}
#[cfg(feature = "alloc")]
#[test]
fn dl_take_range_overlapping() {
let mut buf = vec![1, 2, 3, 4];
let new = [5, 6, 7, 8];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
let x = dual.take(6).unwrap();
assert_eq!(x, &[1, 2, 3, 4, 5, 6]);
}
assert_eq!(buf, &[7, 8]);
}
#[cfg(feature = "alloc")]
#[test]
fn dl_take_multi_ranges() {
let mut buf = vec![1, 2, 3, 4, 5, 6, 7];
let new = [8, 9, 10, 11, 12];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
assert_eq!(dual.take(3).unwrap(), &[1, 2, 3]);
assert_eq!(dual.take(3).unwrap(), &[4, 5, 6]);
assert_eq!(dual.take(3).unwrap(), &[7, 8, 9]);
assert_eq!(dual.take(3).unwrap(), &[10, 11, 12]);
}
assert_eq!(buf, &[]);
}
#[cfg(feature = "alloc")]
#[test]
fn dl_take_multi_ranges2() {
let mut buf = vec![1, 2, 3, 4, 5, 6, 7];
let new = [8, 9, 10, 11, 12];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
assert_eq!(dual.take(3).unwrap(), &[1, 2, 3]);
assert_eq!(dual.take(6).unwrap(), &[4, 5, 6, 7, 8, 9]);
}
assert_eq!(buf, &[10, 11, 12]);
}
#[test]
fn dl_move_then_copy() {
let mut buf = [0; 7];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
let new = [8, 9, 10, 11, 12];
{
let mut dual = DualBuffer::new(&mut buf, &new[..]);
assert_eq!(dual.take(3).unwrap(), &[1, 2, 3]);
assert_eq!(dual.take(6).unwrap(), &[4, 5, 6, 7, 8, 9]);
}
assert_eq!(buf.len(), 3);
}
#[test]
#[should_panic]
fn dl_take_range_oom() {
let mut buf = [0; 4];
let mut buf = FixedLinearBuffer::new(&mut buf);
let new = [1, 2, 3, 4, 5, 6];
let mut dual = DualBuffer::new(&mut buf, &new[..]);
match dual.take(6) {
Err(ParserError::OutOfMemory { required_size }) => {
assert_eq!(required_size, 6);
}
_ => assert!(false),
}
}
#[test]
fn dl_drain_partial_underlying() {
let mut buf = [0; 4];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3]);
let new = [4, 5, 6, 7, 8, 9];
let mut dual = DualBuffer::new(&mut buf, &new[..]);
dual.drain(2);
assert_eq!(dual.len(), 7);
assert_eq!(dual.take(4).unwrap(), &[3, 4, 5, 6]);
assert_eq!(dual.len(), 3);
}
#[test]
fn dl_drain() {
let mut buf = [0; 4];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3]);
let new = [4, 5, 6, 7, 8, 9];
let mut dual = DualBuffer::new(&mut buf, &new[..]);
dual.drain(5);
assert_eq!(dual.take(3).unwrap(), &[6, 7, 8]);
assert_eq!(dual.len(), 1);
}
#[test]
fn dl_clear() {
let mut buf = [0; 4];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3]);
let new = [4, 5, 6, 7, 8, 9];
let mut dual = DualBuffer::new(&mut buf, &new[..]);
assert_eq!(dual.len(), 9);
dual.clear();
assert_eq!(dual.len(), 0);
}
#[test]
fn dl_peek_raw() {
let mut buf = [0; 4];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3]);
let new = [4, 5, 6, 7, 8, 9];
let dual = DualBuffer::new(&mut buf, &new[..]);
let (a, b) = dual.peek_raw(2..6);
assert_eq!(a, &[3]);
assert_eq!(b, &[4, 5, 6]);
}
#[test]
fn flb_clear() {
let mut buf = [0; 16];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
assert_eq!(buf.len(), 7);
buf.clear();
assert_eq!(buf.len(), 0);
}
#[test]
#[should_panic]
fn flb_index_outside_range() {
let mut buf = [0; 16];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
let _ = buf[5..10];
}
#[test]
fn flb_extend_outside_range() {
let mut buf = [0; 16];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
assert_eq!(buf.len(), 16);
}
#[test]
fn flb_drain() {
let mut buf = [0; 16];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
buf.drain(3);
assert_eq!(buf.len(), 4);
assert_eq!(&buf[0..buf.len()], &[4, 5, 6, 7]);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
assert_eq!(buf.len(), 11);
assert_eq!(&buf[0..buf.len()], &[4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]);
}
#[test]
fn flb_drain_all() {
let mut buf = [0; 16];
let mut buf = FixedLinearBuffer::new(&mut buf);
buf.extend_from_slice(&[1, 2, 3, 4, 5, 6, 7]);
buf.drain(7);
assert_eq!(buf.len(), 0);
}
#[test]
fn flb_find() {
let mut buf = [1, 2, 3, 4, 5, 6, 7, 8];
let mut buf = FixedLinearBuffer::new(&mut buf);
assert_eq!(buf.find(5), None);
buf.extend_from_slice(&[1, 2, 3, 4]);
assert_eq!(buf.find(5), None);
buf.extend_from_slice(&[5, 6, 7, 8]);
assert_eq!(buf.find(5), Some(4));
}
#[cfg(feature = "alloc")]
#[test]
fn parser_oom_processes_multiple_small_packets() {
let packet = [0xb5, 0x62, 0x5, 0x1, 0x2, 0x0, 0x4, 0x5, 0x11, 0x38];
let mut bytes = vec![];
bytes.extend_from_slice(&packet);
bytes.extend_from_slice(&packet);
bytes.extend_from_slice(&packet);
bytes.extend_from_slice(&packet);
bytes.extend_from_slice(&packet);
let mut buffer = [0; 10];
let buffer = FixedLinearBuffer::new(&mut buffer);
let mut parser = Parser::new(buffer);
let mut it = parser.consume(&bytes);
for _ in 0..5 {
match it.next() {
Some(Ok(PacketRef::AckAck(_packet))) => {
}
_ => assert!(false),
}
}
assert!(it.next().is_none());
}
#[test]
fn parser_handle_garbage_first_byte() {
let mut buffer = [0; 12];
let buffer = FixedLinearBuffer::new(&mut buffer);
let mut parser = Parser::new(buffer);
let bytes = [0xb5, 0xb5, 0x62, 0x5, 0x1, 0x2, 0x0, 0x4, 0x5, 0x11, 0x38];
{
let mut it = parser.consume(&bytes);
match it.next() {
Some(Ok(PacketRef::AckAck(_packet))) => {
}
_ => assert!(false),
}
assert!(it.next().is_none());
}
}
#[test]
fn parser_oom_clears_buffer() {
let bytes = CfgNav5Builder {
mask: CfgNav5Params::DYN,
dyn_model: CfgNav5DynModel::AirborneWithLess1gAcceleration,
fix_mode: CfgNav5FixMode::Only3D,
fixed_alt: 100.17,
fixed_alt_var: 0.0017,
min_elev_degrees: 17,
pdop: 1.7,
tdop: 1.7,
pacc: 17,
tacc: 17,
static_hold_thresh: 2.17,
dgps_time_out: 17,
cno_thresh_num_svs: 17,
cno_thresh: 17,
static_hold_max_dist: 0x1717,
utc_standard: CfgNav5UtcStandard::UtcChina,
..CfgNav5Builder::default()
}
.into_packet_bytes();
let mut buffer = [0; 12];
let buffer = FixedLinearBuffer::new(&mut buffer);
let mut parser = Parser::new(buffer);
{
let mut it = parser.consume(&bytes[0..8]);
assert!(it.next().is_none());
}
{
let mut it = parser.consume(&bytes[8..]);
match it.next() {
Some(Err(ParserError::OutOfMemory { required_size })) => {
assert_eq!(required_size, bytes.len() - 6);
}
_ => {
assert!(false);
}
}
assert!(it.next().is_none());
}
let bytes = [0xb5, 0x62, 0x5, 0x1, 0x2, 0x0, 0x4, 0x5, 0x11, 0x38];
{
let mut it = parser.consume(&bytes);
match it.next() {
Some(Ok(PacketRef::AckAck(_packet))) => {
}
_ => assert!(false),
}
assert!(it.next().is_none());
}
}
#[test]
fn parser_accepts_packet_array_underlying() {
let bytes = CfgNav5Builder {
mask: CfgNav5Params::DYN,
dyn_model: CfgNav5DynModel::AirborneWithLess1gAcceleration,
fix_mode: CfgNav5FixMode::Only3D,
fixed_alt: 100.17,
fixed_alt_var: 0.0017,
min_elev_degrees: 17,
pdop: 1.7,
tdop: 1.7,
pacc: 17,
tacc: 17,
static_hold_thresh: 2.17,
dgps_time_out: 17,
cno_thresh_num_svs: 17,
cno_thresh: 17,
static_hold_max_dist: 0x1717,
utc_standard: CfgNav5UtcStandard::UtcChina,
..CfgNav5Builder::default()
}
.into_packet_bytes();
let mut buffer = [0; 1024];
let buffer = FixedLinearBuffer::new(&mut buffer);
let mut parser = Parser::new(buffer);
let mut it = parser.consume(&bytes);
match it.next() {
Some(Ok(PacketRef::CfgNav5(_packet))) => {
}
_ => {
assert!(false);
}
}
assert!(it.next().is_none());
}
#[test]
#[cfg(feature = "std")]
fn parser_accepts_packet_vec_underlying() {
let bytes = CfgNav5Builder {
mask: CfgNav5Params::DYN,
dyn_model: CfgNav5DynModel::AirborneWithLess1gAcceleration,
fix_mode: CfgNav5FixMode::Only3D,
fixed_alt: 100.17,
fixed_alt_var: 0.0017,
min_elev_degrees: 17,
pdop: 1.7,
tdop: 1.7,
pacc: 17,
tacc: 17,
static_hold_thresh: 2.17,
dgps_time_out: 17,
cno_thresh_num_svs: 17,
cno_thresh: 17,
static_hold_max_dist: 0x1717,
utc_standard: CfgNav5UtcStandard::UtcChina,
..CfgNav5Builder::default()
}
.into_packet_bytes();
let mut parser = Parser::default();
let mut it = parser.consume(&bytes);
match it.next() {
Some(Ok(PacketRef::CfgNav5(_packet))) => {
}
_ => {
assert!(false);
}
}
assert!(it.next().is_none());
}
#[test]
#[cfg(feature = "std")]
fn parser_accepts_multiple_packets() {
let mut data = vec![];
data.extend_from_slice(
&CfgNav5Builder {
pacc: 21,
..CfgNav5Builder::default()
}
.into_packet_bytes(),
);
data.extend_from_slice(
&CfgNav5Builder {
pacc: 18,
..CfgNav5Builder::default()
}
.into_packet_bytes(),
);
let mut parser = Parser::default();
let mut it = parser.consume(&data);
match it.next() {
Some(Ok(PacketRef::CfgNav5(packet))) => {
assert_eq!(packet.pacc(), 21);
}
_ => {
assert!(false);
}
}
match it.next() {
Some(Ok(PacketRef::CfgNav5(packet))) => {
assert_eq!(packet.pacc(), 18);
}
_ => {
assert!(false);
}
}
assert!(it.next().is_none());
}
}
#[test]
fn test_max_payload_len() {
assert!(MAX_PAYLOAD_LEN >= 1240);
}