Skip to content

Commit

Permalink
Fix URC parsing issues (#214)
Browse files Browse the repository at this point in the history
* Fix consumed bytes when parsing URC

* Fix recovering from garbage data that includes \r\n
  • Loading branch information
t-moe authored Nov 27, 2024
1 parent 75374ac commit a81487b
Showing 1 changed file with 40 additions and 1 deletion.
41 changes: 40 additions & 1 deletion atat/src/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl From<nom::Err<nom::error::Error<&[u8]>>> for ParseError {
}

pub trait Digester {
/// Digest the input buffer and return the result and the number of bytes consumed.
fn digest<'a>(&mut self, buf: &'a [u8]) -> (DigestResult<'a>, usize);
}

Expand Down Expand Up @@ -128,7 +129,7 @@ impl<P: Parser> Digester for AtDigester<P> {

// 2. Match for URC's
match P::parse(buf) {
Ok((urc, len)) => return (DigestResult::Urc(urc), len),
Ok((urc, len)) => return (DigestResult::Urc(urc), len + space_and_echo_bytes),
Err(ParseError::Incomplete) => return incomplete,
_ => {}
}
Expand Down Expand Up @@ -185,6 +186,14 @@ impl<P: Parser> Digester for AtDigester<P> {
return (result, len + space_and_echo_bytes);
}

// Handle '\r\n <Garbage> \r\n <Valid URC> \r\n' as parser::echo will only consume garbage BEFORE a \r\n
if buf.starts_with(b"\r\n") && buf.len() > 4 {
let (res, consumed) = self.digest(&buf[2..]);
if res != DigestResult::None {
return (res, space_and_echo_bytes + 2 + consumed);
}
}

// No matches at all.
incomplete
}
Expand Down Expand Up @@ -827,6 +836,36 @@ mod test {
assert!(buf.is_empty());
}

#[test]
fn urc_prefixed_with_garbage() {
let mut digester = AtDigester::<UrcTestParser>::new();
let mut buf = heapless::Vec::<u8, TEST_RX_BUF_LEN>::new();

buf.extend_from_slice(b"aaaa\r\n+UUSORD: 0,5\r\n").unwrap();
let (res, bytes) = digester.digest(&buf);

assert_eq!((res, bytes), (DigestResult::Urc(b"+UUSORD: 0,5"), 20));
buf.rotate_left(bytes);
buf.truncate(buf.len() - bytes);
assert!(buf.is_empty());
}

#[test]
fn urc_prefixed_with_garbage_including_newline() {
let mut digester = AtDigester::<UrcTestParser>::new();
let mut buf = heapless::Vec::<u8, TEST_RX_BUF_LEN>::new();

buf.extend_from_slice(
b"a\r\na\r\n+UUSORD: 0,5\r\n", // 20 bytes
)
.unwrap();
let (res, bytes) = digester.digest(&buf);
assert_eq!((res, bytes), (DigestResult::Urc(b"+UUSORD: 0,5"), 20));
buf.rotate_left(bytes);
buf.truncate(buf.len() - bytes);
assert!(buf.is_empty());
}

#[test]
fn response_no_echo() {
let mut digester = AtDigester::<UrcTestParser>::new();
Expand Down

0 comments on commit a81487b

Please sign in to comment.