Skip to content

Commit bafa50c

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

File tree

2 files changed

+92
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)