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    ($n:ty | $rest:ty) => ( $crate::TArr<$n, $rest> );
51    ($n:ty, $($tail:ty),+ | $rest:ty) => ( $crate::TArr<$n, ta![$($tail),+ | $rest]> );
52}
53
54// ---------------------------------------------------------------------------------------
55// Length
56
57/// Length of `ATerm` by itself is 0
58impl Len for ATerm {
59    type Output = U0;
60    #[inline]
61    fn len(&self) -> Self::Output {
62        UTerm
63    }
64}
65
66/// Size of a `TypeArray`
67impl<V, A> Len for TArr<V, A>
68where
69    A: Len,
70    Length<A>: Add<B1>,
71    Sum<Length<A>, B1>: Unsigned,
72{
73    type Output = Add1<Length<A>>;
74    #[inline]
75    fn len(&self) -> Self::Output {
76        self.rest.len() + B1
77    }
78}
79
80// ---------------------------------------------------------------------------------------
81// FoldAdd
82
83/// Hide our `Null` type
84const _: () = {
85    /// A type which contributes nothing when adding (i.e. a zero)
86    pub struct Null;
87    impl<T> Add<T> for Null {
88        type Output = T;
89        fn add(self, rhs: T) -> Self::Output {
90            rhs
91        }
92    }
93
94    impl FoldAdd for ATerm {
95        type Output = Null;
96    }
97};
98
99impl<V, A> FoldAdd for TArr<V, A>
100where
101    A: FoldAdd,
102    FoldSum<A>: Add<V>,
103{
104    type Output = Sum<FoldSum<A>, V>;
105}
106
107// ---------------------------------------------------------------------------------------
108// FoldMul
109
110/// Hide our `Null` type
111const _: () = {
112    /// A type which contributes nothing when multiplying (i.e. a one)
113    pub struct Null;
114    impl<T> Mul<T> for Null {
115        type Output = T;
116        fn mul(self, rhs: T) -> Self::Output {
117            rhs
118        }
119    }
120
121    impl FoldMul for ATerm {
122        type Output = Null;
123    }
124};
125
126impl<V, A> FoldMul for TArr<V, A>
127where
128    A: FoldMul,
129    FoldProd<A>: Mul<V>,
130{
131    type Output = Prod<FoldProd<A>, V>;
132}
133
134// ---------------------------------------------------------------------------------------
135// Add arrays
136// Note that two arrays are only addable if they are the same length.
137
138impl Add<ATerm> for ATerm {
139    type Output = ATerm;
140    #[inline]
141    fn add(self, _: ATerm) -> Self::Output {
142        ATerm
143    }
144}
145
146impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al>
147where
148    Al: Add<Ar>,
149    Vl: Add<Vr>,
150{
151    type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>;
152    #[inline]
153    fn add(self, rhs: TArr<Vr, Ar>) -> Self::Output {
154        TArr {
155            first: self.first + rhs.first,
156            rest: self.rest + rhs.rest,
157        }
158    }
159}
160
161// ---------------------------------------------------------------------------------------
162// Subtract arrays
163// Note that two arrays are only subtractable if they are the same length.
164
165impl Sub<ATerm> for ATerm {
166    type Output = ATerm;
167    #[inline]
168    fn sub(self, _: ATerm) -> Self::Output {
169        ATerm
170    }
171}
172
173impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al>
174where
175    Vl: Sub<Vr>,
176    Al: Sub<Ar>,
177{
178    type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>;
179    #[inline]
180    fn sub(self, rhs: TArr<Vr, Ar>) -> Self::Output {
181        TArr {
182            first: self.first - rhs.first,
183            rest: self.rest - rhs.rest,
184        }
185    }
186}
187
188// ---------------------------------------------------------------------------------------
189// Multiply an array by a scalar
190
191impl<Rhs> Mul<Rhs> for ATerm {
192    type Output = ATerm;
193    #[inline]
194    fn mul(self, _: Rhs) -> Self::Output {
195        ATerm
196    }
197}
198
199impl<V, A, Rhs> Mul<Rhs> for TArr<V, A>
200where
201    V: Mul<Rhs>,
202    A: Mul<Rhs>,
203    Rhs: Copy,
204{
205    type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>;
206    #[inline]
207    fn mul(self, rhs: Rhs) -> Self::Output {
208        TArr {
209            first: self.first * rhs,
210            rest: self.rest * rhs,
211        }
212    }
213}
214
215impl Mul<ATerm> for Z0 {
216    type Output = ATerm;
217    #[inline]
218    fn mul(self, _: ATerm) -> Self::Output {
219        ATerm
220    }
221}
222
223impl<U> Mul<ATerm> for PInt<U>
224where
225    U: Unsigned + NonZero,
226{
227    type Output = ATerm;
228    #[inline]
229    fn mul(self, _: ATerm) -> Self::Output {
230        ATerm
231    }
232}
233
234impl<U> Mul<ATerm> for NInt<U>
235where
236    U: Unsigned + NonZero,
237{
238    type Output = ATerm;
239    #[inline]
240    fn mul(self, _: ATerm) -> Self::Output {
241        ATerm
242    }
243}
244
245impl<V, A> Mul<TArr<V, A>> for Z0
246where
247    Z0: Mul<A>,
248{
249    type Output = TArr<Z0, Prod<Z0, A>>;
250    #[inline]
251    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
252        TArr {
253            first: Z0,
254            rest: self * rhs.rest,
255        }
256    }
257}
258
259impl<V, A, U> Mul<TArr<V, A>> for PInt<U>
260where
261    U: Unsigned + NonZero,
262    PInt<U>: Mul<A> + Mul<V>,
263{
264    type Output = TArr<Prod<PInt<U>, V>, Prod<PInt<U>, A>>;
265    #[inline]
266    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
267        TArr {
268            first: self * rhs.first,
269            rest: self * rhs.rest,
270        }
271    }
272}
273
274impl<V, A, U> Mul<TArr<V, A>> for NInt<U>
275where
276    U: Unsigned + NonZero,
277    NInt<U>: Mul<A> + Mul<V>,
278{
279    type Output = TArr<Prod<NInt<U>, V>, Prod<NInt<U>, A>>;
280    #[inline]
281    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
282        TArr {
283            first: self * rhs.first,
284            rest: self * rhs.rest,
285        }
286    }
287}
288
289// ---------------------------------------------------------------------------------------
290// Divide an array by a scalar
291
292impl<Rhs> Div<Rhs> for ATerm {
293    type Output = ATerm;
294    #[inline]
295    fn div(self, _: Rhs) -> Self::Output {
296        ATerm
297    }
298}
299
300impl<V, A, Rhs> Div<Rhs> for TArr<V, A>
301where
302    V: Div<Rhs>,
303    A: Div<Rhs>,
304    Rhs: Copy,
305{
306    type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>;
307    #[inline]
308    fn div(self, rhs: Rhs) -> Self::Output {
309        TArr {
310            first: self.first / rhs,
311            rest: self.rest / rhs,
312        }
313    }
314}
315
316// ---------------------------------------------------------------------------------------
317// Partial Divide an array by a scalar
318
319impl<Rhs> PartialDiv<Rhs> for ATerm {
320    type Output = ATerm;
321    #[inline]
322    fn partial_div(self, _: Rhs) -> Self::Output {
323        ATerm
324    }
325}
326
327impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A>
328where
329    V: PartialDiv<Rhs>,
330    A: PartialDiv<Rhs>,
331    Rhs: Copy,
332{
333    type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>;
334    #[inline]
335    fn partial_div(self, rhs: Rhs) -> Self::Output {
336        TArr {
337            first: self.first.partial_div(rhs),
338            rest: self.rest.partial_div(rhs),
339        }
340    }
341}
342
343// ---------------------------------------------------------------------------------------
344// Modulo an array by a scalar
345use core::ops::Rem;
346
347impl<Rhs> Rem<Rhs> for ATerm {
348    type Output = ATerm;
349    #[inline]
350    fn rem(self, _: Rhs) -> Self::Output {
351        ATerm
352    }
353}
354
355impl<V, A, Rhs> Rem<Rhs> for TArr<V, A>
356where
357    V: Rem<Rhs>,
358    A: Rem<Rhs>,
359    Rhs: Copy,
360{
361    type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>;
362    #[inline]
363    fn rem(self, rhs: Rhs) -> Self::Output {
364        TArr {
365            first: self.first % rhs,
366            rest: self.rest % rhs,
367        }
368    }
369}
370
371// ---------------------------------------------------------------------------------------
372// Negate an array
373use core::ops::Neg;
374
375impl Neg for ATerm {
376    type Output = ATerm;
377    #[inline]
378    fn neg(self) -> Self::Output {
379        ATerm
380    }
381}
382
383impl<V, A> Neg for TArr<V, A>
384where
385    V: Neg,
386    A: Neg,
387{
388    type Output = TArr<Negate<V>, Negate<A>>;
389    #[inline]
390    fn neg(self) -> Self::Output {
391        TArr {
392            first: -self.first,
393            rest: -self.rest,
394        }
395    }
396}