tuple/lib.rs
1#![allow(unused_parens)]
2#![cfg_attr(feature="impl_simd", feature(portable_simd))]
3/*!
4
5# Feature flags
6 - `impl_num` add support for traits from the num crate. (default on)
7 - `impl_simd` add support for simd types. (default off)
8 - `impl_serde` impl Serialize and Deserialize from serde
9
10# Examples
11
12```
13extern crate tuple;
14use tuple::*;
15# fn main() {}
16```
17All following operations are defined on the `T1` .. `Tn` type of this crate,
18as well for the normal tuple types.
19
20## Element-wise operations
21
22```
23# extern crate tuple;
24# use tuple::*;
25# fn main() {
26let a = T2(3, 4) + T2(5, 4);
27assert_eq!(a, T2(8, 8));
28
29let b = T2(3u32, 4.0f32) * T2(7, 3.0);
30assert_eq!(b, T2(21, 12.));
31
32assert_eq!(T3(1, 2, 3).map(|x| x * 2), T3(2, 4, 6));
33# }
34```
35
36## Indexing
37
38This is implemented in the [`TupleElements`](trait.TupleElements.html) trait.
39
40Indexing works as expected and panics when out of bounds.
41There are also `get` and `get_mut` functions that return `Option<&T>` and `Option<&mut T>`.
42
43```
44# extern crate tuple;
45# use tuple::*;
46# fn main() {
47assert_eq!(T3(1, 2, 3)[2], 3);
48
49assert_eq!(T2(7, 8).get(1), Some(&8));
50assert_eq!(T2(7, 8).get(2), None);
51# }
52```
53
54## Iterate over the elements of a tuple
55```
56# extern crate tuple;
57# use tuple::*;
58# fn main() {
59for i in T2(1, 2).elements() {
60 println!("{}", i);
61}
62
63let mut b = T3(3, 4, 5);
64for i in b.elements_mut() {
65 *i += 1;
66}
67assert_eq!(b.elements().sum::<u32>(), 15);
68# }
69```
70
71### Consume a tuple and iterate over the elements
72```
73# extern crate tuple;
74# use tuple::*;
75# fn main() {
76for i in T2(String::from("hello"), String::from("world")).into_elements() {
77 let s: String = i; // it's really a String
78 println!("{}", s);
79}
80# }
81```
82
83## Conversions
84
85```
86# extern crate tuple;
87# use tuple::*;
88# fn main() {
89// slice to tuple
90assert_eq!(T3::from_slice(&[1u8, 2, 3, 4, 5][..]), Some(T3(1, 2, 3)));
91
92// tuple to and from array
93let t = T3(1, 2, 3);
94let a: [u8; 3] = t.into();
95let t: T3<_, _, _> = a.into();
96
97assert_eq!(T2(Some(1), Some(2)).collect(), Some(T2(1, 2)));
98# }
99
100```
101## Joining two tuples
102```
103# extern crate tuple;
104# use tuple::*;
105# fn main() {
106let a = T2(1, 2);
107let b = T3(3, 4, 5);
108assert_eq!(a.join(b), T5(1, 2, 3, 4, 5));
109# }
110```
111
112## Splitting a tuple in two parts
113```
114# extern crate tuple;
115# use tuple::*;
116# fn main() {
117let a = T4(1, 2, 3, 4);
118let (b, c): (T1<_>, _) = a.split(); // split needs a type hint for the left side
119assert_eq!(b, T1(1));
120assert_eq!(c, T3(2, 3, 4));
121# }
122```
123
124## Rotate and Reverse
125
126```
127# extern crate tuple;
128# use tuple::*;
129# fn main() {
130let a = T4((), 2, 3, true);
131assert_eq!(a.rot_l(), T4(2, 3, true, ())); // rotate left
132assert_eq!(a.rot_r(), T4(true, (), 2, 3)); // rotate right
133assert_eq!(a.reverse(), T4(true, 3, 2, ())); // reverse
134# }
135```
136
137## Adding a Trait
138
139```
140#[macro_use]
141extern crate tuple;
142extern crate num_traits;
143
144use tuple::*;
145use num_traits::Zero;
146use std::ops::{Add, Sub, Mul};
147use std::fmt::Debug;
148
149trait Ring: Add + Sub + Mul + Zero + Debug + Sized {}
150
151// The name is up to you
152macro_rules! impl_ring {
153 // This line is defined by this crate and can't be changed
154 ($($Tuple:ident $Arr:ident { $($T:ident . $t:ident . $idx:tt),* } )*) => ($(
155
156 // This is expanded for every Tuple type
157 impl<$($T),*> Ring for $Tuple<$($T),*> where Self: Zero, $( $T: Ring ),* {}
158
159 // this has to match again
160 )*)
161}
162
163// actually implement it!
164impl_tuple!(impl_ring);
165
166# fn main() {}
167```
168**/
169
170#![cfg_attr(not(feature="std"), no_std)]
171#![allow(non_camel_case_types, non_snake_case)]
172
173#[cfg(feature="impl_num")]
174extern crate num_traits;
175
176#[cfg(feature="impl_num")]
177use num_traits as num;
178
179#[cfg(feature="std")]
180extern crate core;
181
182#[cfg(feature="impl_serde")]
183extern crate serde;
184
185use core::{ptr, mem};
186
187pub struct Elements<T> {
188 tuple: T,
189 index: usize
190}
191impl<T> Elements<T> {
192 #[inline(always)]
193 fn new(t: T) -> Elements<T> {
194 Elements { tuple: t, index: 0 }
195 }
196}
197pub struct IntoElements<T: TupleElements> {
198 tuple: Option<T>,
199 index: usize
200}
201impl<T: TupleElements> IntoElements<T> {
202 #[inline(always)]
203 fn new(t: T) -> IntoElements<T> {
204 IntoElements { tuple: Some(t), index: 0 }
205 }
206}
207
208/// This trait is marked as unsafe, due to the requirement of the get_mut method,
209/// which is required work as an injective map of `index -> element`
210///
211/// A tuple must not have a `Drop` implementation.
212pub unsafe trait TupleElements: Sized {
213 type Element;
214 const N: usize;
215
216 /// returns an Iterator over references to the elements of the tuple
217 #[inline(always)]
218 fn elements(&self) -> Elements<&Self> { Elements::new(self) }
219
220 /// returns an Iterator over mutable references to elements of the tuple
221 #[inline(always)]
222 fn elements_mut(&mut self) -> Elements<&mut Self> { Elements::new(self) }
223
224 // return an Iterator over the elements of the tuple
225 #[inline(always)]
226 fn into_elements(self) -> IntoElements<Self> { IntoElements::new(self) }
227
228 /// attempt to access the n-th element
229 fn get(&self, n: usize) -> Option<&Self::Element>;
230
231 /// attempt to access the n-th element mutablbly.
232 /// This function shall not return the same data for two different indices.
233 fn get_mut(&mut self, n: usize) -> Option<&mut Self::Element>;
234
235 fn from_iter<I>(iter: I) -> Option<Self> where I: Iterator<Item=Self::Element>;
236}
237
238pub trait Map<T>: TupleElements {
239 type Output: TupleElements<Element=T>;
240 /// apply a function to each element and return the result
241 fn map<F>(self, f: F) -> Self::Output where F: Fn(Self::Element) -> T;
242 /// same as `map`, but accepts a FnMut
243 fn map_mut<F>(self, f: F) -> Self::Output where F: FnMut(Self::Element) -> T;
244}
245
246/**
247splat: copy the argument into all elements
248
249```
250# use tuple::*;
251# fn main() {
252let a = T4::splat(42);
253assert_eq!(a, T4(42, 42, 42, 42));
254# }
255```
256*/
257pub trait Splat<T> {
258 fn splat(t: T) -> Self;
259}
260
261/// Call a `Fn` and unpack the arguments.
262
263/**
264```
265# use tuple::*;
266# fn main() {
267 fn foo(a: u32, b: &str) { }
268 foo.call((1, "hi"));
269 foo.call(T2(1, "hi"));
270# }
271```
272**/
273pub trait Call<T> {
274 type Output;
275 fn call(&self, args: T) -> Self::Output;
276}
277
278/// Call a `FnOnce` and unpack the arguments.
279pub trait CallOnce<T> {
280 type Output;
281 fn call_once(self, args: T) -> Self::Output;
282}
283
284/// Call a `FnMut` and unpack the arguments.
285pub trait CallMut<T> {
286 type Output;
287 fn call_mut(&mut self, args: T) -> Self::Output;
288}
289
290#[derive(Debug, Eq, PartialEq)]
291pub enum ConvertError {
292 OutOfBounds
293}
294
295impl<'a, T> Iterator for Elements<&'a T> where T: TupleElements {
296 type Item = &'a T::Element;
297 #[inline(always)]
298 fn next(&mut self) -> Option<Self::Item> {
299 let t = self.tuple.get(self.index);
300 if let Some(_) = t {
301 self.index += 1;
302 }
303 t
304 }
305}
306impl<'a, T> Iterator for Elements<&'a mut T> where T: TupleElements {
307 type Item = &'a mut T::Element;
308 #[inline(always)]
309 fn next(&mut self) -> Option<Self::Item> {
310 if let Some(t) = self.tuple.get_mut(self.index) {
311 self.index += 1;
312
313 // we only hand out one reference to each item
314 // and that lifetime is limited to the Elements struct
315 Some(unsafe { &mut *(t as *mut T::Element) })
316 } else {
317 None
318 }
319 }
320}
321impl<T> Iterator for IntoElements<T> where T: TupleElements {
322 type Item = T::Element;
323 #[inline(always)]
324 fn next(&mut self) -> Option<Self::Item> {
325 match self.tuple.as_mut().unwrap().get(self.index) {
326 Some(p) => {
327 self.index += 1; // mark as taken
328 let v = unsafe { ptr::read(p) }; // read it
329 Some(v)
330 },
331 None => None
332 }
333 }
334}
335impl<T> Drop for IntoElements<T> where T: TupleElements {
336 #[inline(always)]
337 fn drop(&mut self) {
338 let mut tuple = self.tuple.take().unwrap();
339 // only drop remaining elements
340 for i in self.index .. T::N {
341 unsafe {
342 ptr::drop_in_place(tuple.get_mut(i).unwrap());
343 }
344 }
345 mem::forget(tuple);
346 }
347}
348
349/// Allows to join/concatenate two tuples
350pub trait OpJoin<RHS> {
351 type Output;
352 fn join(self, rhs: RHS) -> Self::Output;
353}
354
355pub trait OpSplit<L> {
356 type R;
357 fn split(self) -> (L, Self::R);
358}
359
360pub trait OpRotateLeft {
361 type Output;
362 /// rotate left. The previously first element is now the first.
363 fn rot_l(self) -> Self::Output;
364}
365pub trait OpRotateRight {
366 type Output;
367 /// rotate right. The previously last element is now the last.
368 fn rot_r(self) -> Self::Output;
369}
370pub trait OpReverse {
371 type Output;
372 /// reverse the elements.
373 fn reverse(self) -> Self::Output;
374}
375
376#[macro_use]
377mod utils;
378/* python3:
379import string
380for i in range(1, 17):
381 print("T{i} A{i} {{ {inner} }}".format(i=i, inner=", ".join("{a}.{b}.{n}".format(a=string.ascii_uppercase[j],b=string.ascii_lowercase[j],n=j) for j in range(i))))
382*/
383#[macro_export]
384macro_rules! impl_tuple {
385 ($def:ident) => ($def!(
386T1 A1 { A.a.0 }
387T2 A2 { A.a.0, B.b.1 }
388T3 A3 { A.a.0, B.b.1, C.c.2 }
389T4 A4 { A.a.0, B.b.1, C.c.2, D.d.3 }
390T5 A5 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4 }
391T6 A6 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5 }
392T7 A7 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6 }
393T8 A8 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7 }
394T9 A9 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8 }
395T10 A10 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9 }
396T11 A11 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9, K.k.10 }
397T12 A12 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9, K.k.10, L.l.11 }
398T13 A13 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9, K.k.10, L.l.11, M.m.12 }
399T14 A14 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9, K.k.10, L.l.11, M.m.12, N.n.13 }
400T15 A15 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9, K.k.10, L.l.11, M.m.12, N.n.13, O.o.14 }
401T16 A16 { A.a.0, B.b.1, C.c.2, D.d.3, E.e.4, F.f.5, G.g.6, H.h.7, I.i.8, J.j.9, K.k.10, L.l.11, M.m.12, N.n.13, O.o.14, P.p.15 }
402 );)
403}
404macro_rules! init {
405 ($($Tuple:ident $Arr:ident { $($T:ident . $t:ident . $idx:tt),* } )*) => ($(
406 pub struct $Tuple<$($T),*>($(pub $T),*);
407 pub type $Arr<T> = $Tuple<$(A!(T, $T)),*>;
408 )*)
409}
410impl_tuple!(init);
411
412mod m_init;
413mod m_ops;
414mod m_convert;
415mod m_array;
416
417#[cfg(feature="impl_num")]
418mod m_num;
419
420mod m_tuple;
421mod m_iter;
422mod m_call;
423
424#[cfg(all(feature="impl_simd", any(target_arch="x86", target_arch="x86_64")))]
425#[macro_use]
426mod m_simd;
427
428#[cfg(feature="std")]
429mod m_std;
430
431//#[cfg(feature="impl_simd")]
432//impl_tuple!(m_simd);
433
434#[cfg(feature="impl_serde")]
435mod m_serde;
436
437/*
438use itertools::tuple_impl::TupleCollect;
439#[macro_use]
440mod impl_itertools;
441trace_macros!(true);
442impl_tuple!(impl_itertools);
443*/
444
445/**
446```
447# extern crate tuple;
448# use tuple::*;
449# fn main() {
450assert_eq!(tuple("hello world".split(' ')), Some(("hello", "world")));
451# }
452```
453**/
454pub fn tuple<T, I>(iter: I) -> Option<T> where
455 T: TupleElements, I: Iterator<Item=T::Element>
456{
457 T::from_iter(iter)
458}