first pass tlv (bad!)

This commit is contained in:
Alex Janka 2024-02-18 09:31:27 +11:00
parent c2aa1e15c7
commit 0aef7feb32
2 changed files with 409 additions and 0 deletions

View 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)
}
}

View 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()
}
}