substrate_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#[cfg(feature = "derive_scale")]
7use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
8
9use super::*;
10
11/// The terminating type for type arrays.
12#[cfg_attr(
13    feature = "derive_scale",
14    derive(scale_info::TypeInfo, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen)
15)]
16#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)]
17pub struct ATerm;
18
19impl TypeArray for ATerm {}
20
21/// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its
22/// values can be more than bits, and it is designed to act as an array. So you can only add two if
23/// they have the same number of elements, for example.
24///
25/// This array is only really designed to contain `Integer` types. If you use it with others, you
26/// may find it lacking functionality.
27#[cfg_attr(
28    feature = "derive_scale",
29    derive(scale_info::TypeInfo, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen)
30)]
31#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)]
32pub struct TArr<V, A> {
33    first: V,
34    rest: A,
35}
36
37impl<V, A> TypeArray for TArr<V, A> {}
38
39/// Create a new type-level arrray. Only usable on Rust 1.13.0 or newer.
40///
41/// There's not a whole lot you can do with it right now.
42///
43/// # Example
44/// ```rust
45/// #[macro_use]
46/// extern crate typenum;
47/// use typenum::consts::*;
48///
49/// type Array = tarr![P3, N4, Z0, P38];
50/// # fn main() { let _: Array; }
51#[macro_export]
52macro_rules! tarr {
53    () => ( $crate::ATerm );
54    ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> );
55    ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> );
56    ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> );
57    ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> );
58}
59
60// ---------------------------------------------------------------------------------------
61// Length
62
63/// Length of `ATerm` by itself is 0
64impl Len for ATerm {
65    type Output = U0;
66    #[inline]
67    fn len(&self) -> Self::Output {
68        UTerm
69    }
70}
71
72/// Size of a `TypeArray`
73impl<V, A> Len for TArr<V, A>
74where
75    A: Len,
76    Length<A>: Add<B1>,
77    Sum<Length<A>, B1>: Unsigned,
78{
79    type Output = Add1<Length<A>>;
80    #[inline]
81    fn len(&self) -> Self::Output {
82        self.rest.len() + B1
83    }
84}
85
86// ---------------------------------------------------------------------------------------
87// Add arrays
88// Note that two arrays are only addable if they are the same length.
89
90impl Add<ATerm> for ATerm {
91    type Output = ATerm;
92    #[inline]
93    fn add(self, _: ATerm) -> Self::Output {
94        ATerm
95    }
96}
97
98impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al>
99where
100    Al: Add<Ar>,
101    Vl: Add<Vr>,
102{
103    type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>;
104    #[inline]
105    fn add(self, rhs: TArr<Vr, Ar>) -> Self::Output {
106        TArr {
107            first: self.first + rhs.first,
108            rest: self.rest + rhs.rest,
109        }
110    }
111}
112
113// ---------------------------------------------------------------------------------------
114// Subtract arrays
115// Note that two arrays are only subtractable if they are the same length.
116
117impl Sub<ATerm> for ATerm {
118    type Output = ATerm;
119    #[inline]
120    fn sub(self, _: ATerm) -> Self::Output {
121        ATerm
122    }
123}
124
125impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al>
126where
127    Vl: Sub<Vr>,
128    Al: Sub<Ar>,
129{
130    type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>;
131    #[inline]
132    fn sub(self, rhs: TArr<Vr, Ar>) -> Self::Output {
133        TArr {
134            first: self.first - rhs.first,
135            rest: self.rest - rhs.rest,
136        }
137    }
138}
139
140// ---------------------------------------------------------------------------------------
141// Multiply an array by a scalar
142
143impl<Rhs> Mul<Rhs> for ATerm {
144    type Output = ATerm;
145    #[inline]
146    fn mul(self, _: Rhs) -> Self::Output {
147        ATerm
148    }
149}
150
151impl<V, A, Rhs> Mul<Rhs> for TArr<V, A>
152where
153    V: Mul<Rhs>,
154    A: Mul<Rhs>,
155    Rhs: Copy,
156{
157    type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>;
158    #[inline]
159    fn mul(self, rhs: Rhs) -> Self::Output {
160        TArr {
161            first: self.first * rhs,
162            rest: self.rest * rhs,
163        }
164    }
165}
166
167impl Mul<ATerm> for Z0 {
168    type Output = ATerm;
169    #[inline]
170    fn mul(self, _: ATerm) -> Self::Output {
171        ATerm
172    }
173}
174
175impl<U> Mul<ATerm> for PInt<U>
176where
177    U: Unsigned + NonZero,
178{
179    type Output = ATerm;
180    #[inline]
181    fn mul(self, _: ATerm) -> Self::Output {
182        ATerm
183    }
184}
185
186impl<U> Mul<ATerm> for NInt<U>
187where
188    U: Unsigned + NonZero,
189{
190    type Output = ATerm;
191    #[inline]
192    fn mul(self, _: ATerm) -> Self::Output {
193        ATerm
194    }
195}
196
197impl<V, A> Mul<TArr<V, A>> for Z0
198where
199    Z0: Mul<A>,
200{
201    type Output = TArr<Z0, Prod<Z0, A>>;
202    #[inline]
203    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
204        TArr {
205            first: Z0,
206            rest: self * rhs.rest,
207        }
208    }
209}
210
211impl<V, A, U> Mul<TArr<V, A>> for PInt<U>
212where
213    U: Unsigned + NonZero,
214    PInt<U>: Mul<A> + Mul<V>,
215{
216    type Output = TArr<Prod<PInt<U>, V>, Prod<PInt<U>, A>>;
217    #[inline]
218    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
219        TArr {
220            first: self * rhs.first,
221            rest: self * rhs.rest,
222        }
223    }
224}
225
226impl<V, A, U> Mul<TArr<V, A>> for NInt<U>
227where
228    U: Unsigned + NonZero,
229    NInt<U>: Mul<A> + Mul<V>,
230{
231    type Output = TArr<Prod<NInt<U>, V>, Prod<NInt<U>, A>>;
232    #[inline]
233    fn mul(self, rhs: TArr<V, A>) -> Self::Output {
234        TArr {
235            first: self * rhs.first,
236            rest: self * rhs.rest,
237        }
238    }
239}
240
241// ---------------------------------------------------------------------------------------
242// Divide an array by a scalar
243
244impl<Rhs> Div<Rhs> for ATerm {
245    type Output = ATerm;
246    #[inline]
247    fn div(self, _: Rhs) -> Self::Output {
248        ATerm
249    }
250}
251
252impl<V, A, Rhs> Div<Rhs> for TArr<V, A>
253where
254    V: Div<Rhs>,
255    A: Div<Rhs>,
256    Rhs: Copy,
257{
258    type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>;
259    #[inline]
260    fn div(self, rhs: Rhs) -> Self::Output {
261        TArr {
262            first: self.first / rhs,
263            rest: self.rest / rhs,
264        }
265    }
266}
267
268// ---------------------------------------------------------------------------------------
269// Partial Divide an array by a scalar
270
271impl<Rhs> PartialDiv<Rhs> for ATerm {
272    type Output = ATerm;
273    #[inline]
274    fn partial_div(self, _: Rhs) -> Self::Output {
275        ATerm
276    }
277}
278
279impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A>
280where
281    V: PartialDiv<Rhs>,
282    A: PartialDiv<Rhs>,
283    Rhs: Copy,
284{
285    type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>;
286    #[inline]
287    fn partial_div(self, rhs: Rhs) -> Self::Output {
288        TArr {
289            first: self.first.partial_div(rhs),
290            rest: self.rest.partial_div(rhs),
291        }
292    }
293}
294
295// ---------------------------------------------------------------------------------------
296// Modulo an array by a scalar
297use core::ops::Rem;
298
299impl<Rhs> Rem<Rhs> for ATerm {
300    type Output = ATerm;
301    #[inline]
302    fn rem(self, _: Rhs) -> Self::Output {
303        ATerm
304    }
305}
306
307impl<V, A, Rhs> Rem<Rhs> for TArr<V, A>
308where
309    V: Rem<Rhs>,
310    A: Rem<Rhs>,
311    Rhs: Copy,
312{
313    type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>;
314    #[inline]
315    fn rem(self, rhs: Rhs) -> Self::Output {
316        TArr {
317            first: self.first % rhs,
318            rest: self.rest % rhs,
319        }
320    }
321}
322
323// ---------------------------------------------------------------------------------------
324// Negate an array
325use core::ops::Neg;
326
327impl Neg for ATerm {
328    type Output = ATerm;
329    #[inline]
330    fn neg(self) -> Self::Output {
331        ATerm
332    }
333}
334
335impl<V, A> Neg for TArr<V, A>
336where
337    V: Neg,
338    A: Neg,
339{
340    type Output = TArr<Negate<V>, Negate<A>>;
341    #[inline]
342    fn neg(self) -> Self::Output {
343        TArr {
344            first: -self.first,
345            rest: -self.rest,
346        }
347    }
348}