#![no_std]
#![warn(missing_docs)]
extern crate self as cantor;
pub mod uint;
pub mod array;
mod compress;
mod map;
mod set;
pub use cantor_macros::*;
pub use compress::*;
pub use map::*;
pub use set::*;
use core::marker::PhantomData;
pub unsafe trait Finite: Ord + Clone + Sized {
const COUNT: usize;
fn index_of(value: Self) -> usize;
fn nth(index: usize) -> Option<Self>;
fn iter() -> FiniteIter<Self> {
FiniteIter {
index: 0,
marker: PhantomData
}
}
}
pub struct FiniteIter<T: Finite> {
index: usize,
marker: PhantomData<fn() -> T>
}
impl<T: Finite> Iterator for FiniteIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let res = T::nth(self.index);
self.index += 1;
res
}
fn size_hint(&self) -> (usize, Option<usize>) {
let rem = T::COUNT - self.index;
(rem, Some(rem))
}
}
unsafe impl Finite for () {
const COUNT: usize = 1;
fn index_of(_: Self) -> usize {
0
}
fn nth(index: usize) -> Option<Self> {
if index == 0 {
Some(())
} else {
None
}
}
}
unsafe impl Finite for bool {
const COUNT: usize = 2;
fn index_of(value: Self) -> usize {
value as usize
}
fn nth(index: usize) -> Option<Self> {
match index {
0 => Some(false),
1 => Some(true),
_ => None,
}
}
}
unsafe impl Finite for u8 {
const COUNT: usize = 1 << 8;
fn index_of(value: Self) -> usize {
value as usize
}
fn nth(index: usize) -> Option<Self> {
if index < Self::COUNT {
Some(index as u8)
} else {
None
}
}
}
unsafe impl Finite for u16 {
const COUNT: usize = 1 << 16;
fn index_of(value: Self) -> usize {
value as usize
}
fn nth(index: usize) -> Option<Self> {
if index < Self::COUNT {
Some(index as u16)
} else {
None
}
}
}
unsafe impl<T: Finite> Finite for Option<T> {
const COUNT: usize = 1 + T::COUNT;
fn index_of(value: Self) -> usize {
match value {
Some(value) => 1 + T::index_of(value),
None => 0
}
}
fn nth(index: usize) -> Option<Self> {
if index == 0 {
Some(None)
} else if index < Self::COUNT {
Some(T::nth(index - 1))
} else {
None
}
}
}
unsafe impl<A: Finite, B: Finite> Finite for (A, B) {
const COUNT: usize = A::COUNT * B::COUNT;
fn index_of(value: Self) -> usize {
A::index_of(value.0) * B::COUNT + B::index_of(value.1)
}
fn nth(index: usize) -> Option<Self> {
if index < Self::COUNT {
Some((
A::nth(index / B::COUNT).unwrap(),
B::nth(index % B::COUNT).unwrap(),
))
} else {
None
}
}
}
#[macro_export]
macro_rules! impl_concrete_finite {
($t:ty) => {
unsafe impl ::cantor::CompressFinite for $t {
type Index = ::cantor::uint::Uint<{
::cantor::uint::log2(<$t as ::cantor::Finite>::COUNT - 1)
}>;
}
unsafe impl<V> ::cantor::ArrayFinite<V> for $t {
type Array = [V; <$t as ::cantor::Finite>::COUNT];
}
unsafe impl ::cantor::BitmapFinite for $t
where
for<'a> ::cantor::uint::NumBits<'a, { <$t as ::cantor::Finite>::COUNT }>:
::cantor::uint::HasUint
{
type Bitmap = ::cantor::uint::Uint<{ <$t as ::cantor::Finite>::COUNT }>;
}
};
}
impl_concrete_finite!(());
impl_concrete_finite!(bool);
impl_concrete_finite!(u8);
impl_concrete_finite!(u16);
#[cfg(test)]
mod tests;