awdl_frame_parser/common/
awdl_str.rs

1use core::ops::{Deref, DerefMut};
2
3use scroll::{
4    ctx::{MeasureWith, StrCtx, TryFromCtx, TryIntoCtx},
5    Pread, Pwrite,
6};
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
9/// A string in the format used by AWDL.
10/// The characters are preceeded by a length byte.
11pub struct AWDLStr<'a>(pub &'a str);
12impl<'a> AWDLStr<'a> {
13    pub const fn size_in_bytes(&'a self) -> usize {
14        self.0.len() + 1
15    }
16}
17impl<'a> MeasureWith<()> for AWDLStr<'a> {
18    fn measure_with(&self, _ctx: &()) -> usize {
19        self.size_in_bytes()
20    }
21}
22impl<'a> TryFromCtx<'a> for AWDLStr<'a> {
23    type Error = scroll::Error;
24    fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
25        let mut offset = 0;
26
27        let length = from.gread::<u8>(&mut offset)? as usize;
28        let str = from.gread_with::<&'a str>(&mut offset, StrCtx::Length(length))?;
29        Ok((Self(str), offset))
30    }
31}
32impl<'a> TryIntoCtx for AWDLStr<'a> {
33    type Error = scroll::Error;
34    fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
35        let mut offset = 0;
36        if self.len() >= u8::MAX as usize {
37            return Err(scroll::Error::TooBig {
38                size: u8::MAX as usize,
39                len: self.len(),
40            });
41        }
42        buf.gwrite(self.0.len() as u8, &mut offset)?;
43        buf.gwrite(self.0, &mut offset)?;
44        Ok(offset)
45    }
46}
47impl<'a> Deref for AWDLStr<'a> {
48    type Target = &'a str;
49    fn deref(&self) -> &Self::Target {
50        &self.0
51    }
52}
53impl<'a> DerefMut for AWDLStr<'a> {
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.0
56    }
57}
58impl<'a> From<&'a str> for AWDLStr<'a> {
59    fn from(value: &'a str) -> Self {
60        Self(value)
61    }
62}
63#[cfg(test)]
64#[test]
65fn test_awdl_str() {
66    use alloc::vec;
67
68    let bytes = [0x06, 0x6c, 0x61, 0x6d, 0x62, 0x64, 0x61].as_slice();
69    let string = bytes.pread::<AWDLStr<'_>>(0).unwrap();
70    assert_eq!(string, "lambda".into());
71    let mut buf = vec![0x00; string.measure_with(&())];
72    let _ = buf.pwrite::<AWDLStr<'_>>(string, 0).unwrap();
73    assert_eq!(bytes, buf);
74}