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 arrray. 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 } 51 52 // --------------------------------------------------------------------------------------- 53 // Length 54 55 /// Length of `ATerm` by itself is 0 56 impl Len for ATerm { 57 type Output = U0; 58 #[inline] len(&self) -> Self::Output59 fn len(&self) -> Self::Output { 60 UTerm 61 } 62 } 63 64 /// Size of a `TypeArray` 65 impl<V, A> Len for TArr<V, A> 66 where 67 A: Len, 68 Length<A>: Add<B1>, 69 Sum<Length<A>, B1>: Unsigned, 70 { 71 type Output = Add1<Length<A>>; 72 #[inline] len(&self) -> Self::Output73 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 82 impl Add<ATerm> for ATerm { 83 type Output = ATerm; 84 #[inline] add(self, _: ATerm) -> Self::Output85 fn add(self, _: ATerm) -> Self::Output { 86 ATerm 87 } 88 } 89 90 impl<Al, Vl, Ar, Vr> Add<TArr<Vr, Ar>> for TArr<Vl, Al> 91 where 92 Al: Add<Ar>, 93 Vl: Add<Vr>, 94 { 95 type Output = TArr<Sum<Vl, Vr>, Sum<Al, Ar>>; 96 #[inline] add(self, rhs: TArr<Vr, Ar>) -> Self::Output97 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 109 impl Sub<ATerm> for ATerm { 110 type Output = ATerm; 111 #[inline] sub(self, _: ATerm) -> Self::Output112 fn sub(self, _: ATerm) -> Self::Output { 113 ATerm 114 } 115 } 116 117 impl<Vl, Al, Vr, Ar> Sub<TArr<Vr, Ar>> for TArr<Vl, Al> 118 where 119 Vl: Sub<Vr>, 120 Al: Sub<Ar>, 121 { 122 type Output = TArr<Diff<Vl, Vr>, Diff<Al, Ar>>; 123 #[inline] sub(self, rhs: TArr<Vr, Ar>) -> Self::Output124 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 135 impl<Rhs> Mul<Rhs> for ATerm { 136 type Output = ATerm; 137 #[inline] mul(self, _: Rhs) -> Self::Output138 fn mul(self, _: Rhs) -> Self::Output { 139 ATerm 140 } 141 } 142 143 impl<V, A, Rhs> Mul<Rhs> for TArr<V, A> 144 where 145 V: Mul<Rhs>, 146 A: Mul<Rhs>, 147 Rhs: Copy, 148 { 149 type Output = TArr<Prod<V, Rhs>, Prod<A, Rhs>>; 150 #[inline] mul(self, rhs: Rhs) -> Self::Output151 fn mul(self, rhs: Rhs) -> Self::Output { 152 TArr { 153 first: self.first * rhs, 154 rest: self.rest * rhs, 155 } 156 } 157 } 158 159 impl Mul<ATerm> for Z0 { 160 type Output = ATerm; 161 #[inline] mul(self, _: ATerm) -> Self::Output162 fn mul(self, _: ATerm) -> Self::Output { 163 ATerm 164 } 165 } 166 167 impl<U> Mul<ATerm> for PInt<U> 168 where 169 U: Unsigned + NonZero, 170 { 171 type Output = ATerm; 172 #[inline] mul(self, _: ATerm) -> Self::Output173 fn mul(self, _: ATerm) -> Self::Output { 174 ATerm 175 } 176 } 177 178 impl<U> Mul<ATerm> for NInt<U> 179 where 180 U: Unsigned + NonZero, 181 { 182 type Output = ATerm; 183 #[inline] mul(self, _: ATerm) -> Self::Output184 fn mul(self, _: ATerm) -> Self::Output { 185 ATerm 186 } 187 } 188 189 impl<V, A> Mul<TArr<V, A>> for Z0 190 where 191 Z0: Mul<A>, 192 { 193 type Output = TArr<Z0, Prod<Z0, A>>; 194 #[inline] mul(self, rhs: TArr<V, A>) -> Self::Output195 fn mul(self, rhs: TArr<V, A>) -> Self::Output { 196 TArr { 197 first: Z0, 198 rest: self * rhs.rest, 199 } 200 } 201 } 202 203 impl<V, A, U> Mul<TArr<V, A>> for PInt<U> 204 where 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] mul(self, rhs: TArr<V, A>) -> Self::Output210 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 218 impl<V, A, U> Mul<TArr<V, A>> for NInt<U> 219 where 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] mul(self, rhs: TArr<V, A>) -> Self::Output225 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 236 impl<Rhs> Div<Rhs> for ATerm { 237 type Output = ATerm; 238 #[inline] div(self, _: Rhs) -> Self::Output239 fn div(self, _: Rhs) -> Self::Output { 240 ATerm 241 } 242 } 243 244 impl<V, A, Rhs> Div<Rhs> for TArr<V, A> 245 where 246 V: Div<Rhs>, 247 A: Div<Rhs>, 248 Rhs: Copy, 249 { 250 type Output = TArr<Quot<V, Rhs>, Quot<A, Rhs>>; 251 #[inline] div(self, rhs: Rhs) -> Self::Output252 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 263 impl<Rhs> PartialDiv<Rhs> for ATerm { 264 type Output = ATerm; 265 #[inline] partial_div(self, _: Rhs) -> Self::Output266 fn partial_div(self, _: Rhs) -> Self::Output { 267 ATerm 268 } 269 } 270 271 impl<V, A, Rhs> PartialDiv<Rhs> for TArr<V, A> 272 where 273 V: PartialDiv<Rhs>, 274 A: PartialDiv<Rhs>, 275 Rhs: Copy, 276 { 277 type Output = TArr<PartialQuot<V, Rhs>, PartialQuot<A, Rhs>>; 278 #[inline] partial_div(self, rhs: Rhs) -> Self::Output279 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 289 use core::ops::Rem; 290 291 impl<Rhs> Rem<Rhs> for ATerm { 292 type Output = ATerm; 293 #[inline] rem(self, _: Rhs) -> Self::Output294 fn rem(self, _: Rhs) -> Self::Output { 295 ATerm 296 } 297 } 298 299 impl<V, A, Rhs> Rem<Rhs> for TArr<V, A> 300 where 301 V: Rem<Rhs>, 302 A: Rem<Rhs>, 303 Rhs: Copy, 304 { 305 type Output = TArr<Mod<V, Rhs>, Mod<A, Rhs>>; 306 #[inline] rem(self, rhs: Rhs) -> Self::Output307 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 317 use core::ops::Neg; 318 319 impl Neg for ATerm { 320 type Output = ATerm; 321 #[inline] neg(self) -> Self::Output322 fn neg(self) -> Self::Output { 323 ATerm 324 } 325 } 326 327 impl<V, A> Neg for TArr<V, A> 328 where 329 V: Neg, 330 A: Neg, 331 { 332 type Output = TArr<Negate<V>, Negate<A>>; 333 #[inline] neg(self) -> Self::Output334 fn neg(self) -> Self::Output { 335 TArr { 336 first: -self.first, 337 rest: -self.rest, 338 } 339 } 340 } 341