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