Skip to content

Commit

Permalink
Also handle non-quoted payloads
Browse files Browse the repository at this point in the history
  • Loading branch information
ijager committed Dec 6, 2023
1 parent fbfb30f commit f72537f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
20 changes: 14 additions & 6 deletions serde_at/src/de/length_delimited.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ use serde::{de, Deserialize, Deserializer};

/// Structure for parsing a length delimited bytes payload.
///
/// This assumes that the payload is quoted.
/// The quotes are in the byte stream but not counted in the length field.
/// This supports both quoted and non-quoted payloads.
/// For "quoted" payloads the length is assumed to be excluding the surrounding double quotes.
///
/// For example:
///
/// From this response: `+QMTRECV: 1,0,"topic",4,"ABCD"`
/// We can parse the last two parameters as a 'LengthDelimited' object:
/// For both this response: `+QMTRECV: 1,0,"topic",4,"ABCD"`
/// and this response: `+QTRECV: 1,0,"topic",4,ABCD`
///
/// We can parse the last two parameters as a 'LengthDelimited' object which yields:
/// `'4,"ABCD"' => LengthDelimited { len: 4, bytes: [65, 66, 67, 68] }`
///
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -56,8 +58,14 @@ impl<'de, const N: usize> de::Visitor<'de> for LengthDelimitedVisitor<N> {
let len = parse_len(&v[0..pos])
.map_err(|_| de::Error::custom("expected an unsigned int"))?;
// +1 to skip the comma after the length.
let start = pos + 1 + 1; // extra +1 to remove outer quotes
let end = start + len;
let mut start = pos + 1;
let mut end = start + len;
// Check if payload is surrounded by double quotes not included in len.
let slice_len = v.len();
if slice_len >= (end + 2) && (v[start] == b'"' && v[end + 1] == b'"') {
start += 1; // Extra +1 to remove first quote (")
end += 1; // Move end by 1 to compensate for the quote.
}
Ok(LengthDelimited {
len,
bytes: Bytes::from_slice(&v[start..end])
Expand Down
20 changes: 19 additions & 1 deletion serde_at/src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,25 @@ mod tests {
);
}

#[test]
fn length_delimited_no_quotes() {
#[derive(Clone, Debug, Deserialize)]
pub struct PayloadResponse {
pub ctx: u8, // Some other params
pub id: i8, // Some other params
pub payload: LengthDelimited<32>,
}

let res: PayloadResponse = crate::from_slice(b"1,-1,9,ABCD,1234").unwrap();
assert_eq!(res.ctx, 1);
assert_eq!(res.id, -1);
assert_eq!(res.payload.len, 9);
assert_eq!(
res.payload.bytes,
Bytes::<32>::from_slice(b"ABCD,1234").unwrap()
);
}

#[test]
fn length_delimited_json() {
#[derive(Clone, Debug, Deserialize)]
Expand All @@ -926,7 +945,6 @@ mod tests {
pub id: i8, // Some other params
pub payload: LengthDelimited<32>,
}
// This tests correct handling of commas in the payload.
let res: PayloadResponse =
crate::from_slice(b"1,-2,28,\"{\"cmd\": \"blink\", \"pin\": \"2\"}\"").unwrap();
assert_eq!(res.ctx, 1);
Expand Down

0 comments on commit f72537f

Please sign in to comment.