| 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 | } |
| 51 | |
| 52 | // --------------------------------------------------------------------------------------- |
| 53 | // Length |
| 54 | |
| 55 | /// Length of `ATerm` by itself is 0 |
| 56 | impl 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` |
| 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 ] |
| 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 | |
| 82 | impl Add<ATerm> for ATerm { |
| 83 | type Output = ATerm; |
| 84 | #[inline ] |
| 85 | 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 ] |
| 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 | |
| 109 | impl Sub<ATerm> for ATerm { |
| 110 | type Output = ATerm; |
| 111 | #[inline ] |
| 112 | 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 ] |
| 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 | |
| 135 | impl<Rhs> Mul<Rhs> for ATerm { |
| 136 | type Output = ATerm; |
| 137 | #[inline ] |
| 138 | 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 ] |
| 151 | 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 ] |
| 162 | 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 ] |
| 173 | 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 ] |
| 184 | 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 ] |
| 195 | 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 ] |
| 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 | |
| 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 ] |
| 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 | |
| 236 | impl<Rhs> Div<Rhs> for ATerm { |
| 237 | type Output = ATerm; |
| 238 | #[inline ] |
| 239 | 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 ] |
| 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 | |
| 263 | impl<Rhs> PartialDiv<Rhs> for ATerm { |
| 264 | type Output = ATerm; |
| 265 | #[inline ] |
| 266 | 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 ] |
| 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 |
| 289 | use core::ops::Rem; |
| 290 | |
| 291 | impl<Rhs> Rem<Rhs> for ATerm { |
| 292 | type Output = ATerm; |
| 293 | #[inline ] |
| 294 | 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 ] |
| 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 |
| 317 | use core::ops::Neg; |
| 318 | |
| 319 | impl Neg for ATerm { |
| 320 | type Output = ATerm; |
| 321 | #[inline ] |
| 322 | 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 ] |
| 334 | fn neg(self) -> Self::Output { |
| 335 | TArr { |
| 336 | first: -self.first, |
| 337 | rest: -self.rest, |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |