use crate::fab::{AlignedValue, AlignedValueSlice, Alignment, AlignmentAtom};
use crate::hash::{HashOutput, PERSISTENT_HASH_BYTES as PHB};
pub trait Aligned {
fn alignment() -> Alignment;
}
pub trait DynAligned {
fn dyn_alignment(&self) -> Alignment;
}
impl<T: Aligned> DynAligned for T {
fn dyn_alignment(&self) -> Alignment {
T::alignment()
}
}
macro_rules! tuple_aligned {
() => {
impl Aligned for () {
fn alignment() -> Alignment {
Alignment(Vec::new())
}
}
};
($a:ident$(, $as:ident)*) => {
impl<$a: Aligned$(, $as: Aligned)*> Aligned for ($a$(, $as)* ,) {
fn alignment() -> Alignment {
Alignment::concat([&$a::alignment()$(, &$as::alignment())*])
}
}
tuple_aligned!($($as),*);
}
}
tuple_aligned!(A, B, C, D, E, F, G, H, I, J, K);
macro_rules! fixed_bytes_aligned {
($($ty:ty; $size:expr_2021),*) => {
$(
impl Aligned for $ty {
fn alignment() -> Alignment {
Alignment::singleton(AlignmentAtom::Bytes { length: $size as u32 })
}
}
)*
}
}
fixed_bytes_aligned!(
HashOutput; PHB,
bool; 1,
u8; 1,
u16; 2,
u32; 4,
u64; 8,
u128; 16
);
impl<const N: usize> Aligned for [u8; N] {
fn alignment() -> Alignment {
Alignment::singleton(AlignmentAtom::Bytes { length: N as u32 })
}
}
impl Aligned for &[u8] {
fn alignment() -> Alignment {
Alignment::singleton(AlignmentAtom::Compress)
}
}
impl Aligned for Vec<u8> {
fn alignment() -> Alignment {
Alignment::singleton(AlignmentAtom::Compress)
}
}
impl<T: Aligned> Aligned for Option<T> {
fn alignment() -> Alignment {
Alignment::concat([&bool::alignment(), &T::alignment()])
}
}
impl Alignment {
pub fn option_of(&self) -> Alignment {
Alignment::concat([&bool::alignment(), self])
}
}
impl DynAligned for AlignedValue {
fn dyn_alignment(&self) -> Alignment {
self.alignment.clone()
}
}
impl DynAligned for AlignedValueSlice<'_> {
fn dyn_alignment(&self) -> Alignment {
self.1.clone()
}
}