use std::iter::{once, Chain, Once};
pub type Chain2<T> = Chain<Once<T>, Once<T>>;
pub type Chain3<T> = Chain<Chain<Once<T>, Once<T>>, Once<T>>;
pub trait Pair: Sized {
type Item;
fn to_pair(self) -> (Self::Item, Self::Item);
fn from_items(a: Self::Item, b: Self::Item) -> Self;
fn pairwise<O, P, F, R>(self, other: O, f: F) -> P
where
O: Pair,
P: Pair<Item = R>,
F: Fn(Self::Item, O::Item) -> R,
{
let (a, b) = self.to_pair();
let (c, d) = other.to_pair();
P::from_items(f(a, c), f(b, d))
}
fn pair_iter(self) -> Chain2<Self::Item> {
let (a, b) = self.to_pair();
once(a).chain(once(b))
}
}
impl<T> Pair for (T, T) {
type Item = T;
#[inline(always)]
fn to_pair(self) -> (Self::Item, Self::Item) {
self
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item) -> Self {
(a, b)
}
}
impl<T> Pair for [T; 2]
where
T: Copy,
{
type Item = T;
#[inline(always)]
fn to_pair(self) -> (Self::Item, Self::Item) {
(self[0], self[1])
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item) -> Self {
[a, b]
}
}
impl<T> Pair for (T, T, T, T) {
type Item = (T, T);
#[inline(always)]
fn to_pair(self) -> (Self::Item, Self::Item) {
((self.0, self.1), (self.2, self.3))
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item) -> Self {
(a.0, a.1, b.0, b.1)
}
}
impl<T> Pair for [T; 4]
where
T: Copy,
{
type Item = [T; 2];
#[inline(always)]
fn to_pair(self) -> (Self::Item, Self::Item) {
([self[0], self[1]], [self[2], self[3]])
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item) -> Self {
[a[0], a[1], b[0], b[1]]
}
}
impl<T> Pair for (T, T, T, T, T, T) {
type Item = (T, T, T);
#[inline(always)]
fn to_pair(self) -> (Self::Item, Self::Item) {
((self.0, self.1, self.2), (self.3, self.4, self.5))
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item) -> Self {
(a.0, a.1, a.2, b.0, b.1, b.2)
}
}
impl<T> Pair for [T; 6]
where
T: Copy,
{
type Item = [T; 3];
#[inline(always)]
fn to_pair(self) -> (Self::Item, Self::Item) {
([self[0], self[1], self[2]], [self[3], self[4], self[5]])
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item) -> Self {
[a[0], a[1], a[2], b[0], b[1], b[2]]
}
}
pub trait Trio: Sized {
type Item;
fn to_trio(self) -> (Self::Item, Self::Item, Self::Item);
fn from_items(a: Self::Item, b: Self::Item, c: Self::Item) -> Self;
fn pairwise<O, T, F, R>(self, other: O, ff: F) -> T
where
O: Trio,
T: Trio<Item = R>,
F: Fn(Self::Item, O::Item) -> R,
{
let (a, b, c) = self.to_trio();
let (d, e, f) = other.to_trio();
T::from_items(ff(a, d), ff(b, e), ff(c, f))
}
fn trio_iter(self) -> Chain3<Self::Item> {
let (a, b, c) = self.to_trio();
once(a).chain(once(b)).chain(once(c))
}
}
impl<T> Trio for (T, T, T) {
type Item = T;
#[inline(always)]
fn to_trio(self) -> (Self::Item, Self::Item, Self::Item) {
self
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item, c: Self::Item) -> Self {
(a, b, c)
}
}
impl<T> Trio for [T; 3]
where
T: Copy,
{
type Item = T;
#[inline(always)]
fn to_trio(self) -> (Self::Item, Self::Item, Self::Item) {
(self[0], self[1], self[2])
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item, c: Self::Item) -> Self {
[a, b, c]
}
}
impl<T> Trio for (T, T, T, T, T, T) {
type Item = (T, T);
#[inline(always)]
fn to_trio(self) -> (Self::Item, Self::Item, Self::Item) {
((self.0, self.1), (self.2, self.3), (self.4, self.5))
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item, c: Self::Item) -> Self {
(a.0, a.1, b.0, b.1, c.0, c.1)
}
}
impl<T> Trio for [T; 6]
where
T: Copy,
{
type Item = [T; 2];
#[inline(always)]
fn to_trio(self) -> (Self::Item, Self::Item, Self::Item) {
([self[0], self[1]], [self[2], self[3]], [self[4], self[5]])
}
#[inline(always)]
fn from_items(a: Self::Item, b: Self::Item, c: Self::Item) -> Self {
[a[0], a[1], b[0], b[1], c[0], c[1]]
}
}