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}
397