Variadic tuples(rust-lang/rfcs#2775)
Hash trait from std
impl<(..T), Last> Hash for (..T, Last)
where
..(T: Hash,),
Last: Hash + ?Sized, {
#[allow(non_snake_case)]
fn hash<S: Hasher>(&self, state: &mut S) {
let (ref tuple @ .., ref last) = *self;
for member in tuple {
member.hash(state);
};
last.hash(state);
}
}
Merge two tuples together
trait Merge<(..R)> {
type Value;
fn merge(self, r: (..R)) -> Self::Value;
}
impl<(..L), (..R)> Merge<(..R)> for (..L) {
type Value = (..L, ..R);
fn merge(self, r: (..R)) -> Self::Value {
(for l in self { l }, for r in r { r })
}
}
Reverse order of tuple members
trait Rev {
type Value;
fn rev(self) -> Self::Value;
}
impl Rev for () {
type Value = ();
fn rev(self) -> Self::Value { () }
}
impl<Head, (..Tail)> Rev for (Head, ..Tail)
where
(..Tail): Rev,
<(..Tail) as Rev>::Value: Merge<(Head,)> {
type Value = <<(..Tail) as Rev>::Value as Merge<(Head,)>>::Output;
fn rev(self) -> Self::Value {
let (h, t @ ..) = self;
let rev_t = <(..Tail) as Rev>::rev(t);
rev_t.merge((h,))
}
}
Join two tuples of the same size, the result tuple will be a tuple where each of its member is a tuple with first member coming from first tuple and second member from second tuple.
trait Zip<T> {
type Out;
fn zip(self, value: T) -> Self::Out;
}
impl<(..(L, R)> Zip<(..R)> for (..L) {
type Out = (..(L, R));
fn zip(self, value: (..R)) -> Self::Out {
for (l, r) in (self, value) {
(l, r)
}
}
}
Split a tuple into two tuples with specified result tuples
fn split<(..L), (..R)>(value: (..L, ..R)) -> ((..L), (..R)) {
let (l @ .., r @ ..) = value;
(l, r)
}
Define a structure that use a tuple of HashMap defined by generic parameters
struct MegaMap<(..(K, V))> {
maps: (..HashMap<K, V>),
}
impl<(..(K, V))> MegaMap<(..(K, V))>
where ..(K: Hash), {
fn get(&self, k: (..K)) -> (..Option<V>) {
let result: (..Option<&V>) = {
(for (ref k, map), (Key, Value) in (k, &self.maps), (K, V) {
HashMap::<Key, Value>::get(&map, k)
})
};
result
}
}
Define a zero cost abstraction pattern to make sure some hypotheses are true
struct CanRead;
struct CanAdd;
struct CanWrite;
struct CanRemove;
struct Token<(..C)>;
trait Has<T> {
const VALUE: bool;
}
impl<T> Has<T> for () {
const VALUE: bool = false;
}
impl<T, Head, (..Tuple)> Has<T> for (Head, ..Tuple)
where (..Tuple): Has<T>, {
const VALUE: bool = TypeId::of::<Head>() == TypeId::of::<T>() || (..Tuple)::VALUE;
}
fn read<(..T)>(token: Token<(..T)>)
where T: Has<CanRead> {
const_assert!(T::Value);
}
impl<T, Last> Hash for Tuple<T, Last>
where
T: Hash,
Last: Hash + ?Sized, {
#[allow(non_snake_case)]
fn hash<S: Hasher>(&self, state: &mut S) {
self.elem.hash(state);
self.tail.hash(state);
}
}
trait Merge<T> {
type Out;
fn merge(self, value: T) -> Self::Out;
}
impl<T, Elem, Tail> Merge<T> for Tuple<Elem, Tail>
where Tail: Merge<Elem> {
type Out = Tuple<T, <Tail as Merge<Elem>>::Out>;
fn merge(self, value: T) -> Self::Out {
Tuple::new(value, <Tail as Merge<Elem>>::merge(self.tail, self.elem))
}
}
trait Rev {
type Out;
fn rev(self) -> Self::Out;
}
impl Rev for () {
type Out = ();
fn rev(self) -> Self::Out { () }
}
impl<T> Rev for (T, ) {
type Out = (T, );
fn rev(self) -> Self::Out { self }
}
impl<L, R> Rev for (L, R) {
type Out = (R, L);
fn rev(self) -> Self::Out { (self.1, self.0) }
}
impl<Head, Tail> Rev for Tuple<Head, Tail>
where
Tail: Rev,
<Tail as Rev>::Out: Merge<Head> {
type Out = <<Tail as Rev>::Out as Merge<Head>>::Out;
fn rev(self) -> Self::Out {
<<Tail as Rev>::Out as Merge<Head>>::merge(<Tail as Rev>::rev(self.tail), self.elem)
}
}
trait Zip<T> {
type Out;
fn zip(self, other: T) -> Self::Out;
}
impl Zip<()> for () {
type Out = ();
fn zip(self, other: ()) -> () { () }
}
impl<LE, LT, RE, RT> Zip<Tuple<RE, RT>> for Tuple<LE, LT>
where
LE: Zip<RT> {
type Out = Tuple<(LE, RE), <LE as Zip<RT>>::Out>;
fn zip(self, other: Tuple<RE, RT>) -> Self::Out {
Tuple::new((self.elem, other.elem), <LT as Zip<RT>>::zip(self.tail, other.tail))
}
}
???
???
struct CanRead;
struct CanAdd;
struct CanWrite;
struct CanRemove;
struct Token<(..C)>;
trait Has<T> {
const VALUE: bool;
}
impl<T> Has<T> for () {
const VALUE: bool = false;
}
impl<T, Head, Tail> Has<T> for Tuple<Head, Tail>
where Tail: Has<T>, {
const VALUE: bool = TypeId::of::<Head>() == TypeId::of::<T>() || Tail::VALUE;
}
fn read<(..T)>(token: Token<(..T)>)
where T: Has<CanRead> {
const_assert!(T::Value);
// we are allowed to read
}