coremem_types: enumerated: allow folding the enum into the first element
This commit is contained in:
@@ -1,13 +1,25 @@
|
|||||||
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano, PeanoNonZero, PNext};
|
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano, PeanoNonZero, PNext};
|
||||||
use crate::compound::list::{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
|
||||||
|
pub trait DiscriminantCodable<P: Peano> {
|
||||||
|
fn discr(&self) -> Discr<P>;
|
||||||
|
}
|
||||||
|
|
||||||
// discriminant which encodes up to *and including* P.
|
// discriminant which encodes up to *and including* P.
|
||||||
pub struct Discr<P: Peano>(u32, PhantomData<P>);
|
#[derive(Copy, Clone, Default, PartialEq)]
|
||||||
|
pub struct Discr<P: Peano>(u32, P::Unit);
|
||||||
|
|
||||||
|
impl<P: Peano> DiscriminantCodable<P> for Discr<P> {
|
||||||
|
fn discr(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<P: Peano> Discr<P> {
|
impl<P: Peano> Discr<P> {
|
||||||
fn new_unchecked(u: u32) -> Self {
|
fn new_unchecked(u: u32) -> Self {
|
||||||
Self(u, PhantomData)
|
Self(u, Default::default())
|
||||||
}
|
}
|
||||||
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 {
|
||||||
@@ -33,59 +45,88 @@ pub trait VariantHandler<N: Peano> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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) variant of E
|
||||||
struct EnumDispatch<'a, E, F> {
|
struct DispatchIndexable<'a, I, F> {
|
||||||
enum_: &'a E,
|
indexable: &'a I,
|
||||||
f: F,
|
f: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E, F> EnumDispatch<'a, E, F> {
|
impl<'a, I, F> DispatchIndexable<'a, I, F> {
|
||||||
fn new(enum_: &'a E, f: F) -> Self {
|
fn new(indexable: &'a I, f: F) -> Self {
|
||||||
Self { enum_, f }
|
Self { indexable, f }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, L, F> DiscrHandler<P0> for EnumDispatch<'a, Enum<L>, F>
|
impl<'a, I, F> DiscrHandler<P0> for DispatchIndexable<'a, I, F>
|
||||||
where
|
where
|
||||||
L: Indexable<P0>,
|
I: Indexable<P0>,
|
||||||
L::Element: Copy,
|
I::Element: Copy,
|
||||||
F: VariantHandler<P0, Args=L::Element>,
|
F: VariantHandler<P0, Args=I::Element>,
|
||||||
{
|
{
|
||||||
type Output = F::Output;
|
type Output = F::Output;
|
||||||
type PrevOrPanic = Self;
|
type PrevOrPanic = Self;
|
||||||
fn call(self) -> Self::Output {
|
fn call(self) -> Self::Output {
|
||||||
self.f.call(self.enum_.0.get())
|
self.f.call(self.indexable.get())
|
||||||
}
|
}
|
||||||
fn prev(self) -> Self::PrevOrPanic {
|
fn prev(self) -> Self::PrevOrPanic {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, L, F, P: Peano> DiscrHandler<PNext<P>> for EnumDispatch<'a, Enum<L>, F>
|
impl<'a, I, F, P: Peano> DiscrHandler<PNext<P>> for DispatchIndexable<'a, I, F>
|
||||||
where
|
where
|
||||||
L: Indexable<PNext<P>>,
|
I: Indexable<PNext<P>>,
|
||||||
L::Element: Copy,
|
I::Element: Copy,
|
||||||
F: VariantHandler<PNext<P>, Args=L::Element, Output=<Self as DiscrHandler<P>>::Output>,
|
F: VariantHandler<PNext<P>, Args=I::Element, Output=<Self as DiscrHandler<P>>::Output>,
|
||||||
Self: DiscrHandler<P>,
|
Self: DiscrHandler<P>,
|
||||||
{
|
{
|
||||||
type Output = F::Output;
|
type Output = F::Output;
|
||||||
type PrevOrPanic = Self;
|
type PrevOrPanic = Self;
|
||||||
fn call(self) -> Self::Output {
|
fn call(self) -> Self::Output {
|
||||||
self.f.call(self.enum_.0.get())
|
self.f.call(self.indexable.get())
|
||||||
}
|
}
|
||||||
fn prev(self) -> Self::PrevOrPanic {
|
fn prev(self) -> Self::PrevOrPanic {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Enum<L>(L);
|
struct Enum<D, L>(D, L);
|
||||||
|
|
||||||
trait DiscriminantedEnum<P: Peano>: Sized {
|
trait EnumRequirements {
|
||||||
fn discr(&self) -> Discr<P>;
|
type MaxDiscr: Peano;
|
||||||
fn dispatch<'a, F>(&'a self, f: F) -> <EnumDispatch<'a, Self, F> as DiscrHandler<P>>::Output
|
fn discr(&self) -> Discr<Self::MaxDiscr>;
|
||||||
where
|
}
|
||||||
EnumDispatch<'a, Self, F>: DiscrHandler<P>
|
|
||||||
{
|
impl<D, L> EnumRequirements for Enum<(D,), L>
|
||||||
self.discr().dispatch(EnumDispatch::new(self, f))
|
where
|
||||||
|
D: DiscriminantCodable<<<L as list::Meta>::Length as PeanoNonZero>::Prev>,
|
||||||
|
L: list::Meta,
|
||||||
|
{
|
||||||
|
type MaxDiscr = <<L as list::Meta>::Length as PeanoNonZero>::Prev;
|
||||||
|
fn discr(&self) -> Discr<Self::MaxDiscr> {
|
||||||
|
self.0.0.discr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L> EnumRequirements for Enum<(), L>
|
||||||
|
where
|
||||||
|
L: list::Meta + Indexable<P0>,
|
||||||
|
list::ElementAt<P0, L>: Copy + DiscriminantCodable<<<L as list::Meta>::Length as PeanoNonZero>::Prev>,
|
||||||
|
{
|
||||||
|
type MaxDiscr = <<L as list::Meta>::Length as PeanoNonZero>::Prev;
|
||||||
|
fn discr(&self) -> Discr<Self::MaxDiscr> {
|
||||||
|
self.1.get().discr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<D, L> Enum<D, L>
|
||||||
|
where Self: EnumRequirements
|
||||||
|
{
|
||||||
|
fn dispatch<'a, F>(&'a self, f: F) -> <DispatchIndexable<'a, L, F> as DiscrHandler<<Self as EnumRequirements>::MaxDiscr>>::Output
|
||||||
|
where
|
||||||
|
DispatchIndexable<'a, L, F>: DiscrHandler<<Self as EnumRequirements>::MaxDiscr>
|
||||||
|
{
|
||||||
|
self.discr().dispatch(DispatchIndexable::new(&self.1, f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano};
|
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano, PeanoNonZero, PNext};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
@@ -96,3 +96,16 @@ impl<E0, E1, E2, E3> IntoList for (E0, E1, E2, E3) {
|
|||||||
Node::new(self.0, (self.1, self.2, self.3).into_list())
|
Node::new(self.0, (self.1, self.2, self.3).into_list())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Meta {
|
||||||
|
type Length: PeanoNonZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H> Meta for Node<H, Null> {
|
||||||
|
type Length = P1;
|
||||||
|
}
|
||||||
|
impl<H, T: Meta> Meta for Node<H, T> {
|
||||||
|
type Length = PNext<T::Length>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ElementAt<P, L> = <L as Indexable<P>>::Element;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#[derive(Default)]
|
#[derive(Copy, Clone, Default, PartialEq)]
|
||||||
pub struct PNext<P>(P);
|
pub struct PNext<P>(P);
|
||||||
#[derive(Default)]
|
#[derive(Copy, Clone, Default, PartialEq)]
|
||||||
pub struct P0;
|
pub struct P0;
|
||||||
|
|
||||||
pub type P1 = PNext<P0>;
|
pub type P1 = PNext<P0>;
|
||||||
@@ -11,9 +11,12 @@ pub type P5 = PNext<P4>;
|
|||||||
pub type P6 = PNext<P5>;
|
pub type P6 = PNext<P5>;
|
||||||
pub type P7 = PNext<P6>;
|
pub type P7 = PNext<P6>;
|
||||||
|
|
||||||
pub trait Peano: Default {
|
pub trait Peano: Copy + Clone + Default + PartialEq {
|
||||||
type Next: PeanoNonZero;
|
type Next: PeanoNonZero;
|
||||||
type PrevOrZero: Peano;
|
type PrevOrZero: Peano;
|
||||||
|
/// always set to ()
|
||||||
|
/// this exists to allow Peano numbers to be used as struct parameters without PhantomData
|
||||||
|
type Unit: Copy + Clone + Default + PartialEq;
|
||||||
const VALUE: u32;
|
const VALUE: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,11 +27,13 @@ pub trait PeanoNonZero: Peano {
|
|||||||
impl Peano for P0 {
|
impl Peano for P0 {
|
||||||
type Next = P1;
|
type Next = P1;
|
||||||
type PrevOrZero = P0;
|
type PrevOrZero = P0;
|
||||||
|
type Unit = ();
|
||||||
const VALUE: u32 = 0;
|
const VALUE: u32 = 0;
|
||||||
}
|
}
|
||||||
impl<P: Peano> Peano for PNext<P> {
|
impl<P: Peano> Peano for PNext<P> {
|
||||||
type Next = PNext<PNext<P>>;
|
type Next = PNext<PNext<P>>;
|
||||||
type PrevOrZero = P;
|
type PrevOrZero = P;
|
||||||
|
type Unit = ();
|
||||||
const VALUE: u32 = 1 + P::VALUE;
|
const VALUE: u32 = 1 + P::VALUE;
|
||||||
}
|
}
|
||||||
impl<P: Peano> PeanoNonZero for PNext<P> {
|
impl<P: Peano> PeanoNonZero for PNext<P> {
|
||||||
|
Reference in New Issue
Block a user