Skip to content

Commit

Permalink
Merge pull request #24 from anti-social/buf-impl
Browse files Browse the repository at this point in the history
Simple fixed buffer implementation to store parsed data
  • Loading branch information
tact1m4n3 authored Apr 25, 2024
2 parents 03f0ec9 + 86b6d21 commit a21bed9
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 66 deletions.
76 changes: 76 additions & 0 deletions src/buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
pub(crate) struct BytesReader<'a> {
buf: &'a [u8],
idx: usize,
}

impl<'a> BytesReader<'a> {
pub fn new(buf: &'a [u8]) -> Self {
Self { buf, idx: 0 }
}

pub fn consumed(&self) -> usize {
self.idx
}

pub fn is_empty(&self) -> bool {
self.idx == self.buf.len()
}

pub fn next(&mut self) -> Option<u8> {
if self.idx < self.buf.len() {
let val = self.buf[self.idx];
self.idx += 1;
Some(val)
} else {
None
}
}

pub fn next_n(&mut self, n: usize) -> &[u8] {
let end_idx = (self.idx + n).min(self.buf.len());
let data = &self.buf[self.idx..end_idx];
self.idx = end_idx;
data
}
}

pub(crate) struct Buf<const C: usize> {
buf: [u8; C],
len: usize,
}

impl<const C: usize> Buf<C> {
pub const fn new() -> Self {
Self {
buf: [0; C],
len: 0,
}
}

pub fn len(&self) -> usize {
self.len
}

pub fn push(&mut self, c: u8) -> bool {
if let Some(v) = self.buf.get_mut(self.len) {
*v = c;
self.len += 1;
true
} else {
false
}
}

pub fn push_bytes(&mut self, data: &[u8]) {
self.buf[self.len..self.len + data.len()].copy_from_slice(data);
self.len += data.len();
}

pub fn data(&self) -> &[u8; C] {
&self.buf
}

pub fn clear(&mut self) {
self.len = 0;
}
}
107 changes: 41 additions & 66 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ use snafu::prelude::*;
#[link_section = ".data"]
static CRC8: Crc<u8> = Crc::<u8>::new(&CRC_8_DVB_S2);

use buffer::{Buf, BytesReader};
pub use packets::*;

mod buffer;
mod packets;
mod to_array;

/// Represents a packet reader
pub struct PacketReader {
buf: [u8; Packet::MAX_LENGTH],
buf: Buf<{ Packet::MAX_LENGTH }>,
state: ReadState,
}

Expand All @@ -57,11 +59,19 @@ impl PacketReader {
/// Creates a new PacketReader struct
pub const fn new() -> Self {
Self {
buf: [0; Packet::MAX_LENGTH],
buf: Buf::new(),
state: ReadState::WaitingForSync,
}
}

/// Resets reader's state
///
/// Useful in situations when timeout is triggered but a packet is not parsed
pub fn reset(&mut self) {
self.buf.clear();
self.state = ReadState::WaitingForSync;
}

/// Reads the first packet from the buffer
pub fn push_bytes(&mut self, bytes: &[u8]) -> (Option<RawPacket>, usize) {
let mut reader = BytesReader::new(bytes);
Expand All @@ -70,7 +80,8 @@ impl PacketReader {
ReadState::WaitingForSync => {
while let Some(addr_byte) = reader.next() {
if PacketAddress::try_from(addr_byte).is_ok() {
self.buf[0] = addr_byte;
self.buf.clear();
self.buf.push(addr_byte);
self.state = ReadState::WaitingForLen;
break;
}
Expand All @@ -85,9 +96,8 @@ impl PacketReader {
if let Some(len_byte) = reader.next() {
match len_byte {
Self::MIN_DATA_LENGTH..=Self::MAX_DATA_LENGTH => {
self.buf[1] = len_byte;
self.buf.push(len_byte);
self.state = ReadState::Reading {
idx: Packet::HEADER_LENGTH,
len: Packet::HEADER_LENGTH + len_byte as usize,
};
}
Expand All @@ -96,16 +106,15 @@ impl PacketReader {
continue;
}
}
ReadState::Reading { ref mut idx, len } => {
let data = reader.next_n(len - *idx);
self.buf[*idx..*idx + data.len()].copy_from_slice(data);
*idx += data.len();
if *idx >= len {
ReadState::Reading { len } => {
let data = reader.next_n(len - self.buf.len());
self.buf.push_bytes(data);
if self.buf.len() >= len {
self.state = ReadState::WaitingForSync;
break Some(
RawPacket {
buf: &self.buf,
len,
buf: self.buf.data(),
len: self.buf.len(),
}
);
}
Expand Down Expand Up @@ -323,43 +332,7 @@ impl PacketType {
enum ReadState {
WaitingForSync,
WaitingForLen,
Reading { idx: usize, len: usize },
}

struct BytesReader<'a> {
buf: &'a [u8],
idx: usize,
}

impl<'a> BytesReader<'a> {
fn new(buf: &'a [u8]) -> Self {
Self { buf, idx: 0 }
}

fn consumed(&self) -> usize {
self.idx
}

fn is_empty(&self) -> bool {
self.idx == self.buf.len()
}

fn next(&mut self) -> Option<u8> {
if self.idx < self.buf.len() {
let val = self.buf[self.idx];
self.idx += 1;
Some(val)
} else {
None
}
}

fn next_n(&mut self, n: usize) -> &[u8] {
let end_idx = (self.idx + n).min(self.buf.len());
let data = &self.buf[self.idx..end_idx];
self.idx = end_idx;
data
}
Reading { len: usize },
}

#[cfg(test)]
Expand Down Expand Up @@ -392,23 +365,25 @@ mod tests {
let mut reader = PacketReader::new();
let typ = PacketType::RcChannelsPacked;

// Garbage
assert!(reader.push_bytes(&[0, 1, 2, 3]).0.is_none());
// More garbage
assert!(reader.push_bytes(&[254, 255]).0.is_none());
// Sync
assert!(reader.push_bytes(&[PacketAddress::Handset as u8]).0.is_none());
// Len
assert!(reader.push_bytes(&[24]).0.is_none());
// Type
assert!(reader.push_bytes(&[typ as u8]).0.is_none());
// Payload
assert!(reader.push_bytes(&[0; 22]).0.is_none());
// Checksum
assert!(matches!(
reader.push_bytes(&[239]).0.map(|raw_packet| Packet::parse(raw_packet)).expect("packet expected"),
Ok(Packet::RcChannels(RcChannels(channels))) if channels == [0; 16]
));
for _ in 0..2 {
// Garbage
assert!(reader.push_bytes(&[1, 2, 3]).0.is_none());
// More garbage
assert!(reader.push_bytes(&[254, 255]).0.is_none());
// Sync
assert!(reader.push_bytes(&[PacketAddress::Handset as u8]).0.is_none());
// Len
assert!(reader.push_bytes(&[24]).0.is_none());
// Type
assert!(reader.push_bytes(&[typ as u8]).0.is_none());
// Payload
assert!(reader.push_bytes(&[0; 22]).0.is_none());
// Checksum
assert!(matches!(
reader.push_bytes(&[239]).0.map(|raw_packet| Packet::parse(raw_packet)).expect("packet expected"),
Ok(Packet::RcChannels(RcChannels(channels))) if channels == [0; 16]
));
}
}

#[test]
Expand Down

0 comments on commit a21bed9

Please sign in to comment.