coremem_types: Enum: add a basic test

This commit is contained in:
2022-07-21 20:35:30 -07:00
parent b8a36c87a6
commit 3541ab14c1

View File

@@ -2,13 +2,19 @@ use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano, PeanoNonZero, PNex
use crate::compound::list::{self, Indexable, IntoList, List}; use crate::compound::list::{self, Indexable, IntoList, List};
use core::marker::PhantomData; use core::marker::PhantomData;
// anything which can encode a discriminant up to *and including* P /// implement for something which supports being called for this specific variant
pub trait VariantHandler<N: Peano, Arg> {
type Output;
fn call(&self, a: Arg) -> Self::Output;
}
/// anything which can encode a discriminant up to *and including* P
pub trait DiscriminantCodable<P: Peano> { pub trait DiscriminantCodable<P: Peano> {
fn decode_discr(&self) -> Discr<P>; fn decode_discr(&self) -> Discr<P>;
fn encode_discr(&mut self, d: Discr<P>); fn encode_discr(&mut self, d: Discr<P>);
} }
// decode_discriminant which encodes up to *and including* P. /// discriminant which encodes up to *and including* P.
#[derive(Copy, Clone, Default, PartialEq)] #[derive(Copy, Clone, Default, PartialEq)]
pub struct Discr<P: Peano>(u32, P::Unit); pub struct Discr<P: Peano>(u32, P::Unit);
@@ -25,10 +31,12 @@ impl<P: Peano> Discr<P> {
fn new_unchecked(u: u32) -> Self { fn new_unchecked(u: u32) -> Self {
Self(u, Default::default()) Self(u, Default::default())
} }
}
impl<P: Peano> Discr<P> {
fn dispatch<H: DiscrHandler<P>>(&self, h: H) -> H::Output { fn dispatch<H: DiscrHandler<P>>(&self, h: H) -> H::Output {
match self.0 { match self.0 {
v if v == P::VALUE => h.call(), v if v < P::PrevOrZero::VALUE => Discr::<P::PrevOrZero>::new_unchecked(v).dispatch(h.prev()),
less => Discr::<P::PrevOrZero>::new_unchecked(less).dispatch(h.prev()), _equal => h.call(),
} }
} }
} }
@@ -41,14 +49,7 @@ pub trait DiscrHandler<N: Peano> {
fn prev(self) -> Self::PrevOrPanic; fn prev(self) -> Self::PrevOrPanic;
} }
/// implement for something which supports being called for this specific variant /// helper used to call F with some (yet-to-be-determined) index of I
pub trait VariantHandler<N: Peano> {
type Output;
type Args;
fn call(&self, a: Self::Args) -> Self::Output;
}
/// helper used to call F with some (yet-to-be-determined) variant of E
struct DispatchIndexable<'a, I, F> { struct DispatchIndexable<'a, I, F> {
indexable: &'a I, indexable: &'a I,
f: F, f: F,
@@ -60,11 +61,12 @@ impl<'a, I, F> DispatchIndexable<'a, I, F> {
} }
} }
// base case: anything which is zero-indexable can be dispatched
impl<'a, I, F> DiscrHandler<P0> for DispatchIndexable<'a, I, F> impl<'a, I, F> DiscrHandler<P0> for DispatchIndexable<'a, I, F>
where where
I: Indexable<P0>, I: Indexable<P0>,
I::Element: Copy, I::Element: Copy,
F: VariantHandler<P0, Args=I::Element>, F: VariantHandler<P0, I::Element>,
{ {
type Output = F::Output; type Output = F::Output;
type PrevOrPanic = Self; type PrevOrPanic = Self;
@@ -76,11 +78,13 @@ where
} }
} }
// inductive case: if we know how dispatch up through P, and the collection is P+1-indexable, then we can
// index up through P+1
impl<'a, I, F, P: Peano> DiscrHandler<PNext<P>> for DispatchIndexable<'a, I, F> impl<'a, I, F, P: Peano> DiscrHandler<PNext<P>> for DispatchIndexable<'a, I, F>
where where
I: Indexable<PNext<P>>, I: Indexable<PNext<P>>,
I::Element: Copy, I::Element: Copy,
F: VariantHandler<PNext<P>, Args=I::Element, Output=<Self as DiscrHandler<P>>::Output>, F: VariantHandler<PNext<P>, I::Element, Output=<Self as DiscrHandler<P>>::Output>,
Self: DiscrHandler<P>, Self: DiscrHandler<P>,
{ {
type Output = F::Output; type Output = F::Output;
@@ -93,6 +97,9 @@ where
} }
} }
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "fmt", derive(Debug))]
#[derive(Copy, Clone, Default, PartialEq)]
struct Enum<D, L>(D, L); struct Enum<D, L>(D, L);
trait EnumRequirements { trait EnumRequirements {
@@ -141,3 +148,23 @@ where Self: EnumRequirements
} }
} }
#[cfg(test)]
mod test {
use super::*;
#[test]
fn dispatch() {
struct Receiver {
returns: f32,
}
impl<P: Peano, T> VariantHandler<P, T> for Receiver {
type Output = f32;
fn call(&self, _: T) -> f32 {
self.returns
}
}
let e: Enum<(Discr<P1>,), List<(u32, f32)>> = Enum::default();
let r = Receiver { returns: 5f32 };
assert_eq!(e.dispatch(r), 5f32);
}
}