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::marker::PhantomData;
6 use core::ops::{Add, Div, Mul, Sub};
7 
8 use super::*;
9 
10 /// The terminating type for type arrays.
11 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)]
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 pub struct TArr<V, A> {
24     _marker: PhantomData<(V, 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;
len(&self) -> Self::Output56     fn len(&self) -> Self::Output {
57         UTerm
58     }
59 }
60 
61 /// Size of a `TypeArray`
62 impl<V, A> Len for TArr<V, A>
63 where
64     A: Len,
65     Length<A>: Add<B1>,
66     Sum<Length<A>, B1>: Unsigned,
67 {
68     type Output = Add1<Length<A>>;
len(&self) -> Self::Output69     fn len(&self) -> Self::Output {
70         unsafe { ::core::mem::uninitialized() }
71     }
72 }
73 
74 // ---------------------------------------------------------------------------------------
75 // Add arrays
76 // Note that two arrays are only addable if they are the same length.
77 
78 impl Add<ATerm> for ATerm {
79     type Output = ATerm;
add(self, _: ATerm) -> Self::Output80     fn add(self, _: ATerm) -> Self::Output {
81         ATerm
82     }
83 }
84 
85 impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al>
86 where
87     Al: Add<Ar>,
88     Vl: Add<Vr>,
89 {
90     type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>;
add(self, _: TArr<Vr, Ar>) -> Self::Output91     fn add(self, _: TArr<Vr, Ar>) -> Self::Output {
92         unsafe { ::core::mem::uninitialized() }
93     }
94 }
95 
96 // ---------------------------------------------------------------------------------------
97 // Subtract arrays
98 // Note that two arrays are only subtractable if they are the same length.
99 
100 impl Sub<ATerm> for ATerm {
101     type Output = ATerm;
sub(self, _: ATerm) -> Self::Output102     fn sub(self, _: ATerm) -> Self::Output {
103         ATerm
104     }
105 }
106 
107 impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al>
108 where
109     Vl: Sub<Vr>,
110     Al: Sub<Ar>,
111 {
112     type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>;
sub(self, _: TArr<Vr, Ar>) -> Self::Output113     fn sub(self, _: TArr<Vr, Ar>) -> Self::Output {
114         unsafe { ::core::mem::uninitialized() }
115     }
116 }
117 
118 // ---------------------------------------------------------------------------------------
119 // Multiply an array by a scalar
120 
121 impl<Rhs> Mul<Rhs> for ATerm {
122     type Output = ATerm;
mul(self, _: Rhs) -> Self::Output123     fn mul(self, _: Rhs) -> Self::Output {
124         ATerm
125     }
126 }
127 
128 impl<V, A, Rhs> Mul<Rhs> for TArr<V, A>
129 where
130     V: Mul<Rhs>,
131     A: Mul<Rhs>,
132 {
133     type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>;
mul(self, _: Rhs) -> Self::Output134     fn mul(self, _: Rhs) -> Self::Output {
135         unsafe { ::core::mem::uninitialized() }
136     }
137 }
138 
139 impl Mul<ATerm> for Z0 {
140     type Output = ATerm;
mul(self, _: ATerm) -> Self::Output141     fn mul(self, _: ATerm) -> Self::Output {
142         ATerm
143     }
144 }
145 
146 impl<U> Mul<ATerm> for PInt<U>
147 where
148     U: Unsigned + NonZero,
149 {
150     type Output = ATerm;
mul(self, _: ATerm) -> Self::Output151     fn mul(self, _: ATerm) -> Self::Output {
152         ATerm
153     }
154 }
155 
156 impl<U> Mul<ATerm> for NInt<U>
157 where
158     U: Unsigned + NonZero,
159 {
160     type Output = ATerm;
mul(self, _: ATerm) -> Self::Output161     fn mul(self, _: ATerm) -> Self::Output {
162         ATerm
163     }
164 }
165 
166 impl<V, A> Mul<TArr<V, A>> for Z0
167 where
168     Z0: Mul<A>,
169 {
170     type Output = TArr<Z0, Prod<Z0, A>>;
mul(self, _: TArr<V, A>) -> Self::Output171     fn mul(self, _: TArr<V, A>) -> Self::Output {
172         unsafe { ::core::mem::uninitialized() }
173     }
174 }
175 
176 impl<V, A, U> Mul<TArr<V, A>> for PInt<U>
177 where
178     U: Unsigned + NonZero,
179     PInt<U>: Mul<A> + Mul<V>,
180 {
181     type Output = TArr<Prod<PInt<U>, V>, Prod<PInt<U>, A>>;
mul(self, _: TArr<V, A>) -> Self::Output182     fn mul(self, _: TArr<V, A>) -> Self::Output {
183         unsafe { ::core::mem::uninitialized() }
184     }
185 }
186 
187 impl<V, A, U> Mul<TArr<V, A>> for NInt<U>
188 where
189     U: Unsigned + NonZero,
190     NInt<U>: Mul<A> + Mul<V>,
191 {
192     type Output = TArr<Prod<NInt<U>, V>, Prod<NInt<U>, A>>;
mul(self, _: TArr<V, A>) -> Self::Output193     fn mul(self, _: TArr<V, A>) -> Self::Output {
194         unsafe { ::core::mem::uninitialized() }
195     }
196 }
197 
198 // ---------------------------------------------------------------------------------------
199 // Divide an array by a scalar
200 
201 impl<Rhs> Div<Rhs> for ATerm {
202     type Output = ATerm;
div(self, _: Rhs) -> Self::Output203     fn div(self, _: Rhs) -> Self::Output {
204         ATerm
205     }
206 }
207 
208 impl<V, A, Rhs> Div<Rhs> for TArr<V, A>
209 where
210     V: Div<Rhs>,
211     A: Div<Rhs>,
212 {
213     type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>;
div(self, _: Rhs) -> Self::Output214     fn div(self, _: Rhs) -> Self::Output {
215         unsafe { ::core::mem::uninitialized() }
216     }
217 }
218 
219 // ---------------------------------------------------------------------------------------
220 // Partial Divide an array by a scalar
221 
222 impl<Rhs> PartialDiv<Rhs> for ATerm {
223     type Output = ATerm;
partial_div(self, _: Rhs) -> Self::Output224     fn partial_div(self, _: Rhs) -> Self::Output {
225         ATerm
226     }
227 }
228 
229 impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A>
230 where
231     V: PartialDiv<Rhs>,
232     A: PartialDiv<Rhs>,
233 {
234     type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>;
partial_div(self, _: Rhs) -> Self::Output235     fn partial_div(self, _: Rhs) -> Self::Output {
236         unsafe { ::core::mem::uninitialized() }
237     }
238 }
239 
240 // ---------------------------------------------------------------------------------------
241 // Modulo an array by a scalar
242 use core::ops::Rem;
243 
244 impl<Rhs> Rem<Rhs> for ATerm {
245     type Output = ATerm;
rem(self, _: Rhs) -> Self::Output246     fn rem(self, _: Rhs) -> Self::Output {
247         ATerm
248     }
249 }
250 
251 impl<V, A, Rhs> Rem<Rhs> for TArr<V, A>
252 where
253     V: Rem<Rhs>,
254     A: Rem<Rhs>,
255 {
256     type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>;
rem(self, _: Rhs) -> Self::Output257     fn rem(self, _: Rhs) -> Self::Output {
258         unsafe { ::core::mem::uninitialized() }
259     }
260 }
261 
262 // ---------------------------------------------------------------------------------------
263 // Negate an array
264 use core::ops::Neg;
265 
266 impl Neg for ATerm {
267     type Output = ATerm;
neg(self) -> Self::Output268     fn neg(self) -> Self::Output {
269         ATerm
270     }
271 }
272 
273 impl<V, A> Neg for TArr<V, A>
274 where
275     V: Neg,
276     A: Neg,
277 {
278     type Output = TArr<Negate<V>, Negate<A>>;
neg(self) -> Self::Output279     fn neg(self) -> Self::Output {
280         unsafe { ::core::mem::uninitialized() }
281     }
282 }
283