Skip to content

Commit 5a84651

Browse files
Add trait for tuple splitting
1 parent 606dc20 commit 5a84651

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod iteration;
1515
mod join;
1616
mod map;
1717
mod merge;
18+
mod prefix;
1819
mod relation;
1920
mod test;
2021
mod treefrog;
@@ -23,6 +24,7 @@ mod variable;
2324
pub use crate::{
2425
iteration::Iteration,
2526
join::JoinInput,
27+
prefix::Split,
2628
relation::Relation,
2729
treefrog::{
2830
extend_anti::ExtendAnti,

src/prefix.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/// Trait for splitting a tuple into two at some index.
2+
///
3+
/// `P` is a tuple containing only the desired fields prior to the index. For some type `(A, B)`,
4+
/// `(A, B)`, `(A,)`, and `()` would all be valid choices for `P`, but `(B,)` would not be.
5+
pub trait Split<P>: Sized {
6+
/// The remaining fields after the input has been split.
7+
type Suffix: Sized;
8+
9+
/// Splits a tuple into a prefix and a suffix.
10+
fn split(self) -> (P, Self::Suffix);
11+
12+
/// Returns the prefix of the tuple.
13+
fn prefix(self) -> P {
14+
self.split().0
15+
}
16+
17+
/// Returns the suffix of the tuple.
18+
fn suffix(self) -> Self::Suffix {
19+
self.split().1
20+
}
21+
}
22+
23+
macro_rules! rev {
24+
($($T:ident)*) => {
25+
rev!(@REV [$($T)*])
26+
};
27+
(@REV [$H:ident $($T:ident)*] $($R:ident)*) => {
28+
rev!(@REV [$($T)*] $H $($R)*)
29+
};
30+
(@REV [$H:ident] $($R:ident)*) => {
31+
rev!(@REV [] $H $($R)*)
32+
};
33+
(@REV [] $($R:ident)*) => { ($($R,)*) };
34+
}
35+
36+
macro_rules! impls {
37+
($($t:ident)*) => {
38+
impls!(@outer [$($t)*]);
39+
};
40+
41+
(@outer [$h:ident $($t:ident)+]) => {
42+
impls!(@inner [$h $($t)*] [$h $($t)*] []);
43+
impls!(@outer [$($t)*]);
44+
};
45+
(@outer [$h:ident]) => {
46+
impls!(@inner [$h] [$h] []);
47+
impls!(@outer []);
48+
};
49+
(@outer []) => {};
50+
51+
(@inner [$($t:ident)+] [$p:ident $($pt:ident)*] [$($r:ident)*]) => {
52+
impls!(@imp [$($t)*] [$p $($pt)*] [$($r)*]);
53+
impls!(@inner [$($t)*] [$($pt)*] [$p $($r)*]);
54+
};
55+
(@inner [$($t:ident)+] [$p:ident] [$($r:ident)*]) => {
56+
impls!(@imp [$($t)*] [$p] [$($r)*]);
57+
impls!(@inner [$($t)*] [] [$p $($r)*]);
58+
};
59+
(@inner [$($t:ident)+] [] [$($r:ident)*]) => {
60+
impls!(@imp [$($t)*] [] [$($r)*]);
61+
};
62+
63+
(@imp [$($t:ident)+] [$($p:ident)*] [$($r:ident)*]) => {
64+
impl<$($t),*> Split<rev!($($p)*)> for rev!($($t)*) {
65+
type Suffix = ($($r,)*);
66+
67+
fn split(self) -> (rev!($($p)*), Self::Suffix) {
68+
let rev!($($t)*) = self;
69+
(rev!($($p)*), ($($r,)*))
70+
}
71+
}
72+
};
73+
(@imp [$($t:ident),+] [] []) => {
74+
impl<$($t),*> Split<()> for rev!($($t),*) {
75+
type Suffix = Self;
76+
77+
fn split(self) -> ((), Self) {
78+
((), self)
79+
}
80+
}
81+
};
82+
}
83+
84+
#[allow(non_snake_case)]
85+
mod impls {
86+
use super::*;
87+
88+
impls!(F E D C B A);
89+
}

0 commit comments

Comments
 (0)