use crate::{tuple, tuple_t};
use std::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Unit;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Tuple<First, Other>(
pub First,
).
pub Other,
);
pub trait TupleLike {
type AsRefOutput<'a>: TupleLike
where
Self: 'a;
type AsMutOutput<'a>: TupleLike
where
Self: 'a;
type PushFrontOutput<T>: TupleLike;
type PushBackOutput<T>: TupleLike;
type RevOutput: TupleLike;
type JoinOutput<T>: TupleLike
where
T: TupleLike;
type ToSomeOutput: TupleLike;
type ToOkOutput<E>: TupleLike;
const LEN: usize;
fn len(&self) -> usize {
Self::LEN
}
fn as_ref(&self) -> Self::AsRefOutput<'_>;
fn as_mut(&mut self) -> Self::AsMutOutput<'_>;
fn push<T>(self, value: T) -> Self::PushBackOutput<T>;
fn push_front<T>(self, value: T) -> Self::PushFrontOutput<T>;
fn push_back<T>(self, value: T) -> Self::PushBackOutput<T>;
fn rev(self) -> Self::RevOutput;
fn join<T>(self, value: T) -> Self::JoinOutput<T>
where
T: TupleLike;
fn to_some(self) -> Self::ToSomeOutput;
fn to_ok<E>(self) -> Self::ToOkOutput<E>;
}
impl TupleLike for Unit {
type AsRefOutput<'a> = Unit;
type AsMutOutput<'a> = Unit;
type PushFrontOutput<T> = Tuple<T, Unit>;
type PushBackOutput<T> = Tuple<T, Unit>;
type RevOutput = Unit;
type JoinOutput<T> = T where T: TupleLike;
type ToSomeOutput = Unit;
type ToOkOutput<E> = Unit;
const LEN: usize = 0;
fn as_ref(&self) -> Self::AsRefOutput<'_> {
Self
}
fn as_mut(&mut self) -> Self::AsMutOutput<'_> {
Self
}
fn push<T>(self, value: T) -> Self::PushBackOutput<T> {
Tuple(value, self)
}
fn push_front<T>(self, value: T) -> Self::PushFrontOutput<T> {
Tuple(value, self)
}
fn push_back<T>(self, value: T) -> Self::PushBackOutput<T> {
Tuple(value, self)
}
fn rev(self) -> Self::RevOutput {
self
}
fn join<T>(self, value: T) -> Self::JoinOutput<T>
where
T: TupleLike,
{
value
}
fn to_some(self) -> Self::ToSomeOutput {
Self
}
fn to_ok<E>(self) -> Self::ToOkOutput<E> {
Self
}
}
impl<First, Other> TupleLike for Tuple<First, Other>
where
Other: TupleLike,
{
type AsRefOutput<'a> = Tuple<&'a First, Other::AsRefOutput<'a>> where Self: 'a;
type AsMutOutput<'a> = Tuple<&'a mut First, Other::AsMutOutput<'a>> where Self: 'a;
type PushFrontOutput<T> = Tuple<T, Self>;
type PushBackOutput<T> = Tuple<First, Other::PushBackOutput<T>>;
type RevOutput = <Other::RevOutput as TupleLike>::PushBackOutput<First>;
type JoinOutput<T> = Tuple<First, Other::JoinOutput<T>> where T: TupleLike;
type ToSomeOutput = Tuple<Option<First>, Other::ToSomeOutput>;
type ToOkOutput<E> = Tuple<Result<First, E>, Other::ToOkOutput<E>>;
const LEN: usize = Other::LEN + 1;
fn as_ref(&self) -> Self::AsRefOutput<'_> {
Tuple(&self.0, self.1.as_ref())
}
fn as_mut(&mut self) -> Self::AsMutOutput<'_> {
Tuple(&mut self.0, self.1.as_mut())
}
fn push<T>(self, value: T) -> Self::PushBackOutput<T> {
Tuple(self.0, self.1.push(value))
}
fn push_front<T>(self, value: T) -> Self::PushFrontOutput<T> {
Tuple(value, self)
}
fn push_back<T>(self, value: T) -> Self::PushBackOutput<T> {
self.push::<T>(value)
}
fn rev(self) -> Self::RevOutput {
self.1.rev().push(self.0)
}
fn join<T>(self, value: T) -> Self::JoinOutput<T>
where
T: TupleLike,
{
Tuple(self.0, self.1.join(value))
}
fn to_some(self) -> Self::ToSomeOutput {
Tuple(Some(self.0), self.1.to_some())
}
fn to_ok<E>(self) -> Self::ToOkOutput<E> {
Tuple(Ok(self.0), self.1.to_ok())
}
}
pub trait Popable {
type PopFrontOutput: TupleLike;
type PopFrontElemet;
type PopBackOutput: TupleLike;
type PopBackElement;
fn pop(self) -> (Self::PopBackOutput, Self::PopBackElement);
fn pop_front(self) -> (Self::PopFrontOutput, Self::PopFrontElemet);
fn pop_back(self) -> (Self::PopBackOutput, Self::PopBackElement);
}
impl<First, Other> Popable for Tuple<First, Other>
where
Other: Popable + TupleLike,
{
type PopFrontOutput = Other;
type PopFrontElemet = First;
type PopBackOutput = Tuple<First, Other::PopBackOutput>;
type PopBackElement = Other::PopBackElement;
fn pop(self) -> (Self::PopBackOutput, Self::PopBackElement) {
let (tup, elem) = self.1.pop();
(Tuple(self.0, tup), elem)
}
fn pop_front(self) -> (Self::PopFrontOutput, Self::PopFrontElemet) {
(self.1, self.0)
}
fn pop_back(self) -> (Self::PopBackOutput, Self::PopBackElement) {
self.pop()
}
}
impl<First> Popable for Tuple<First, Unit> {
type PopFrontOutput = Unit;
type PopFrontElemet = First;
type PopBackOutput = Unit;
type PopBackElement = First;
fn pop(self) -> (Self::PopBackOutput, Self::PopBackElement) {
(Unit, self.0)
}
fn pop_front(self) -> (Self::PopFrontOutput, Self::PopFrontElemet) {
(Unit, self.0)
}
fn pop_back(self) -> (Self::PopBackOutput, Self::PopBackElement) {
self.pop()
}
}
pub trait Rotatable {
type RotLeftOutput: TupleLike;
type RotRightOutput: TupleLike;
fn rot_l(self) -> Self::RotLeftOutput;
fn rot_r(self) -> Self::RotRightOutput;
}
impl Rotatable for Unit {
type RotLeftOutput = Unit;
type RotRightOutput = Unit;
fn rot_l(self) -> Unit {
self
}
fn rot_r(self) -> Unit {
self
}
}
impl<First, Other> Rotatable for Tuple<First, Other>
where
Other: TupleLike,
Self: Popable,
{
type RotLeftOutput = Other::PushBackOutput<First>;
type RotRightOutput =
Tuple<<Self as Popable>::PopBackElement, <Self as Popable>::PopBackOutput>;
fn rot_l(self) -> Self::RotLeftOutput {
let Tuple(first, other) = self;
other.push(first)
}
fn rot_r(self) -> Self::RotRightOutput {
let (out, elem) = self.pop();
Tuple(elem, out)
}
}
pub trait ToPrimitive {
type Primitive;
fn primitive(self) -> Self::Primitive;
}
#[cfg(not(feature = "any_array"))]
pub trait ToArray<T>: super::TupleLike {
type Array;
fn to_array(self) -> Self::Array;
}
__tuple_traits_impl! { 0; }
__tuple_traits_impl! { 1; T0 }
__tuple_traits_impl! { 2; T0 T1 }
__tuple_traits_impl! { 3; T0 T1 T2 }
__tuple_traits_impl! { 4; T0 T1 T2 T3 }
__tuple_traits_impl! { 5; T0 T1 T2 T3 T4 }
__tuple_traits_impl! { 6; T0 T1 T2 T3 T4 T5 }
__tuple_traits_impl! { 7; T0 T1 T2 T3 T4 T5 T6 }
__tuple_traits_impl! { 8; T0 T1 T2 T3 T4 T5 T6 T7 }
__tuple_traits_impl! { 9; T0 T1 T2 T3 T4 T5 T6 T7 T8 }
__tuple_traits_impl! { 10; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 }
__tuple_traits_impl! { 11; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 }
__tuple_traits_impl! { 12; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 }
__tuple_traits_impl! { 13; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 }
__tuple_traits_impl! { 14; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 }
__tuple_traits_impl! { 15; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 }
__tuple_traits_impl! { 16; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 }
__tuple_traits_impl! { 17; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 }
__tuple_traits_impl! { 18; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 }
__tuple_traits_impl! { 19; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 }
__tuple_traits_impl! { 20; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 }
__tuple_traits_impl! { 21; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 }
__tuple_traits_impl! { 22; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 }
__tuple_traits_impl! { 23; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 }
__tuple_traits_impl! { 24; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 }
__tuple_traits_impl! { 25; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 }
__tuple_traits_impl! { 26; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 }
__tuple_traits_impl! { 27; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 }
__tuple_traits_impl! { 28; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 }
__tuple_traits_impl! { 29; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 }
__tuple_traits_impl! { 30; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 }
__tuple_traits_impl! { 31; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 }
__tuple_traits_impl! { 32; T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 }
impl Add for Unit {
type Output = Unit;
fn add(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Add<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Add<First2>,
Other1: Add<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn add(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 + rhs.0, self.1 + rhs.1)
}
}
impl AddAssign for Unit {
fn add_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> AddAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: AddAssign<First2>,
Other1: AddAssign<Other2>,
{
fn add_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 += rhs.0;
self.1 += rhs.1;
}
}
impl Sub for Unit {
type Output = Unit;
fn sub(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Sub<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Sub<First2>,
Other1: Sub<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn sub(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 - rhs.0, self.1 - rhs.1)
}
}
impl SubAssign for Unit {
fn sub_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> SubAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: SubAssign<First2>,
Other1: SubAssign<Other2>,
{
fn sub_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 -= rhs.0;
self.1 -= rhs.1;
}
}
impl Mul for Unit {
type Output = Unit;
fn mul(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Mul<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Mul<First2>,
Other1: Mul<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn mul(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 * rhs.0, self.1 * rhs.1)
}
}
impl MulAssign for Unit {
fn mul_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> MulAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: MulAssign<First2>,
Other1: MulAssign<Other2>,
{
fn mul_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 *= rhs.0;
self.1 *= rhs.1;
}
}
impl Div for Unit {
type Output = Unit;
fn div(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Div<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Div<First2>,
Other1: Div<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn div(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 / rhs.0, self.1 / rhs.1)
}
}
impl DivAssign for Unit {
fn div_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> DivAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: DivAssign<First2>,
Other1: DivAssign<Other2>,
{
fn div_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 /= rhs.0;
self.1 /= rhs.1;
}
}
impl Rem for Unit {
type Output = Unit;
fn rem(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Rem<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Rem<First2>,
Other1: Rem<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn rem(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 % rhs.0, self.1 % rhs.1)
}
}
impl RemAssign for Unit {
fn rem_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> RemAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: RemAssign<First2>,
Other1: RemAssign<Other2>,
{
fn rem_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 %= rhs.0;
self.1 %= rhs.1;
}
}
impl BitAnd for Unit {
type Output = Unit;
fn bitand(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> BitAnd<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: BitAnd<First2>,
Other1: BitAnd<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn bitand(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 & rhs.0, self.1 & rhs.1)
}
}
impl BitAndAssign for Unit {
fn bitand_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> BitAndAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: BitAndAssign<First2>,
Other1: BitAndAssign<Other2>,
{
fn bitand_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 &= rhs.0;
self.1 &= rhs.1;
}
}
impl BitOr for Unit {
type Output = Unit;
fn bitor(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> BitOr<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: BitOr<First2>,
Other1: BitOr<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn bitor(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 | rhs.0, self.1 | rhs.1)
}
}
impl BitOrAssign for Unit {
fn bitor_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> BitOrAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: BitOrAssign<First2>,
Other1: BitOrAssign<Other2>,
{
fn bitor_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 |= rhs.0;
self.1 |= rhs.1;
}
}
impl BitXor for Unit {
type Output = Unit;
fn bitxor(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> BitXor<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: BitXor<First2>,
Other1: BitXor<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn bitxor(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 ^ rhs.0, self.1 ^ rhs.1)
}
}
impl BitXorAssign for Unit {
fn bitxor_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> BitXorAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: BitXorAssign<First2>,
Other1: BitXorAssign<Other2>,
{
fn bitxor_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 ^= rhs.0;
self.1 ^= rhs.1;
}
}
impl Shl for Unit {
type Output = Unit;
fn shl(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Shl<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Shl<First2>,
Other1: Shl<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn shl(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 << rhs.0, self.1 << rhs.1)
}
}
impl ShlAssign for Unit {
fn shl_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> ShlAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: ShlAssign<First2>,
Other1: ShlAssign<Other2>,
{
fn shl_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 <<= rhs.0;
self.1 <<= rhs.1;
}
}
impl Shr for Unit {
type Output = Unit;
fn shr(self, _: Unit) -> Self::Output {
Unit
}
}
impl<First1, Other1, First2, Other2> Shr<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: Shr<First2>,
Other1: Shr<Other2>,
{
type Output = Tuple<First1::Output, Other1::Output>;
fn shr(self, rhs: Tuple<First2, Other2>) -> Self::Output {
Tuple(self.0 >> rhs.0, self.1 >> rhs.1)
}
}
impl ShrAssign for Unit {
fn shr_assign(&mut self, _: Unit) {}
}
impl<First1, Other1, First2, Other2> ShrAssign<Tuple<First2, Other2>> for Tuple<First1, Other1>
where
First1: ShrAssign<First2>,
Other1: ShrAssign<Other2>,
{
fn shr_assign(&mut self, rhs: Tuple<First2, Other2>) {
self.0 >>= rhs.0;
self.1 >>= rhs.1;
}
}
impl Neg for Unit {
type Output = Unit;
fn neg(self) -> Self::Output {
self
}
}
impl<First: Neg, Other: Neg> Neg for Tuple<First, Other> {
type Output = Tuple<First::Output, Other::Output>;
fn neg(self) -> Self::Output {
Tuple(-self.0, -self.1)
}
}
impl Not for Unit {
type Output = Unit;
fn not(self) -> Self::Output {
self
}
}
impl<First: Not, Other: Not> Not for Tuple<First, Other> {
type Output = Tuple<First::Output, Other::Output>;
fn not(self) -> Self::Output {
Tuple(!self.0, !self.1)
}
}