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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user