#![no_std]
#![warn(missing_docs)]
mod arithmetic;
mod eq;
mod iter;
pub mod prelude {
pub use crate::{slist, Slist, SlistAsRef, SlistFlatten, SlistMap, SlistReverse, SlistSum};
}
mod as_ref;
mod flatten;
mod map;
mod reverse;
pub use as_ref::SlistAsRef;
pub use flatten::SlistFlatten;
pub use map::SlistMap;
pub use reverse::SlistReverse;
pub use slist_derive::slist_typegen;
use core::cmp::Ordering;
use core::fmt::{self, Display, Formatter};
use core::ops::{Add, Index, IndexMut};
pub trait Slist<T>: Sized {
const MAXLEN: usize = 0;
type Filter;
#[inline]
fn filter<F: FnMut(&T) -> bool>(self, _f: F) -> Either<Self, Self::Filter> {
Either::Left(self)
}
#[inline]
fn foldr<U, F: FnMut(U, T) -> U>(self, acc: U, _f: &mut F) -> U {
acc
}
#[inline]
fn foldl<U, F: FnMut(U, T) -> U>(self, acc: U, _f: F) -> U {
acc
}
#[inline]
fn for_each<F: FnMut(T)>(self, _f: F) {}
#[inline]
fn sum<U>(self) -> U
where
U: Add<T, Output = U> + Default,
{
self.foldl(U::default(), U::add)
}
#[inline]
fn get(&self, _index: usize) -> Option<&T> {
None
}
#[inline]
fn get_mut(&mut self, _index: usize) -> Option<&mut T> {
None
}
#[inline]
fn view(&self, _f: &mut Formatter<'_>) -> fmt::Result
where
T: Display,
{
Ok(())
}
#[inline]
fn len(&self) -> usize {
Self::MAXLEN
}
#[inline]
fn is_empty(&self) -> bool {
true
}
}
#[derive(Debug, Default)]
pub struct List<T, N: Slist<T>> {
tail: N,
head: T,
}
#[derive(Debug)]
pub enum Either<N, M> {
Left(N),
Right(M),
}
#[derive(Debug)]
pub enum Void {}
impl<T> Slist<T> for Void {
type Filter = Void;
}
impl<T> Slist<T> for () {
type Filter = Void;
}
impl<T, N: Slist<T, Filter = S>, S: SlistSum<T, Next = N>> Slist<T> for List<T, N> {
const MAXLEN: usize = 1 + N::MAXLEN;
type Filter = Either<N, N::Filter>;
#[inline]
fn foldr<U, F: FnMut(U, T) -> U>(self, acc: U, f: &mut F) -> U {
let acc = self.tail.foldr(acc, f);
f(acc, self.head)
}
#[inline]
fn foldl<U, F: FnMut(U, T) -> U>(self, acc: U, mut f: F) -> U {
self.tail.foldl(f(acc, self.head), f)
}
#[inline]
fn filter<F: FnMut(&T) -> bool>(self, mut f: F) -> Either<Self, Self::Filter> {
let (head, tail) = self.pop();
if f(&head) {
tail.filter(f).push(head)
} else {
Either::Right(tail.filter(f))
}
}
#[inline]
fn for_each<F: FnMut(T)>(self, mut f: F) {
f(self.head);
self.tail.for_each(f);
}
#[inline]
fn get(&self, index: usize) -> Option<&T> {
match index.cmp(&(Self::MAXLEN - 1)) {
Ordering::Greater => None,
Ordering::Equal => Some(&self.head),
Ordering::Less => self.tail.get(index),
}
}
#[inline]
fn get_mut(&mut self, index: usize) -> Option<&mut T> {
match index.cmp(&(Self::MAXLEN - 1)) {
Ordering::Greater => None,
Ordering::Equal => Some(&mut self.head),
Ordering::Less => self.tail.get_mut(index),
}
}
#[inline]
fn view(&self, f: &mut Formatter<'_>) -> fmt::Result
where
T: Display,
{
self.tail.view(f)?;
write!(f, "{}, ", &self.head)
}
#[inline]
fn is_empty(&self) -> bool {
false
}
}
impl<T, N: Slist<T>, M: Slist<T>> Slist<T> for Either<N, M> {
const MAXLEN: usize = [N::MAXLEN, M::MAXLEN][(N::MAXLEN < M::MAXLEN) as usize];
type Filter = Either<N::Filter, M::Filter>;
#[inline]
fn foldr<U, F: FnMut(U, T) -> U>(self, acc: U, f: &mut F) -> U {
match self {
Either::Left(n) => n.foldr(acc, f),
Either::Right(m) => m.foldr(acc, f),
}
}
#[inline]
fn foldl<U, F: FnMut(U, T) -> U>(self, acc: U, f: F) -> U {
match self {
Either::Left(n) => n.foldl(acc, f),
Either::Right(m) => m.foldl(acc, f),
}
}
#[inline]
fn filter<F: FnMut(&T) -> bool>(self, f: F) -> Either<Self, Self::Filter> {
match self {
Either::Left(n) => match n.filter(f) {
Either::Left(l) => Either::Left(Either::Left(l)),
Either::Right(r) => Either::Right(Either::Left(r)),
},
Either::Right(m) => match m.filter(f) {
Either::Left(l) => Either::Left(Either::Right(l)),
Either::Right(r) => Either::Right(Either::Right(r)),
},
}
}
#[inline]
fn for_each<F: FnMut(T)>(self, f: F) {
match self {
Either::Left(n) => n.for_each(f),
Either::Right(m) => m.for_each(f),
}
}
#[inline]
fn get(&self, index: usize) -> Option<&T> {
match self {
Either::Left(n) => n.get(index),
Either::Right(m) => m.get(index),
}
}
#[inline]
fn get_mut(&mut self, index: usize) -> Option<&mut T> {
match self {
Either::Left(n) => n.get_mut(index),
Either::Right(m) => m.get_mut(index),
}
}
#[inline]
fn len(&self) -> usize {
match self {
Either::Left(n) => n.len(),
Either::Right(m) => m.len(),
}
}
#[inline]
fn is_empty(&self) -> bool {
match self {
Either::Left(n) => n.is_empty(),
Either::Right(m) => m.is_empty(),
}
}
}
pub trait SlistSum<T>: Slist<T> {
type Next: Slist<T>;
fn push(self, item: T) -> Either<Self::Next, Self>;
}
impl<T> SlistSum<T> for () {
type Next = List<T, ()>;
#[inline]
fn push(self, item: T) -> Either<Self::Next, ()> {
Either::Left(List::new(item))
}
}
impl<T> SlistSum<T> for Void {
type Next = ();
#[inline]
fn push(self, _: T) -> Either<Self::Next, Self> {
Either::Left(())
}
}
impl<T, N: Slist<T, Filter = S>, S: SlistSum<T, Next = N>> SlistSum<T> for Either<N, S> {
type Next = List<T, N>;
#[inline]
fn push(self, item: T) -> Either<Self::Next, Self> {
match self {
Either::Left(l) => Either::Left(List {
head: item,
tail: l,
}),
Either::Right(r) => Either::Right(r.push(item)),
}
}
}
impl<T> List<T, ()> {
#[inline]pub const
fn new(first: T) -> Self {
List {
head: first,
tail: (),
}
}
}
impl<T, N: Slist<T, Filter = S>, S: SlistSum<T, Next = N>> List<T, N> {
#[inline]pub
fn push(self, item: T) -> List<T, Self> {
List {
head: item,
tail: self,
}
}
#[inline]pub
fn pop(self) -> (T, N) {
(self.head, self.tail)
}
}
impl<T, N: Slist<T, Filter = S>, S: SlistSum<T, Next = N>> Index<usize> for List<T, N> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &T {
self.get(index).unwrap()
}
}
impl<T, N: Slist<T, Filter = S>, S: SlistSum<T, Next = N>> IndexMut<usize> for List<T, N> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut T {
self.get_mut(index).unwrap()
}
}
impl<T, N, M> Index<usize> for Either<N, M>
where
N: Slist<T> + Index<usize, Output = T>,
M: Slist<T> + Index<usize, Output = T>,
{
type Output = T;
#[inline]
fn index(&self, index: usize) -> &T {
match self {
Either::Left(n) => n.index(index),
Either::Right(m) => m.index(index),
}
}
}
impl<T, N, M> IndexMut<usize> for Either<N, M>
where
N: Slist<T> + Index<usize, Output = T> + IndexMut<usize>,
M: Slist<T> + Index<usize, Output = T> + IndexMut<usize>,
{
#[inline]
fn index_mut(&mut self, index: usize) -> &mut T {
match self {
Either::Left(n) => n.index_mut(index),
Either::Right(m) => m.index_mut(index),
}
}
}
impl<T: Display, N: Slist<T, Filter = S>, S: SlistSum<T, Next = N>> Display for List<T, N> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
self.tail.view(f)?;
write!(f, "{}]", &self.head)
}
}
impl<N: Display, M: Display> Display for Either<N, M> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Either::Left(n) => write!(f, "{}", &n),
Either::Right(m) => write!(f, "_{}", &m),
}
}
}
impl<T: Clone, N: Clone + Slist<T>> Clone for List<T, N> {
#[inline]
fn clone(&self) -> Self {
List {
head: self.head.clone(),
tail: self.tail.clone(),
}
}
}
impl<T: Copy, N: Copy + Slist<T>> Copy for List<T, N> {}
impl<N: Clone, M: Clone> Clone for Either<M, N> {
#[inline]
fn clone(&self) -> Self {
match self {
Either::Left(n) => Either::Left(n.clone()),
Either::Right(m) => Either::Right(m.clone()),
}
}
}
impl<N: Copy, M: Copy> Copy for Either<N, M> {}
impl<N, M: Default> Default for Either<N, M> {
#[inline]
fn default() -> Self {
Either::Right(M::default())
}
}
impl<N: Default> Default for Either<N, Void> {
#[inline]
fn default() -> Self {
Either::Left(Default::default())
}
}
#[macro_export]
macro_rules! slist {
($s:expr $(, $x:expr)*) => (
$crate::List::new($s)$(.push($x))*
);
($elem:expr; $n:expr) => (
{
use $crate::{slist_typegen, List, SlistMap};
let list: $crate::slist_typegen!($n) = Default::default();
list.map(|_| $elem)
}
);
}