flatk/
tuple.rs

1//! Tuples are useful for combining different storage types together in an
2//! ad-hoc structure of arrays pattern. This module facilitates this functionality.
3
4use super::*;
5
6/// A tuple wraps its containers, so itself is a value type and not a borrow.
7impl<S, T> ValueType for (S, T) {}
8impl<S: Viewed, T: Viewed> Viewed for (S, T) {}
9
10impl<A, B, S: Push<A>, T: Push<B>> Push<(A, B)> for (S, T) {
11    #[inline]
12    fn push(&mut self, (a, b): (A, B)) {
13        self.0.push(a);
14        self.1.push(b);
15    }
16}
17
18impl<S: Truncate, T: Truncate> Truncate for (S, T) {
19    #[inline]
20    fn truncate(&mut self, len: usize) {
21        self.0.truncate(len);
22        self.1.truncate(len);
23    }
24}
25
26impl<S: Clear, T: Clear> Clear for (S, T) {
27    #[inline]
28    fn clear(&mut self) {
29        self.0.clear();
30        self.1.clear();
31    }
32}
33
34impl<S: IntoStorage, T: IntoStorage> IntoStorage for (S, T) {
35    type StorageType = (S::StorageType, T::StorageType);
36
37    #[inline]
38    fn into_storage(self) -> Self::StorageType {
39        (self.0.into_storage(), self.1.into_storage())
40    }
41}
42
43impl<U, V, S: StorageInto<U>, T: StorageInto<V>> StorageInto<(U, V)> for (S, T) {
44    type Output = (S::Output, T::Output);
45    #[inline]
46    fn storage_into(self) -> Self::Output {
47        (self.0.storage_into(), self.1.storage_into())
48    }
49}
50
51impl<S, T, Out> MapStorage<Out> for (S, T) {
52    type Input = (S, T);
53    type Output = Out;
54    #[inline]
55    fn map_storage<F: FnOnce(Self::Input) -> Out>(self, f: F) -> Self::Output {
56        f(self)
57    }
58}
59
60impl<S, T, U> CloneWithStorage<U> for (S, T) {
61    type CloneType = U;
62    #[inline]
63    fn clone_with_storage(&self, storage: U) -> Self::CloneType {
64        storage
65    }
66}
67
68impl<S: IntoOwned, T: IntoOwned> IntoOwned for (S, T) {
69    type Owned = (S::Owned, T::Owned);
70    #[inline]
71    fn into_owned(self) -> Self::Owned {
72        (self.0.into_owned(), self.1.into_owned())
73    }
74}
75
76impl<S: IntoOwnedData, T: IntoOwnedData> IntoOwnedData for (S, T) {
77    type OwnedData = (S::OwnedData, T::OwnedData);
78    #[inline]
79    fn into_owned_data(self) -> Self::OwnedData {
80        (self.0.into_owned_data(), self.1.into_owned_data())
81    }
82}
83
84impl<'a, S, T> GetIndex<'a, (S, T)> for usize
85where
86    S: Get<'a, usize>,
87    T: Get<'a, usize>,
88{
89    type Output = (S::Output, T::Output);
90    #[inline]
91    fn get(self, (ref s, ref t): &(S, T)) -> Option<Self::Output> {
92        s.get(self)
93            .and_then(|s_item| t.get(self).map(|t_item| (s_item, t_item)))
94    }
95}
96
97impl<'a, S, T> GetIndex<'a, (S, T)> for std::ops::Range<usize>
98where
99    S: Get<'a, std::ops::Range<usize>>,
100    T: Get<'a, std::ops::Range<usize>>,
101{
102    type Output = (S::Output, T::Output);
103    #[inline]
104    fn get(self, (ref s, ref t): &(S, T)) -> Option<Self::Output> {
105        s.get(self.clone())
106            .and_then(|s_item| t.get(self).map(|t_item| (s_item, t_item)))
107    }
108}
109
110impl<'a, S, T, N> GetIndex<'a, (S, T)> for StaticRange<N>
111where
112    S: Get<'a, StaticRange<N>>,
113    T: Get<'a, StaticRange<N>>,
114    N: Unsigned + Copy,
115{
116    type Output = (S::Output, T::Output);
117    #[inline]
118    fn get(self, (ref s, ref t): &(S, T)) -> Option<Self::Output> {
119        s.get(self)
120            .and_then(|s_item| t.get(self).map(|t_item| (s_item, t_item)))
121    }
122}
123
124impl<'a, S, T> IsolateIndex<(S, T)> for usize
125where
126    S: Isolate<usize>,
127    T: Isolate<usize>,
128{
129    type Output = (S::Output, T::Output);
130    #[inline]
131    unsafe fn isolate_unchecked(self, (s, t): (S, T)) -> Self::Output {
132        (s.isolate_unchecked(self), t.isolate_unchecked(self))
133    }
134    #[inline]
135    fn try_isolate(self, (s, t): (S, T)) -> Option<Self::Output> {
136        s.try_isolate(self)
137            .and_then(|s_item| t.try_isolate(self).map(|t_item| (s_item, t_item)))
138    }
139}
140
141impl<'a, S, T> IsolateIndex<(S, T)> for std::ops::Range<usize>
142where
143    S: Isolate<std::ops::Range<usize>>,
144    T: Isolate<std::ops::Range<usize>>,
145{
146    type Output = (S::Output, T::Output);
147    #[inline]
148    unsafe fn isolate_unchecked(self, (s, t): (S, T)) -> Self::Output {
149        (s.isolate_unchecked(self.clone()), t.isolate_unchecked(self))
150    }
151    #[inline]
152    fn try_isolate(self, (s, t): (S, T)) -> Option<Self::Output> {
153        s.try_isolate(self.clone())
154            .and_then(|s_item| t.try_isolate(self).map(|t_item| (s_item, t_item)))
155    }
156}
157
158impl<S: Set, T: Set> Set for (S, T) {
159    type Elem = (S::Elem, T::Elem);
160    type Atom = (S::Atom, T::Atom);
161    #[inline]
162    fn len(&self) -> usize {
163        debug_assert_eq!(self.0.len(), self.1.len());
164        self.0.len()
165    }
166}
167
168impl<'a, S: View<'a>, T: View<'a>> View<'a> for (S, T) {
169    type Type = (S::Type, T::Type);
170
171    #[inline]
172    fn view(&'a self) -> Self::Type {
173        (self.0.view(), self.1.view())
174    }
175}
176
177impl<'a, S: ViewMut<'a>, T: ViewMut<'a>> ViewMut<'a> for (S, T) {
178    type Type = (S::Type, T::Type);
179
180    #[inline]
181    fn view_mut(&'a mut self) -> Self::Type {
182        (self.0.view_mut(), self.1.view_mut())
183    }
184}
185
186impl<S, T> SplitAt for (S, T)
187where
188    S: SplitAt,
189    T: SplitAt,
190{
191    #[inline]
192    fn split_at(self, mid: usize) -> (Self, Self) {
193        let (s, t) = self;
194        let (s_l, s_r) = s.split_at(mid);
195        let (t_l, t_r) = t.split_at(mid);
196        ((s_l, t_l), (s_r, t_r))
197    }
198}
199
200impl<S, T> SplitOff for (S, T)
201where
202    S: SplitOff,
203    T: SplitOff,
204{
205    #[inline]
206    fn split_off(&mut self, mid: usize) -> Self {
207        let (s, t) = self;
208        let s_r = s.split_off(mid);
209        let t_r = t.split_off(mid);
210        (s_r, t_r)
211    }
212}
213
214impl<S, T, N> SplitPrefix<N> for (S, T)
215where
216    S: SplitPrefix<N>,
217    T: SplitPrefix<N>,
218{
219    type Prefix = (S::Prefix, T::Prefix);
220
221    #[inline]
222    fn split_prefix(self) -> Option<(Self::Prefix, Self)> {
223        let (s, t) = self;
224        s.split_prefix().and_then(|(s_prefix, s_rest)| {
225            t.split_prefix()
226                .map(|(t_prefix, t_rest)| ((s_prefix, t_prefix), (s_rest, t_rest)))
227        })
228    }
229}
230
231impl<S, T> SplitFirst for (S, T)
232where
233    S: SplitFirst,
234    T: SplitFirst,
235{
236    type First = (S::First, T::First);
237
238    #[inline]
239    fn split_first(self) -> Option<(Self::First, Self)> {
240        let (s, t) = self;
241        s.split_first().and_then(|(s_first, s_rest)| {
242            t.split_first()
243                .map(|(t_first, t_rest)| ((s_first, t_first), (s_rest, t_rest)))
244        })
245    }
246}
247
248/// We can only provide a reference to the underlying storage of a tuple if the
249/// tuple is made up of storage type collections itself. In this case the
250/// storage is the tuple itself.
251impl<S: Storage<Storage = S>, T: Storage<Storage = T>> Storage for (S, T) {
252    type Storage = (S, T);
253    #[inline]
254    fn storage(&self) -> &Self::Storage {
255        self
256    }
257}
258
259impl<S: StorageMut<Storage = S>, T: StorageMut<Storage = T>> StorageMut for (S, T) {
260    #[inline]
261    fn storage_mut(&mut self) -> &mut Self::Storage {
262        self
263    }
264}
265
266impl<S: Dummy, T: Dummy> Dummy for (S, T) {
267    #[inline]
268    unsafe fn dummy() -> Self {
269        (S::dummy(), T::dummy())
270    }
271}
272
273impl<S: RemovePrefix, T: RemovePrefix> RemovePrefix for (S, T) {
274    #[inline]
275    fn remove_prefix(&mut self, n: usize) {
276        self.0.remove_prefix(n);
277        self.1.remove_prefix(n);
278    }
279}
280
281impl<N, S, T> IntoStaticChunkIterator<N> for (S, T)
282where
283    S: IntoStaticChunkIterator<N>,
284    T: IntoStaticChunkIterator<N>,
285    N: Unsigned,
286{
287    type Item = (S::Item, T::Item);
288    type IterType = std::iter::Zip<S::IterType, T::IterType>;
289
290    #[inline]
291    fn into_static_chunk_iter(self) -> Self::IterType {
292        self.0
293            .into_static_chunk_iter()
294            .zip(self.1.into_static_chunk_iter())
295    }
296}
297
298impl<N, S: UniChunkable<N>, T: UniChunkable<N>> UniChunkable<N> for (S, T) {
299    type Chunk = (S::Chunk, T::Chunk);
300}
301
302impl<S: PushChunk<N>, T: PushChunk<N>, N> PushChunk<N> for (S, T) {
303    #[inline]
304    fn push_chunk(&mut self, chunk: Self::Chunk) {
305        self.0.push_chunk(chunk.0);
306        self.1.push_chunk(chunk.1);
307    }
308}
309
310#[cfg(test)]
311mod tests {
312    use super::*;
313
314    #[test]
315    fn unichunked_tuple() {
316        let a = vec![1, 2, 3, 4];
317        let b = vec![6, 7, 8, 9];
318        let chunked_a_b = Chunked2::from_flat((a, b));
319        assert_eq!(chunked_a_b.view().at(0), (&[1, 2], &[6, 7]));
320        let mut iter = chunked_a_b.iter();
321        assert_eq!(iter.next().unwrap(), (&[1, 2], &[6, 7]));
322        assert_eq!(iter.next().unwrap(), (&[3, 4], &[8, 9]));
323        assert_eq!(iter.next(), None);
324    }
325
326    #[test]
327    fn chunked_tuple() {
328        let sizes = vec![1, 2, 2];
329        let a = vec![1, 2, 3, 4, 5];
330        let b = vec![6, 7, 8, 9, 10];
331        let chunked_a_b = Chunked::from_sizes(sizes, (a, b));
332        let mut iter = chunked_a_b.iter();
333        assert_eq!(iter.next().unwrap(), (&[1][..], &[6][..]));
334        assert_eq!(iter.next().unwrap(), (&[2, 3][..], &[7, 8][..]));
335        assert_eq!(iter.next().unwrap(), (&[4, 5][..], &[9, 10][..]));
336        assert_eq!(iter.next(), None);
337    }
338
339    #[test]
340    fn chunked_unichunked_tuple_push() {
341        let sizes = vec![1, 2];
342        let a = vec![1, 2, 3, 4, 5, 6];
343        let b = vec![7, 8, 9, 10, 11, 12];
344        let mut a_b = Chunked::from_sizes(sizes, Chunked2::from_flat((a, b)));
345        a_b.push_iter(std::iter::once(([1, 2], [3, 4])));
346        let mut iter = a_b.iter();
347        assert_eq!(
348            iter.next().unwrap(),
349            Chunked2::from_flat((&[1, 2][..], &[7, 8][..]))
350        );
351        assert_eq!(
352            iter.next().unwrap(),
353            Chunked2::from_flat((&[3, 4, 5, 6][..], &[9, 10, 11, 12][..]))
354        );
355        assert_eq!(
356            iter.next().unwrap(),
357            Chunked2::from_flat((&[1, 2][..], &[3, 4][..]))
358        );
359        assert_eq!(iter.next(), None);
360    }
361
362    #[cfg(feature = "sparse")]
363    #[test]
364    fn sparse_chunked_tuple() {
365        let idx = vec![0, 3, 4];
366        let sizes = vec![1, 2, 2];
367        let a = vec![1, 2, 3, 4, 5];
368        let b = vec![6, 7, 8, 9, 10];
369        let a_b = Sparse::from_dim(idx, 5, Chunked::from_sizes(sizes, (a, b)));
370
371        // Verify contents
372        let mut iter = a_b.iter();
373        assert_eq!(iter.next().unwrap(), (0, (&[1][..], &[6][..]), 0));
374        assert_eq!(iter.next().unwrap(), (3, (&[2, 3][..], &[7, 8][..]), 3));
375        assert_eq!(iter.next().unwrap(), (4, (&[4, 5][..], &[9, 10][..]), 4));
376        assert_eq!(iter.next(), None);
377
378        // Unwrap
379        //let (a, b) = a_b.
380    }
381}