use core::fmt;
use heapless_bytes::Bytes;
use serde::{de, Deserialize, Deserializer};
#[derive(Clone, Debug)]
pub struct LengthDelimited<const N: usize, const S: usize = 1> {
pub len: usize,
pub bytes: Bytes<N>,
}
impl<'de, const N: usize, const S: usize> Deserialize<'de> for LengthDelimited<N, S> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(2, LengthDelimitedVisitor::<N, S>) }
}
struct LengthDelimitedVisitor<const N: usize, const L: usize>;
impl<'de, const N: usize, const S: usize> de::Visitor<'de> for LengthDelimitedVisitor<N, S> {
type Value = LengthDelimited<N, S>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("length delimited bytes, e.g.: \"4,ABCD\"")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
v.iter()
.position(|&c| !c.is_ascii_digit())
.ok_or_else(|| de::Error::custom("expected a comma"))
.and_then(|pos| {
let len = parse_len(&v[0..pos])
.map_err(|_| de::Error::custom("expected an unsigned int"))?;
let mut start = pos + S;
let mut end = start + len;
let slice_len = v.len();
if slice_len >= (end + 2) && (v[start] == b'"' && v[end + 1] == b'"') {
start += 1; end += 1; }
Ok(LengthDelimited {
len,
bytes: Bytes::from_slice(&v[start..end])
.map_err(|_| de::Error::custom("incorrect slice size"))?,
})
})
}
}
fn parse_len(v: &[u8]) -> Result<usize, ()> {
let len_str: &str = core::str::from_utf8(v).map_err(|_| ())?;
len_str.parse().map_err(|_| ())
}