use core::marker::PhantomData;
use typenum::Unsigned;
pub trait Size {
fn is_fixed() -> bool { Self::size().is_some() }
fn is_variable() -> bool { Self::size().is_none() }
fn size() -> Option<usize>;
}
impl<U: Unsigned> Size for U {
fn size() -> Option<usize> { Some(Self::to_usize()) }
}
pub struct VariableSize;
impl Size for VariableSize {
fn size() -> Option<usize> { None }
}
pub struct Add<A: Size, B: Size>(PhantomData<(A, B)>);
impl<A: Size, B: Size> Size for Add<A, B> {
fn size() -> Option<usize> {
match (A::size(), B::size()) {
(Some(a), Some(b)) => Some(a + b),
_ => None,
}
}
}
pub struct Mul<A: Size, B: Size>(PhantomData<(A, B)>);
impl<A: Size, B: Size> Size for Mul<A, B> {
fn size() -> Option<usize> {
match (A::size(), B::size()) {
(Some(a), Some(b)) => Some(a * b),
_ => None,
}
}
}
pub struct Div<A: Size, B: Size>(PhantomData<(A, B)>);
impl<A: Size, B: Size> Size for Div<A, B> {
fn size() -> Option<usize> {
match (A::size(), B::size()) {
(Some(a), Some(b)) => Some(a / b),
_ => None,
}
}
}
#[macro_export]
macro_rules! sum {
( $one:ty ) => ( $one );
( $first:ty, $( $rest:ty ),* ) => (
$crate::Add<$first, $crate::sum!($( $rest ),*)>
);
}