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::ops::{Add, Div, Mul, Sub}; |
6 | |
7 | use 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))] |
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 | #[cfg_attr (feature = "scale_info" , derive(scale_info::TypeInfo))] |
24 | pub struct TArr<V, A> { |
25 | first: V, |
26 | rest: A, |
27 | } |
28 | |
29 | impl<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 ] |
44 | macro_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 |
58 | impl 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` |
67 | impl<V, A> Len for TArr<V, A> |
68 | where |
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 |
84 | const _: () = { |
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 | |
99 | impl<V, A> FoldAdd for TArr<V, A> |
100 | where |
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 |
111 | const _: () = { |
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 | |
126 | impl<V, A> FoldMul for TArr<V, A> |
127 | where |
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 | |
138 | impl Add<ATerm> for ATerm { |
139 | type Output = ATerm; |
140 | #[inline ] |
141 | fn add(self, _: ATerm) -> Self::Output { |
142 | ATerm |
143 | } |
144 | } |
145 | |
146 | impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al> |
147 | where |
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 | |
165 | impl Sub<ATerm> for ATerm { |
166 | type Output = ATerm; |
167 | #[inline ] |
168 | fn sub(self, _: ATerm) -> Self::Output { |
169 | ATerm |
170 | } |
171 | } |
172 | |
173 | impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al> |
174 | where |
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 | |
191 | impl<Rhs> Mul<Rhs> for ATerm { |
192 | type Output = ATerm; |
193 | #[inline ] |
194 | fn mul(self, _: Rhs) -> Self::Output { |
195 | ATerm |
196 | } |
197 | } |
198 | |
199 | impl<V, A, Rhs> Mul<Rhs> for TArr<V, A> |
200 | where |
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 | |
215 | impl Mul<ATerm> for Z0 { |
216 | type Output = ATerm; |
217 | #[inline ] |
218 | fn mul(self, _: ATerm) -> Self::Output { |
219 | ATerm |
220 | } |
221 | } |
222 | |
223 | impl<U> Mul<ATerm> for PInt<U> |
224 | where |
225 | U: Unsigned + NonZero, |
226 | { |
227 | type Output = ATerm; |
228 | #[inline ] |
229 | fn mul(self, _: ATerm) -> Self::Output { |
230 | ATerm |
231 | } |
232 | } |
233 | |
234 | impl<U> Mul<ATerm> for NInt<U> |
235 | where |
236 | U: Unsigned + NonZero, |
237 | { |
238 | type Output = ATerm; |
239 | #[inline ] |
240 | fn mul(self, _: ATerm) -> Self::Output { |
241 | ATerm |
242 | } |
243 | } |
244 | |
245 | impl<V, A> Mul<TArr<V, A>> for Z0 |
246 | where |
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 | |
259 | impl<V, A, U> Mul<TArr<V, A>> for PInt<U> |
260 | where |
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 | |
274 | impl<V, A, U> Mul<TArr<V, A>> for NInt<U> |
275 | where |
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 | |
292 | impl<Rhs> Div<Rhs> for ATerm { |
293 | type Output = ATerm; |
294 | #[inline ] |
295 | fn div(self, _: Rhs) -> Self::Output { |
296 | ATerm |
297 | } |
298 | } |
299 | |
300 | impl<V, A, Rhs> Div<Rhs> for TArr<V, A> |
301 | where |
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 | |
319 | impl<Rhs> PartialDiv<Rhs> for ATerm { |
320 | type Output = ATerm; |
321 | #[inline ] |
322 | fn partial_div(self, _: Rhs) -> Self::Output { |
323 | ATerm |
324 | } |
325 | } |
326 | |
327 | impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A> |
328 | where |
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 |
345 | use core::ops::Rem; |
346 | |
347 | impl<Rhs> Rem<Rhs> for ATerm { |
348 | type Output = ATerm; |
349 | #[inline ] |
350 | fn rem(self, _: Rhs) -> Self::Output { |
351 | ATerm |
352 | } |
353 | } |
354 | |
355 | impl<V, A, Rhs> Rem<Rhs> for TArr<V, A> |
356 | where |
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 |
373 | use core::ops::Neg; |
374 | |
375 | impl Neg for ATerm { |
376 | type Output = ATerm; |
377 | #[inline ] |
378 | fn neg(self) -> Self::Output { |
379 | ATerm |
380 | } |
381 | } |
382 | |
383 | impl<V, A> Neg for TArr<V, A> |
384 | where |
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 | |