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