typenum/
array.rs

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
5use core::ops::{Add, Div, Mul, Sub};
6
7use 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))]
12pub struct ATerm;
13
14impl 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))]
24pub struct TArr<V, A> {
25    first: V,
26    rest: A,
27}
28
29impl<V, A> TypeArray for TArr<V, A> {}
30
31/// Create a new type-level array. 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]
44macro_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
56impl Len for ATerm {
57    type Output = U0;
58    #[inline]
59    fn len(&self) -> Self::Output {
60        UTerm
61    }
62}
63
64/// Size of a `TypeArray`
65impl<V, A> Len for TArr<V, A>
66where
67    A: Len,
68    Length<A>: Add<B1>,
69    Sum<Length<A>, B1>: Unsigned,
70{
71    type Output = Add1<Length<A>>;
72    #[inline]
73    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
82impl Add<ATerm> for ATerm {
83    type Output = ATerm;
84    #[inline]
85    fn add(self, _: ATerm) -> Self::Output {
86        ATerm
87    }
88}
89
90impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al>
91where
92    Al: Add<Ar>,
93    Vl: Add<Vr>,
94{
95    type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>;
96    #[inline]
97    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
109impl Sub<ATerm> for ATerm {
110    type Output = ATerm;
111    #[inline]
112    fn sub(self, _: ATerm) -> Self::Output {
113        ATerm
114    }
115}
116
117impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al>
118where
119    Vl: Sub<Vr>,
120    Al: Sub<Ar>,
121{
122    type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>;
123    #[inline]
124    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
135impl<Rhs> Mul<Rhs> for ATerm {
136    type Output = ATerm;
137    #[inline]
138    fn mul(self, _: Rhs) -> Self::Output {
139        ATerm
140    }
141}
142
143impl<V, A, Rhs> Mul<Rhs> for TArr<V, A>
144where
145    V: Mul<Rhs>,
146    A: Mul<Rhs>,
147    Rhs: Copy,
148{
149    type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>;
150    #[inline]
151    fn mul(self, rhs: Rhs) -> Self::Output {
152        TArr {
153            first: self.first * rhs,
154            rest: self.rest * rhs,
155        }
156    }
157}
158
159impl Mul<ATerm> for Z0 {
160    type Output = ATerm;
161    #[inline]
162    fn mul(self, _: ATerm) -> Self::Output {
163        ATerm
164    }
165}
166
167impl<U> Mul<ATerm> for PInt<U>
168where
169    U: Unsigned + NonZero,
170{
171    type Output = ATerm;
172    #[inline]
173    fn mul(self, _: ATerm) -> Self::Output {
174        ATerm
175    }
176}
177
178impl<U> Mul<ATerm> for NInt<U>
179where
180    U: Unsigned + NonZero,
181{
182    type Output = ATerm;
183    #[inline]
184    fn mul(self, _: ATerm) -> Self::Output {
185        ATerm
186    }
187}
188
189impl<V, A> Mul<TArr<V, A>> for Z0
190where
191    Z0: Mul<A>,
192{
193    type Output = TArr<Z0, Prod<Z0, A>>;
194    #[inline]
195    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
196        TArr {
197            first: Z0,
198            rest: self * rhs.rest,
199        }
200    }
201}
202
203impl<V, A, U> Mul<TArr<V, A>> for PInt<U>
204where
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]
210    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
218impl<V, A, U> Mul<TArr<V, A>> for NInt<U>
219where
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]
225    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
236impl<Rhs> Div<Rhs> for ATerm {
237    type Output = ATerm;
238    #[inline]
239    fn div(self, _: Rhs) -> Self::Output {
240        ATerm
241    }
242}
243
244impl<V, A, Rhs> Div<Rhs> for TArr<V, A>
245where
246    V: Div<Rhs>,
247    A: Div<Rhs>,
248    Rhs: Copy,
249{
250    type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>;
251    #[inline]
252    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
263impl<Rhs> PartialDiv<Rhs> for ATerm {
264    type Output = ATerm;
265    #[inline]
266    fn partial_div(self, _: Rhs) -> Self::Output {
267        ATerm
268    }
269}
270
271impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A>
272where
273    V: PartialDiv<Rhs>,
274    A: PartialDiv<Rhs>,
275    Rhs: Copy,
276{
277    type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>;
278    #[inline]
279    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
289use core::ops::Rem;
290
291impl<Rhs> Rem<Rhs> for ATerm {
292    type Output = ATerm;
293    #[inline]
294    fn rem(self, _: Rhs) -> Self::Output {
295        ATerm
296    }
297}
298
299impl<V, A, Rhs> Rem<Rhs> for TArr<V, A>
300where
301    V: Rem<Rhs>,
302    A: Rem<Rhs>,
303    Rhs: Copy,
304{
305    type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>;
306    #[inline]
307    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
317use core::ops::Neg;
318
319impl Neg for ATerm {
320    type Output = ATerm;
321    #[inline]
322    fn neg(self) -> Self::Output {
323        ATerm
324    }
325}
326
327impl<V, A> Neg for TArr<V, A>
328where
329    V: Neg,
330    A: Neg,
331{
332    type Output = TArr<Negate<V>, Negate<A>>;
333    #[inline]
334    fn neg(self) -> Self::Output {
335        TArr {
336            first: -self.first,
337            rest: -self.rest,
338        }
339    }
340}