either_slot/tuple/
utils.rs

1use core::{marker::PhantomData, ptr::NonNull};
2
3use tuple_list::{Tuple, TupleList};
4
5use super::{Element, Inner, Sender};
6
7/// A trait for tuple lists that can be converted into its element storage
8/// place in [`Sender`].
9pub trait InElement: TupleList {
10    #[doc(hidden)]
11    type Place: TupleList;
12    #[doc(hidden)]
13    fn init() -> Self::Place;
14    /// See [`Element::place`] for more information.
15    #[doc(hidden)]
16    unsafe fn place(place: &Self::Place, data: Self);
17
18    #[doc(hidden)]
19    type Take: TupleList;
20    /// See [`Element::take`] for more information.
21    #[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
59/// A tuple that is concatenable of other tuples.
60pub trait Concat<T: Tuple>: Tuple {
61    /// The concatenated tuple result.
62    type Output: Tuple;
63
64    /// Concatenates 2 tuples into a longer tuple.
65    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
115/// A typenum-countable tuple list.
116pub trait Count: TupleList {
117    /// The output typenum count.
118    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
133/// A typenum-indexable tuple list.
134///
135/// The type parameter can only receive the output type of [`Count`].
136pub trait Index<I>: TupleList {
137    /// The indexed result type.
138    type Output;
139
140    /// Index the tuple list and obtains its resulting reference.
141    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
168/// A tuple type that is constructible into its tuple slot type.
169pub trait Construct: Tuple
170where
171    Self::TupleList: InElement,
172{
173    /// The constructed tuple list of senders. The returned result type of
174    /// [`tuple`](crate::tuple::tuple) is the corresponding tuple type.
175    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,);