coremem_types: Enum: add a basic test
This commit is contained in:
@@ -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 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> {
|
||||
fn decode_discr(&self) -> 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)]
|
||||
pub struct Discr<P: Peano>(u32, P::Unit);
|
||||
|
||||
@@ -25,10 +31,12 @@ impl<P: Peano> Discr<P> {
|
||||
fn new_unchecked(u: u32) -> Self {
|
||||
Self(u, Default::default())
|
||||
}
|
||||
}
|
||||
impl<P: Peano> Discr<P> {
|
||||
fn dispatch<H: DiscrHandler<P>>(&self, h: H) -> H::Output {
|
||||
match self.0 {
|
||||
v if v == P::VALUE => h.call(),
|
||||
less => Discr::<P::PrevOrZero>::new_unchecked(less).dispatch(h.prev()),
|
||||
v if v < P::PrevOrZero::VALUE => Discr::<P::PrevOrZero>::new_unchecked(v).dispatch(h.prev()),
|
||||
_equal => h.call(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,14 +49,7 @@ pub trait DiscrHandler<N: Peano> {
|
||||
fn prev(self) -> Self::PrevOrPanic;
|
||||
}
|
||||
|
||||
/// implement for something which supports being called for this specific variant
|
||||
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
|
||||
/// helper used to call F with some (yet-to-be-determined) index of I
|
||||
struct DispatchIndexable<'a, I, F> {
|
||||
indexable: &'a I,
|
||||
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>
|
||||
where
|
||||
I: Indexable<P0>,
|
||||
I::Element: Copy,
|
||||
F: VariantHandler<P0, Args=I::Element>,
|
||||
F: VariantHandler<P0, I::Element>,
|
||||
{
|
||||
type Output = F::Output;
|
||||
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>
|
||||
where
|
||||
I: Indexable<PNext<P>>,
|
||||
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>,
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user