awdl_frame_parser/common/
awdl_str.rs1use 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)]
9pub 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}