1use core::{marker::PhantomData, ptr::NonNull};
2
3use tuple_list::{Tuple, TupleList};
4
5use super::{Element, Inner, Sender};
6
7pub trait InElement: TupleList {
10 #[doc(hidden)]
11 type Place: TupleList;
12 #[doc(hidden)]
13 fn init() -> Self::Place;
14 #[doc(hidden)]
16 unsafe fn place(place: &Self::Place, data: Self);
17
18 #[doc(hidden)]
19 type Take: TupleList;
20 #[doc(hidden)]
22 unsafe fn take(place: &Self::Place) -> Self::Take;
23}
24
25impl InElement for () {
26 type Place = ();
27 fn init() {}
28 unsafe fn place(_: &(), _: ()) {}
29 type Take = ();
30 unsafe fn take(_: &()) {}
31}
32
33impl<Head, Tail> InElement for (Head, Tail)
34where
35 (Head, Tail): TupleList,
36 Tail: InElement,
37 (Element<Head>, <Tail as InElement>::Place): TupleList,
38 (Option<Head>, <Tail as InElement>::Take): TupleList,
39{
40 type Place = (Element<Head>, <Tail as InElement>::Place);
41
42 fn init() -> Self::Place {
43 (Element::default(), <Tail as InElement>::init())
44 }
45
46 unsafe fn place(place: &Self::Place, data: Self) {
47 place.0.place(data.0);
48 <Tail as InElement>::place(&place.1, data.1);
49 }
50
51 type Take = (Option<Head>, <Tail as InElement>::Take);
52
53 unsafe fn take(place: &Self::Place) -> Self::Take {
54 let head = place.0.take();
55 (head, <Tail as InElement>::take(&place.1))
56 }
57}
58
59pub trait Concat<T: Tuple>: Tuple {
61 type Output: Tuple;
63
64 fn concat(self, other: T) -> Self::Output;
66}
67
68macro_rules! impl_concat {
69 ($($t:ident,)*) => (impl_concat!(@TRANS ($($t,)*), ()););
70 (@TRANS ($head:ident, $($a:ident,)*), ()) => {
71 impl_concat!(@IMPL (), ($head, $($a,)*));
72 impl_concat!(@TRANS ($($a,)*), ());
73 };
74 (@TRANS (), ()) => {
75 impl_concat!(@IMPL (), ());
76 };
77 (@IMPL ($($b:ident,)*), ($head:ident, $($a:ident,)*)) => {
78 impl<$head, $($a,)* $($b,)*> Concat<($head, $($a,)*)> for ($($b,)*)
79 where
80 ($head, $($a,)*): Tuple,
81 ($($b,)*): Tuple,
82 ($head, $($a,)* $($b,)*): Tuple,
83 {
84 type Output = ($($b,)* $head, $($a,)* );
85
86 #[allow(non_snake_case)]
87 #[allow(unused_parens)]
88 fn concat(self, other: ($head, $($a,)*)) -> Self::Output {
89 let ($head, $($a),*) = other;
90 let ($($b,)*) = self;
91 ($($b,)* $head, $($a,)*)
92 }
93 }
94 impl_concat!(@IMPL ($($b,)* $head,), ($($a,)*));
95 };
96 (@IMPL ($($b:ident,)*), ()) => {
97 impl<$($b,)*> Concat<()> for ($($b,)*)
98 where
99 ($($b,)*): Tuple,
100 {
101 type Output = ($($b,)*);
102
103 fn concat(self, _: ()) -> Self::Output {
104 self
105 }
106 }
107 }
108}
109
110impl_concat!(A, B, C, D, E, F, G, H, I, J, K, L,);
111
112pub struct UTerm;
113pub struct UInt<U>(PhantomData<U>);
114
115pub trait Count: TupleList {
117 type Count;
119}
120
121impl Count for () {
122 type Count = UTerm;
123}
124
125impl<Head, Tail> Count for (Head, Tail)
126where
127 Tail: Count,
128 (Head, Tail): TupleList,
129{
130 type Count = UInt<<Tail as Count>::Count>;
131}
132
133pub trait Index<I>: TupleList {
137 type Output;
139
140 fn index(&self) -> &Self::Output;
142}
143
144impl<Head, Tail> Index<UTerm> for (Head, Tail)
145where
146 Tail: TupleList,
147 (Head, Tail): TupleList,
148{
149 type Output = Head;
150
151 fn index(&self) -> &Self::Output {
152 &self.0
153 }
154}
155
156impl<Head, Tail, U> Index<UInt<U>> for (Head, Tail)
157where
158 Tail: Index<U>,
159 (Head, Tail): TupleList,
160{
161 type Output = <Tail as Index<U>>::Output;
162
163 fn index(&self) -> &Self::Output {
164 self.1.index()
165 }
166}
167
168pub trait Construct: Tuple
170where
171 Self::TupleList: InElement,
172{
173 type Sender: TupleList;
176
177 #[allow(private_interfaces)]
178 #[doc(hidden)]
179 unsafe fn construct(inner: NonNull<Inner<Self::TupleList>>) -> Self::Sender;
180}
181
182macro_rules! impl_construct {
183 ($($t:ident,)*) => { impl_construct!(@TRANS $($t,)*); };
184 (@TRANS $head:ident, $($rest:ident,)*) => {
185 impl_construct!(@IMPL ($head, $($rest,)*), ($head, $($rest,)*));
186 impl_construct!(@TRANS $($rest,)*);
187 };
188 (@TRANS) => { impl_construct!(@IMPL (), ()); };
189 (@IMPL ($($whole:ident,)*), ($head:ident, $($rest:ident,)*)) => {
190 impl<$($whole,)*> Construct for ($($whole,)*) {
191 type Sender = impl_construct!(@DEF (), ($head, $($rest,)*));
192
193 #[allow(private_interfaces)]
194 unsafe fn construct(inner: NonNull<Inner<Self::TupleList>>) -> Self::Sender {
195 impl_construct!(@INIT inner ($head, $($rest,)*))
196 }
197 }
198 };
199 (@IMPL (), ()) => {
200 impl Construct for () {
201 type Sender = ();
202
203 #[allow(private_interfaces)]
204 unsafe fn construct(_: NonNull<Inner<Self::TupleList>>) {}
205 }
206 };
207 (@DEF ($($prefix:ident,)*), ($current:ident, $($suffix:ident,)*)) => {
208 (
209 Sender<($($prefix,)*), $current, ($($suffix,)*)>,
210 impl_construct!(@DEF ($($prefix,)* $current,), ($($suffix,)*))
211 )
212 };
213 (@DEF ($($prefix:ident,)*), ()) => (());
214 (@INIT $inner:ident ($current:ident, $($suffix:ident,)*)) => {
215 (
216 Sender::new($inner),
217 impl_construct!(@INIT $inner ($($suffix,)*))
218 )
219 };
220 (@INIT $inner:ident ()) => (());
221}
222impl_construct!(A, B, C, D, E, F, G, H, I, J, K, L,);