use crate::common::AWDLVersion;
use macro_bits::serializable_enum;
use scroll::{
ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
Pread, Pwrite,
};
use super::{AWDLTLVType, AwdlTlv};
serializable_enum! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum AWDLDeviceClass: u8 {
#[default]
MacOS => 0x1,
IOS => 0x2,
WatchOS => 0x4,
TVOS => 0x8
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct VersionTLV {
pub version: AWDLVersion,
pub device_class: AWDLDeviceClass,
}
impl AwdlTlv for VersionTLV {
const TLV_TYPE: AWDLTLVType = AWDLTLVType::Version;
}
impl MeasureWith<()> for VersionTLV {
fn measure_with(&self, _ctx: &()) -> usize {
2
}
}
impl<'a> TryFromCtx<'a> for VersionTLV {
type Error = scroll::Error;
fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
let mut offset = 0;
let version = AWDLVersion::from_bits(from.gread(&mut offset)?);
let device_class = AWDLDeviceClass::from_bits(from.gread(&mut offset)?);
Ok((
Self {
version,
device_class,
},
offset,
))
}
}
impl TryIntoCtx for VersionTLV {
type Error = scroll::Error;
fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
let mut offset = 0;
buf.gwrite(self.version.into_bits(), &mut offset)?;
buf.gwrite(self.device_class.into_bits(), &mut offset)?;
Ok(offset)
}
}
#[cfg(test)]
#[test]
fn test_version_tlv() {
let bytes = [0x3e, 0x01];
let version_tlv = bytes.pread::<VersionTLV>(0).unwrap();
assert_eq!(
version_tlv,
VersionTLV {
version: AWDLVersion {
major: 3,
minor: 14
},
device_class: AWDLDeviceClass::MacOS,
}
);
let mut buf = [0x00; 2];
buf.pwrite(version_tlv, 0).unwrap();
assert_eq!(buf, bytes);
}