1 //! A type-level array of type-level numbers.
2 //!
3 //! It is not very featureful right now, and should be considered a work in progress.
4 
5 use core::ops::{Add, Div, Mul, Sub};
6 
7 use super::*;
8 
9 /// The terminating type for type arrays.
10 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)]
11 pub struct ATerm;
12 
13 impl TypeArray for ATerm {}
14 
15 /// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its
16 /// values can be more than bits, and it is designed to act as an array. So you can only add two if
17 /// they have the same number of elements, for example.
18 ///
19 /// This array is only really designed to contain `Integer` types. If you use it with others, you
20 /// may find it lacking functionality.
21 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)]
22 pub struct TArr<V, A> {
23     first: V,
24     rest: A,
25 }
26 
27 impl<V, A> TypeArray for TArr<V, A> {}
28 
29 /// Create a new type-level arrray. Only usable on Rust 1.13.0 or newer.
30 ///
31 /// There's not a whole lot you can do with it right now.
32 ///
33 /// # Example
34 /// ```rust
35 /// #[macro_use]
36 /// extern crate typenum;
37 /// use typenum::consts::*;
38 ///
39 /// type Array = tarr![P3, N4, Z0, P38];
40 /// # fn main() { let _: Array; }
41 #[macro_export]
42 macro_rules! tarr {
43     () => ( $crate::ATerm );
44     ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> );
45     ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> );
46     ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> );
47     ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> );
48 }
49 
50 // ---------------------------------------------------------------------------------------
51 // Length
52 
53 /// Length of `ATerm` by itself is 0
54 impl Len for ATerm {
55     type Output = U0;
56     #[inline]
len(&self) -> Self::Output57     fn len(&self) -> Self::Output {
58         UTerm
59     }
60 }
61 
62 /// Size of a `TypeArray`
63 impl<V, A> Len for TArr<V, A>
64 where
65     A: Len,
66     Length<A>: Add<B1>,
67     Sum<Length<A>, B1>: Unsigned,
68 {
69     type Output = Add1<Length<A>>;
70     #[inline]
len(&self) -> Self::Output71     fn len(&self) -> Self::Output {
72         self.rest.len() + B1
73     }
74 }
75 
76 // ---------------------------------------------------------------------------------------
77 // Add arrays
78 // Note that two arrays are only addable if they are the same length.
79 
80 impl Add<ATerm> for ATerm {
81     type Output = ATerm;
82     #[inline]
add(self, _: ATerm) -> Self::Output83     fn add(self, _: ATerm) -> Self::Output {
84         ATerm
85     }
86 }
87 
88 impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al>
89 where
90     Al: Add<Ar>,
91     Vl: Add<Vr>,
92 {
93     type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>;
94     #[inline]
add(self, rhs: TArr<Vr, Ar>) -> Self::Output95     fn add(self, rhs: TArr<Vr, Ar>) -> Self::Output {
96         TArr {
97             first: self.first + rhs.first,
98             rest: self.rest + rhs.rest,
99         }
100     }
101 }
102 
103 // ---------------------------------------------------------------------------------------
104 // Subtract arrays
105 // Note that two arrays are only subtractable if they are the same length.
106 
107 impl Sub<ATerm> for ATerm {
108     type Output = ATerm;
109     #[inline]
sub(self, _: ATerm) -> Self::Output110     fn sub(self, _: ATerm) -> Self::Output {
111         ATerm
112     }
113 }
114 
115 impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al>
116 where
117     Vl: Sub<Vr>,
118     Al: Sub<Ar>,
119 {
120     type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>;
121     #[inline]
sub(self, rhs: TArr<Vr, Ar>) -> Self::Output122     fn sub(self, rhs: TArr<Vr, Ar>) -> Self::Output {
123         TArr {
124             first: self.first - rhs.first,
125             rest: self.rest - rhs.rest,
126         }
127     }
128 }
129 
130 // ---------------------------------------------------------------------------------------
131 // Multiply an array by a scalar
132 
133 impl<Rhs> Mul<Rhs> for ATerm {
134     type Output = ATerm;
135     #[inline]
mul(self, _: Rhs) -> Self::Output136     fn mul(self, _: Rhs) -> Self::Output {
137         ATerm
138     }
139 }
140 
141 impl<V, A, Rhs> Mul<Rhs> for TArr<V, A>
142 where
143     V: Mul<Rhs>,
144     A: Mul<Rhs>,
145     Rhs: Copy,
146 {
147     type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>;
148     #[inline]
mul(self, rhs: Rhs) -> Self::Output149     fn mul(self, rhs: Rhs) -> Self::Output {
150         TArr {
151             first: self.first * rhs,
152             rest: self.rest * rhs,
153         }
154     }
155 }
156 
157 impl Mul<ATerm> for Z0 {
158     type Output = ATerm;
159     #[inline]
mul(self, _: ATerm) -> Self::Output160     fn mul(self, _: ATerm) -> Self::Output {
161         ATerm
162     }
163 }
164 
165 impl<U> Mul<ATerm> for PInt<U>
166 where
167     U: Unsigned + NonZero,
168 {
169     type Output = ATerm;
170     #[inline]
mul(self, _: ATerm) -> Self::Output171     fn mul(self, _: ATerm) -> Self::Output {
172         ATerm
173     }
174 }
175 
176 impl<U> Mul<ATerm> for NInt<U>
177 where
178     U: Unsigned + NonZero,
179 {
180     type Output = ATerm;
181     #[inline]
mul(self, _: ATerm) -> Self::Output182     fn mul(self, _: ATerm) -> Self::Output {
183         ATerm
184     }
185 }
186 
187 impl<V, A> Mul<TArr<V, A>> for Z0
188 where
189     Z0: Mul<A>,
190 {
191     type Output = TArr<Z0, Prod<Z0, A>>;
192     #[inline]
mul(self, rhs: TArr<V, A>) -> Self::Output193     fn mul(self, rhs: TArr<V, A>) -> Self::Output {
194         TArr {
195             first: Z0,
196             rest: self * rhs.rest,
197         }
198     }
199 }
200 
201 impl<V, A, U> Mul<TArr<V, A>> for PInt<U>
202 where
203     U: Unsigned + NonZero,
204     PInt<U>: Mul<A> + Mul<V>,
205 {
206     type Output = TArr<Prod<PInt<U>, V>, Prod<PInt<U>, A>>;
207     #[inline]
mul(self, rhs: TArr<V, A>) -> Self::Output208     fn mul(self, rhs: TArr<V, A>) -> Self::Output {
209         TArr {
210             first: self * rhs.first,
211             rest: self * rhs.rest,
212         }
213     }
214 }
215 
216 impl<V, A, U> Mul<TArr<V, A>> for NInt<U>
217 where
218     U: Unsigned + NonZero,
219     NInt<U>: Mul<A> + Mul<V>,
220 {
221     type Output = TArr<Prod<NInt<U>, V>, Prod<NInt<U>, A>>;
222     #[inline]
mul(self, rhs: TArr<V, A>) -> Self::Output223     fn mul(self, rhs: TArr<V, A>) -> Self::Output {
224         TArr {
225             first: self * rhs.first,
226             rest: self * rhs.rest,
227         }
228     }
229 }
230 
231 // ---------------------------------------------------------------------------------------
232 // Divide an array by a scalar
233 
234 impl<Rhs> Div<Rhs> for ATerm {
235     type Output = ATerm;
236     #[inline]
div(self, _: Rhs) -> Self::Output237     fn div(self, _: Rhs) -> Self::Output {
238         ATerm
239     }
240 }
241 
242 impl<V, A, Rhs> Div<Rhs> for TArr<V, A>
243 where
244     V: Div<Rhs>,
245     A: Div<Rhs>,
246     Rhs: Copy,
247 {
248     type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>;
249     #[inline]
div(self, rhs: Rhs) -> Self::Output250     fn div(self, rhs: Rhs) -> Self::Output {
251         TArr {
252             first: self.first / rhs,
253             rest: self.rest / rhs,
254         }
255     }
256 }
257 
258 // ---------------------------------------------------------------------------------------
259 // Partial Divide an array by a scalar
260 
261 impl<Rhs> PartialDiv<Rhs> for ATerm {
262     type Output = ATerm;
263     #[inline]
partial_div(self, _: Rhs) -> Self::Output264     fn partial_div(self, _: Rhs) -> Self::Output {
265         ATerm
266     }
267 }
268 
269 impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A>
270 where
271     V: PartialDiv<Rhs>,
272     A: PartialDiv<Rhs>,
273     Rhs: Copy,
274 {
275     type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>;
276     #[inline]
partial_div(self, rhs: Rhs) -> Self::Output277     fn partial_div(self, rhs: Rhs) -> Self::Output {
278         TArr {
279             first: self.first.partial_div(rhs),
280             rest: self.rest.partial_div(rhs),
281         }
282     }
283 }
284 
285 // ---------------------------------------------------------------------------------------
286 // Modulo an array by a scalar
287 use core::ops::Rem;
288 
289 impl<Rhs> Rem<Rhs> for ATerm {
290     type Output = ATerm;
291     #[inline]
rem(self, _: Rhs) -> Self::Output292     fn rem(self, _: Rhs) -> Self::Output {
293         ATerm
294     }
295 }
296 
297 impl<V, A, Rhs> Rem<Rhs> for TArr<V, A>
298 where
299     V: Rem<Rhs>,
300     A: Rem<Rhs>,
301     Rhs: Copy,
302 {
303     type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>;
304     #[inline]
rem(self, rhs: Rhs) -> Self::Output305     fn rem(self, rhs: Rhs) -> Self::Output {
306         TArr {
307             first: self.first % rhs,
308             rest: self.rest % rhs,
309         }
310     }
311 }
312 
313 // ---------------------------------------------------------------------------------------
314 // Negate an array
315 use core::ops::Neg;
316 
317 impl Neg for ATerm {
318     type Output = ATerm;
319     #[inline]
neg(self) -> Self::Output320     fn neg(self) -> Self::Output {
321         ATerm
322     }
323 }
324 
325 impl<V, A> Neg for TArr<V, A>
326 where
327     V: Neg,
328     A: Neg,
329 {
330     type Output = TArr<Negate<V>, Negate<A>>;
331     #[inline]
neg(self) -> Self::Output332     fn neg(self) -> Self::Output {
333         TArr {
334             first: -self.first,
335             rest: -self.rest,
336         }
337     }
338 }
339