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