use crate::{Buf, BufError, BufMut, BufResult, Codec, Cursor};
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct u24(pub u32);
impl Codec for u24 {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
writer.write_u8((self.0 >> 16) as u8)?;
writer.write_u8((self.0 >> 8) as u8)?;
writer.write_u8(self.0 as u8)?;
Ok(())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let b0 = reader.read_u8()? as u32;
let b1 = reader.read_u8()? as u32;
let b2 = reader.read_u8()? as u32;
Ok(u24((b0 << 16) | (b1 << 8) | b2))
}
}
impl From<u32> for u24 {
fn from(val: u32) -> Self {
u24(val & 0x00FF_FFFF)
}
}
impl From<u24> for usize {
fn from(val: u24) -> Self {
val.0 as usize
}
}
pub trait LengthPrefix: Codec {
fn as_usize(&self) -> usize;
fn from_usize(val: usize) -> BufResult<Self>;
}
impl LengthPrefix for u8 {
fn as_usize(&self) -> usize {
*self as usize
}
fn from_usize(val: usize) -> BufResult<Self> {
val.try_into().map_err(|_| BufError::InvalidLength)
}
}
impl LengthPrefix for u16 {
fn as_usize(&self) -> usize {
*self as usize
}
fn from_usize(val: usize) -> BufResult<Self> {
val.try_into().map_err(|_| BufError::InvalidLength)
}
}
impl LengthPrefix for u24 {
fn as_usize(&self) -> usize {
self.0 as usize
}
fn from_usize(val: usize) -> BufResult<Self> {
if val > 0x00FF_FFFF {
return Err(BufError::InvalidLength);
}
Ok(u24(val as u32))
}
}
use std::marker::PhantomData;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TlsVec<T, P> {
pub items: Vec<T>,
_marker: PhantomData<P>,
}
impl<T, P> TlsVec<T, P> {
pub fn new(items: Vec<T>) -> Self {
Self {
items,
_marker: PhantomData,
}
}
}
impl<T: Codec, P: LengthPrefix> Codec for TlsVec<T, P> {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
let mut prefix = P::from_usize(0)?;
let initial_cursor_position = writer.position();
prefix.encode(writer, ())?;
let mid_position = writer.position();
let prefix_length = mid_position as isize - initial_cursor_position as isize;
if prefix_length < 0 {
return Err(BufError::UnexpectedValue);
}
for item in &self.items {
item.encode(writer, ())?;
}
let last_position = writer.position();
let data_length = last_position as isize - mid_position as isize;
if data_length < 0 {
return Err(BufError::UnexpectedValue);
}
writer.rewind(data_length as usize + prefix_length as usize)?;
prefix = P::from_usize(data_length as usize)?;
prefix.encode(writer, ())?;
writer.advance(data_length as usize)?;
Ok(())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let prefix = P::decode(reader, ())?;
let expected_bytes = prefix.as_usize();
let start_pos = reader.position();
let mut items = Vec::new();
while reader.position() - start_pos < expected_bytes {
items.push(T::decode(reader, ())?);
}
if reader.position() - start_pos > expected_bytes {
return Err(BufError::InvalidLength);
}
Ok(TlsVec::new(items))
}
}
#[cfg(test)]
mod tests {
#[test]
fn test() {}
}