use crate::{PointerType, Position, Read, StaticSize, Write, Writer};
use derive_deref::Deref;
use std::{convert::TryInto, marker::PhantomData, mem::size_of};
pub trait DynamicStructIndexType:
num::Integer
+ num::FromPrimitive
+ num::ToPrimitive
+ Into<PointerType>
+ Clone
+ Copy
+ for<'a> Read<'a, Output = Self>
+ Write<Output = Self>
{
}
impl DynamicStructIndexType for u8 {}
impl DynamicStructIndexType for u16 {}
#[derive(Clone, Copy, Debug)]
pub struct DynamicStructIndexReader<'a, I>
where
I: DynamicStructIndexType,
{
bytes: &'a [u8],
position: Position<Self>,
marker: PhantomData<I>,
}
impl<'a, I> DynamicStructIndexReader<'a, I>
where
I: DynamicStructIndexType,
{
pub fn new(bytes: &'a [u8], position: Position<Self>) -> DynamicStructIndexReader<'a, I> {
DynamicStructIndexReader {
bytes,
position,
marker: PhantomData,
}
}
pub fn field_count(&self) -> DynamicStructIndexFieldCount<I> {
let field_count_position = self.position.offset(0);
DynamicStructIndexFieldCount::read(self.bytes, field_count_position)
}
pub fn get_field_offset(
&self,
field_id: DynamicStructIndexFieldId<I>,
) -> DynamicStructIndexFieldOffset<I> {
let offset = size_of::<DynamicStructIndexFieldCount<I>>()
+ size_of::<DynamicStructIndexFieldOffset<I>>() * field_id.to_usize().unwrap();
let offset = offset.try_into().unwrap();
DynamicStructIndexFieldOffset::read(self.bytes, self.position.offset(offset))
}
}
#[derive(Debug, Deref, Clone, Copy)]
pub struct DynamicStructIndexPointer(pub PointerType);
#[derive(Debug, Deref, Clone, Copy)]
pub struct DynamicStructIndexFieldCount<I>(pub I)
where
I: DynamicStructIndexType;
#[derive(Debug, Deref, Clone, Copy, Hash, PartialEq, Eq)]
pub struct DynamicStructIndexFieldOffset<I>(pub I)
where
I: DynamicStructIndexType;
#[derive(Debug, Deref, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct DynamicStructIndexFieldId<I>(pub I)
where
I: DynamicStructIndexType;
impl<'a> StaticSize for DynamicStructIndexPointer {
const STATIC_SIZE: PointerType = size_of::<PointerType>() as PointerType;
}
impl<'a> Read<'a> for DynamicStructIndexPointer {
type Output = Self;
fn read(bytes: &'a [u8], position: Position<Self>) -> Self {
DynamicStructIndexPointer(PointerType::read(bytes, position.cast()))
}
}
impl Write for DynamicStructIndexPointer {
type Output = bool;
fn write(&self, writer: &mut Writer) -> Position<Self::Output> {
writer.write(&self.0).cast()
}
}
impl<'a, I> StaticSize for DynamicStructIndexFieldCount<I>
where
I: DynamicStructIndexType,
{
const STATIC_SIZE: PointerType = 2;
}
impl<'a, I> Read<'a> for DynamicStructIndexFieldCount<I>
where
I: DynamicStructIndexType,
{
type Output = Self;
fn read(bytes: &'a [u8], position: Position<Self>) -> Self {
DynamicStructIndexFieldCount(I::read(bytes, position.cast()))
}
}
impl<I> Write for DynamicStructIndexFieldCount<I>
where
I: DynamicStructIndexType,
{
type Output = Self;
fn write(&self, writer: &mut Writer) -> Position<Self::Output> {
writer.write(&self.0).cast()
}
}
impl<'a, I> StaticSize for DynamicStructIndexFieldOffset<I>
where
I: DynamicStructIndexType,
{
const STATIC_SIZE: PointerType = 2;
}
impl<'a, I> Read<'a> for DynamicStructIndexFieldOffset<I>
where
I: DynamicStructIndexType,
{
type Output = Self;
fn read(bytes: &'a [u8], position: Position<Self>) -> Self::Output {
DynamicStructIndexFieldOffset(I::read(bytes, position.cast()))
}
}
impl<I> Write for DynamicStructIndexFieldOffset<I>
where
I: DynamicStructIndexType,
{
type Output = Self;
fn write(&self, writer: &mut Writer) -> Position<Self::Output> {
writer.write(&self.0).cast()
}
}