first pass tlv (bad!)
This commit is contained in:
parent
c2aa1e15c7
commit
0aef7feb32
151
homekit-controller/src/tlv8/data_types.rs
Normal file
151
homekit-controller/src/tlv8/data_types.rs
Normal file
|
@ -0,0 +1,151 @@
|
|||
use super::Tlv;
|
||||
|
||||
pub enum TlvType {
|
||||
Method,
|
||||
Identifier,
|
||||
Salt,
|
||||
PublicKey,
|
||||
Proof,
|
||||
EncryptedData,
|
||||
State,
|
||||
Error,
|
||||
RetryDelay,
|
||||
Certificate,
|
||||
Signature,
|
||||
Permissions,
|
||||
PermissionRegularUser,
|
||||
PermissionAdminUser,
|
||||
FragmentData,
|
||||
FragmentLast,
|
||||
SessionID,
|
||||
}
|
||||
|
||||
impl From<TlvType> for u8 {
|
||||
fn from(value: TlvType) -> Self {
|
||||
match value {
|
||||
TlvType::Method => 0,
|
||||
TlvType::Identifier => 1,
|
||||
TlvType::Salt => 2,
|
||||
TlvType::PublicKey => 3,
|
||||
TlvType::Proof => 4,
|
||||
TlvType::EncryptedData => 5,
|
||||
TlvType::State => 6,
|
||||
TlvType::Error => 7,
|
||||
TlvType::RetryDelay => 8,
|
||||
TlvType::Certificate => 9,
|
||||
TlvType::Signature => 10,
|
||||
TlvType::Permissions => 11,
|
||||
TlvType::PermissionRegularUser => 0,
|
||||
TlvType::PermissionAdminUser => 1,
|
||||
TlvType::FragmentData => 12,
|
||||
TlvType::FragmentLast => 13,
|
||||
TlvType::SessionID => 14,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TlvData {
|
||||
Bytes(Vec<u8>),
|
||||
Tlv8(Vec<Tlv>),
|
||||
Integer(TlvInteger),
|
||||
Float(f64),
|
||||
String(String),
|
||||
Uint(TlvUnsignedInteger),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TlvInteger {
|
||||
OneByte(i8),
|
||||
TwoBytes(i16),
|
||||
FourBytes(i32),
|
||||
EightBytes(i64),
|
||||
}
|
||||
|
||||
impl TlvInteger {
|
||||
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||
match self {
|
||||
TlvInteger::OneByte(v) => v.to_le_bytes().to_vec(),
|
||||
TlvInteger::TwoBytes(v) => v.to_le_bytes().to_vec(),
|
||||
TlvInteger::FourBytes(v) => v.to_le_bytes().to_vec(),
|
||||
TlvInteger::EightBytes(v) => v.to_le_bytes().to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for TlvData
|
||||
where
|
||||
T: Into<TlvInteger>,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
Self::Integer(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i8> for TlvInteger {
|
||||
fn from(value: i8) -> Self {
|
||||
Self::OneByte(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i16> for TlvInteger {
|
||||
fn from(value: i16) -> Self {
|
||||
Self::TwoBytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for TlvInteger {
|
||||
fn from(value: i32) -> Self {
|
||||
Self::FourBytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for TlvInteger {
|
||||
fn from(value: i64) -> Self {
|
||||
Self::EightBytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TlvUnsignedInteger {
|
||||
OneByte(u8),
|
||||
TwoBytes(u16),
|
||||
FourBytes(u32),
|
||||
EightBytes(u64),
|
||||
}
|
||||
|
||||
impl TlvUnsignedInteger {
|
||||
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||
match self {
|
||||
TlvUnsignedInteger::OneByte(v) => v.to_le_bytes().to_vec(),
|
||||
TlvUnsignedInteger::TwoBytes(v) => v.to_le_bytes().to_vec(),
|
||||
TlvUnsignedInteger::FourBytes(v) => v.to_le_bytes().to_vec(),
|
||||
TlvUnsignedInteger::EightBytes(v) => v.to_le_bytes().to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for TlvUnsignedInteger {
|
||||
fn from(value: u8) -> Self {
|
||||
Self::OneByte(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for TlvUnsignedInteger {
|
||||
fn from(value: u16) -> Self {
|
||||
Self::TwoBytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for TlvUnsignedInteger {
|
||||
fn from(value: u32) -> Self {
|
||||
Self::FourBytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for TlvUnsignedInteger {
|
||||
fn from(value: u64) -> Self {
|
||||
Self::EightBytes(value)
|
||||
}
|
||||
}
|
258
homekit-controller/src/tlv8/mod.rs
Normal file
258
homekit-controller/src/tlv8/mod.rs
Normal file
|
@ -0,0 +1,258 @@
|
|||
mod data_types;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[allow(unused)]
|
||||
pub use data_types::{TlvData, TlvInteger, TlvType, TlvUnsignedInteger};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
pub fn decode(data: &[u8]) -> Result<HashMap<u8, Vec<u8>>, TlvError> {
|
||||
let mut tlvs = HashMap::new();
|
||||
let mut data = data;
|
||||
|
||||
while data.len() > 0 {
|
||||
let tlv_len = (data[1] as usize) + 2;
|
||||
let current;
|
||||
(current, data) = data.split_at(tlv_len);
|
||||
|
||||
if data.len() < 3 {
|
||||
return Err(TlvError::TooShort);
|
||||
}
|
||||
|
||||
if data.len() < tlv_len {
|
||||
return Err(TlvError::WrongLength);
|
||||
}
|
||||
|
||||
let tlv_type = current[0];
|
||||
let tlv_data = current[2..].to_vec();
|
||||
tlvs.insert(tlv_type, tlv_data);
|
||||
}
|
||||
Ok(tlvs)
|
||||
}
|
||||
|
||||
fn decode_single(data: &[u8]) -> Result<(u8, Vec<u8>), TlvError> {
|
||||
let tlv_type = data[0];
|
||||
let tlv_len = data[1];
|
||||
let data = &data[2..];
|
||||
Ok((tlv_type, if tlv_len == 0 { vec![] } else { data.to_vec() }))
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum TlvError {
|
||||
#[error("too short")]
|
||||
TooShort,
|
||||
#[error("wrong length")]
|
||||
WrongLength,
|
||||
}
|
||||
|
||||
pub trait TlvEncode {
|
||||
fn encode(&self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
// impl<const N: usize> TlvEncode for &[(u8, Vec<u8>); N] {
|
||||
// fn encode(&self) -> Vec<u8> {
|
||||
// (*self as &[(u8, Vec<u8>)]).encode()
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T> TlvEncode for T
|
||||
where
|
||||
T: AsRef<[(u8, Vec<u8>)]>,
|
||||
{
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
self.as_ref()
|
||||
.iter()
|
||||
.flat_map(|(tlv_type, tlv_data)| {
|
||||
let length = tlv_data.len() as u32;
|
||||
let packets = tlv_data
|
||||
.chunks(255)
|
||||
.enumerate()
|
||||
.flat_map(|(packet_num, data)| {
|
||||
let mut packet = vec![*tlv_type];
|
||||
packet.push((length - 255 * (packet_num as u32)) as u8);
|
||||
packet.extend_from_slice(data);
|
||||
packet
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if packets.is_empty() {
|
||||
let mut first_packet = vec![*tlv_type];
|
||||
first_packet.extend_from_slice(&length.to_le_bytes());
|
||||
first_packet.push(0);
|
||||
first_packet
|
||||
} else {
|
||||
packets
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Tlv(u8, TlvData);
|
||||
|
||||
impl Tlv {
|
||||
pub fn new<A: Into<u8>>(tlv_type: A, tlv_data: TlvData) -> Self {
|
||||
Self(tlv_type.into(), tlv_data)
|
||||
}
|
||||
|
||||
pub fn encode(&self) -> Vec<u8> {
|
||||
let Tlv(tlv_type, data) = self;
|
||||
let bytes = match data {
|
||||
TlvData::Bytes(v) => v.clone(),
|
||||
TlvData::Tlv8(v) => todo!(),
|
||||
TlvData::Integer(v) => v.to_le_bytes(),
|
||||
TlvData::Float(v) => v.to_le_bytes().to_vec(),
|
||||
TlvData::String(v) => v.as_bytes().to_vec(),
|
||||
TlvData::Uint(v) => v.to_le_bytes(),
|
||||
};
|
||||
let length = bytes.len() as u32;
|
||||
let packets = bytes
|
||||
.chunks(255)
|
||||
.enumerate()
|
||||
.flat_map(|(packet_num, data)| {
|
||||
let mut packet = vec![*tlv_type];
|
||||
packet.push((length - 255 * (packet_num as u32)) as u8);
|
||||
packet.extend_from_slice(data);
|
||||
packet
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if packets.is_empty() {
|
||||
let mut first_packet = vec![*tlv_type];
|
||||
first_packet.extend_from_slice(&length.to_le_bytes());
|
||||
first_packet.push(0);
|
||||
first_packet
|
||||
} else {
|
||||
packets
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_single(data: &[u8]) -> Result<Self, TlvError> {
|
||||
let tlv_type = data[0];
|
||||
let tlv_len = data[1];
|
||||
let data = &data[2..];
|
||||
Ok(Self(
|
||||
tlv_type,
|
||||
TlvData::Bytes(if tlv_len == 0 { vec![] } else { data.to_vec() }),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn tlv_type(&self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn tlv_data(&self) -> &TlvData {
|
||||
&self.1
|
||||
}
|
||||
|
||||
pub fn is_type<T: Into<u8>>(&self, value: T) -> bool {
|
||||
self.0 == value.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvData {
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
match self {
|
||||
TlvData::Bytes(val) => val.clone(),
|
||||
TlvData::Tlv8(_val) => todo!(),
|
||||
TlvData::Integer(val) => val.to_le_bytes(),
|
||||
TlvData::Float(_val) => todo!(),
|
||||
TlvData::String(val) => val.as_bytes().to_vec(),
|
||||
TlvData::Uint(val) => val.to_le_bytes(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TlvEncodableData {
|
||||
fn encode_value(&self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl<const N: usize> TlvEncodableData for &[u8; N] {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
(*self as &[u8]).encode_value()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for &[u8] {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for i8 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for i16 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for i32 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for i64 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for isize {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for u8 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for u16 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for u32 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for u64 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for usize {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for f32 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for f64 {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl TlvEncodableData for String {
|
||||
fn encode_value(&self) -> Vec<u8> {
|
||||
self.as_bytes().to_vec()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue