#![feature(tuple_trait, import_trait_associated_functions, never_type)]
#![no_std]
#![allow(mixed_script_confusables, confusable_idents)]
//! 
//!
//! start with [`Tupl`].
mod implementations;
mod picks;
/// Reverse a tuple.
pub trait Reverse: Tupl {
type Reversed: Tupl;
fn reverse(self) -> Self::Reversed;
}
#[doc(inline)]
pub use Reverse::{reverse, reverse as flip};
#[doc(inline)]
pub use Tupl::{
drop, head, head as left, head as fst, last, last as right, pick, take,
};
pub use picks::*;
/// Construct a tuple.
pub fn cons<T, Tup: Cons<T>>(x: T, y: Tup) -> Tup::Cons {
Tup::Cons::cons(x, y)
}
/// Construct a tuple, backwards.
pub fn snoc<T, Tup: Cons<T>>(x: Tup, y: T) -> Tup::Snoc {
Tup::Snoc::snoc(x, y)
}
/// alias for [`snoc`]
pub trait Push<T>: Tupl {
type Result;
/// ```
/// use ttools::*;
/// let x = (1, 2).push(3);
/// assert_eq!(x, ((1, 2, 3)));
/// ```
fn push(self, other: T) -> Self::Result;
}
/// alias for [`cons`]
pub trait With<T: Tupl> {
type Result;
/// ```
/// use ttools::*;
/// let x = 1.with((2, 3));
/// assert_eq!(x, ((1, 2, 3)));
/// ```
fn with(self, other: T) -> Self::Result;
}
// implemented for the constructed type
pub trait Cons<T>: Tupl {
/// (T, ..self)
type Cons: Tupl<Head = T, Tail = Self>;
/// (..self, T)
type Snoc: Tupl<Last = T, Init = Self>;
}
/// backing trait for [`take`].
pub trait TD<const N: usize>: Tupl {
/// self[N..]
type Drop: Tupl;
/// self[..N]
type Take: Tupl;
// self[LEN - N..]
type TakeB: Tupl;
/// self[..LEN - N]
type DropB: Tupl;
/// deconstruct
fn dropf(self) -> (Self::Take, Self::Drop);
/// deconstruct
fn dropb(self) -> (Self::DropB, Self::TakeB);
}
/// backing trait for [`pick`]
pub trait Pick<const N: usize>: Tupl {
/// `self[N]`
type At;
/// self[..N]
type L: Tupl;
/// self[N + 1..]
type R: Tupl;
/// reconstruct
fn repick(l: Self::L, at: Self::At, r: Self::R) -> Self;
/// deconstruct
fn depict(self) -> (Self::L, Self::At, Self::R);
}
/// Main tuple trait.
pub trait Tupl: core::marker::Tuple {
/// Refer to listmonster.
type Head;
/// Refer to listmonster.
type Last;
/// Refer to listmonster.
type Tail: Tupl;
/// Refer to listmonster.
type Init: Tupl;
/// Middle section of listmonster.
type Inner: Tupl;
/// Size of tuple.
const LEN: usize;
/// Note: Partial function.
#[doc(alias = "left")]
fn head(self) -> Self::Head
where
Self: Sized,
{
self.uncons().0
}
/// Note: Partial function.
#[doc(alias = "right")]
fn last(self) -> Self::Last
where
Self: Sized,
{
self.unsnoc().1
}
/// Note: Partial function.
fn take<const N: usize>(self) -> Self::Take
where
Self: TD<N> + Sized,
{
self.dropf().0
}
/// Note: Partial function.
fn drop<const N: usize>(self) -> Self::Drop
where
Self: TD<N> + Sized,
{
self.dropf().1
}
/// Note: Partial function.
fn take_back<const N: usize>(self) -> Self::TakeB
where
Self: TD<N> + Sized,
{
self.dropb().1
}
/// Note: Partial function.
fn drop_back<const N: usize>(self) -> Self::DropB
where
Self: TD<N> + Sized,
{
self.dropb().0
}
/// Gives you the element at index N (from 0).
/// Note: partial function
fn pick<const N: usize>(self) -> Self::At
where
Self: Pick<N> + Sized,
{
self.depict().1
}
/// unconstructs self, returning head and tail (see listmonster)
fn uncons(self) -> (Self::Head, Self::Tail);
/// untcurtsnocs self, returning init and last (see listmonster)
fn unsnoc(self) -> (Self::Init, Self::Last);
/// weird thing, full construct
fn fcons(
start: Self::Head,
inner: Self::Inner,
last: Self::Last,
) -> Self;
/// reconstruct; dont use directly
fn cons(head: Self::Head, tail: Self::Tail) -> Self;
/// retcurtsnoc; dont use directly
fn snoc(init: Self::Init, last: Self::Last) -> Self;
}
#[test]
fn t() {
2.with(cons(4i8, (1i16, 2i32)).push(2))
.take::<2>()
.push(4)
.push(0u8)
.pick::<3>();
}