1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Implementation of [`Bounded`], a wrapper around integer types limiting the number of bits 4 //! usable for value representation. 5 6 use core::{ 7 cmp, 8 fmt, 9 ops::{ 10 self, 11 Deref, // 12 }, //, 13 }; 14 15 use kernel::{ 16 num::Integer, 17 prelude::*, // 18 }; 19 20 /// Evaluates to `true` if `$value` can be represented using at most `$n` bits in a `$type`. 21 /// 22 /// `expr` must be of type `type`, or the result will be incorrect. 23 /// 24 /// Can be used in const context. 25 macro_rules! fits_within { 26 ($value:expr, $type:ty, $n:expr) => {{ 27 let shift: u32 = <$type>::BITS - $n; 28 29 // `value` fits within `$n` bits if shifting it left by the number of unused bits, then 30 // right by the same number, doesn't change it. 31 // 32 // This method has the benefit of working for both unsigned and signed values. 33 ($value << shift) >> shift == $value 34 }}; 35 } 36 37 /// Returns `true` if `value` can be represented with at most `N` bits in a `T`. 38 #[inline(always)] 39 fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool { 40 fits_within!(value, T, num_bits) 41 } 42 43 /// An integer value that requires only the `N` least significant bits of the wrapped type to be 44 /// encoded. 45 /// 46 /// This limits the number of usable bits in the wrapped integer type, and thus the stored value to 47 /// a narrower range, which provides guarantees that can be useful when working within e.g. 48 /// bitfields. 49 /// 50 /// # Invariants 51 /// 52 /// - `N` is greater than `0`. 53 /// - `N` is less than or equal to `T::BITS`. 54 /// - Stored values can be represented with at most `N` bits. 55 /// 56 /// # Examples 57 /// 58 /// The preferred way to create values is through constants and the [`Bounded::new`] family of 59 /// constructors, as they trigger a build error if the type invariants cannot be upheld. 60 /// 61 /// ``` 62 /// use kernel::num::Bounded; 63 /// 64 /// // An unsigned 8-bit integer, of which only the 4 LSBs are used. 65 /// // The value `15` is statically validated to fit that constraint at build time. 66 /// let v = Bounded::<u8, 4>::new::<15>(); 67 /// assert_eq!(v.get(), 15); 68 /// 69 /// // Same using signed values. 70 /// let v = Bounded::<i8, 4>::new::<-8>(); 71 /// assert_eq!(v.get(), -8); 72 /// 73 /// // This doesn't build: a `u8` is smaller than the requested 9 bits. 74 /// // let _ = Bounded::<u8, 9>::new::<10>(); 75 /// 76 /// // This also doesn't build: the requested value doesn't fit within 4 signed bits. 77 /// // let _ = Bounded::<i8, 4>::new::<8>(); 78 /// ``` 79 /// 80 /// Values can also be validated at runtime with [`Bounded::try_new`]. 81 /// 82 /// ``` 83 /// use kernel::num::Bounded; 84 /// 85 /// // This succeeds because `15` can be represented with 4 unsigned bits. 86 /// assert!(Bounded::<u8, 4>::try_new(15).is_some()); 87 /// 88 /// // This fails because `16` cannot be represented with 4 unsigned bits. 89 /// assert!(Bounded::<u8, 4>::try_new(16).is_none()); 90 /// ``` 91 /// 92 /// Non-constant expressions can be validated at build-time thanks to compiler optimizations. This 93 /// should be used with caution, on simple expressions only. 94 /// 95 /// ``` 96 /// use kernel::num::Bounded; 97 /// # fn some_number() -> u32 { 0xffffffff } 98 /// 99 /// // Here the compiler can infer from the mask that the type invariants are not violated, even 100 /// // though the value returned by `some_number` is not statically known. 101 /// let v = Bounded::<u32, 4>::from_expr(some_number() & 0xf); 102 /// ``` 103 /// 104 /// Comparison and arithmetic operations are supported on [`Bounded`]s with a compatible backing 105 /// type, regardless of their number of valid bits. 106 /// 107 /// ``` 108 /// use kernel::num::Bounded; 109 /// 110 /// let v1 = Bounded::<u32, 8>::new::<4>(); 111 /// let v2 = Bounded::<u32, 4>::new::<15>(); 112 /// 113 /// assert!(v1 != v2); 114 /// assert!(v1 < v2); 115 /// assert_eq!(v1 + v2, 19); 116 /// assert_eq!(v2 % v1, 3); 117 /// ``` 118 /// 119 /// These operations are also supported between a [`Bounded`] and its backing type. 120 /// 121 /// ``` 122 /// use kernel::num::Bounded; 123 /// 124 /// let v = Bounded::<u8, 4>::new::<15>(); 125 /// 126 /// assert!(v == 15); 127 /// assert!(v > 12); 128 /// assert_eq!(v + 5, 20); 129 /// assert_eq!(v / 3, 5); 130 /// ``` 131 /// 132 /// A change of backing types is possible using [`Bounded::cast`], and the number of valid bits can 133 /// be extended or reduced with [`Bounded::extend`] and [`Bounded::try_shrink`]. 134 /// 135 /// ``` 136 /// use kernel::num::Bounded; 137 /// 138 /// let v = Bounded::<u32, 12>::new::<127>(); 139 /// 140 /// // Changes backing type from `u32` to `u16`. 141 /// let _: Bounded<u16, 12> = v.cast(); 142 /// 143 /// // This does not build, as `u8` is smaller than 12 bits. 144 /// // let _: Bounded<u8, 12> = v.cast(); 145 /// 146 /// // We can safely extend the number of bits... 147 /// let _ = v.extend::<15>(); 148 /// 149 /// // ... to the limits of the backing type. This doesn't build as a `u32` cannot contain 33 bits. 150 /// // let _ = v.extend::<33>(); 151 /// 152 /// // Reducing the number of bits is validated at runtime. This works because `127` can be 153 /// // represented with 8 bits. 154 /// assert!(v.try_shrink::<8>().is_some()); 155 /// 156 /// // ... but not with 6, so this fails. 157 /// assert!(v.try_shrink::<6>().is_none()); 158 /// ``` 159 /// 160 /// Infallible conversions from a primitive integer to a large-enough [`Bounded`] are supported. 161 /// 162 /// ``` 163 /// use kernel::num::Bounded; 164 /// 165 /// // This unsigned `Bounded` has 8 bits, so it can represent any `u8`. 166 /// let v = Bounded::<u32, 8>::from(128u8); 167 /// assert_eq!(v.get(), 128); 168 /// 169 /// // This signed `Bounded` has 8 bits, so it can represent any `i8`. 170 /// let v = Bounded::<i32, 8>::from(-128i8); 171 /// assert_eq!(v.get(), -128); 172 /// 173 /// // This doesn't build, as this 6-bit `Bounded` does not have enough capacity to represent a 174 /// // `u8` (regardless of the passed value). 175 /// // let _ = Bounded::<u32, 6>::from(10u8); 176 /// 177 /// // Booleans can be converted into single-bit `Bounded`s. 178 /// 179 /// let v = Bounded::<u64, 1>::from(false); 180 /// assert_eq!(v.get(), 0); 181 /// 182 /// let v = Bounded::<u64, 1>::from(true); 183 /// assert_eq!(v.get(), 1); 184 /// ``` 185 /// 186 /// Infallible conversions from a [`Bounded`] to a primitive integer are also supported, and 187 /// dependent on the number of bits used for value representation, not on the backing type. 188 /// 189 /// ``` 190 /// use kernel::num::Bounded; 191 /// 192 /// // Even though its backing type is `u32`, this `Bounded` only uses 6 bits and thus can safely 193 /// // be converted to a `u8`. 194 /// let v = Bounded::<u32, 6>::new::<63>(); 195 /// assert_eq!(u8::from(v), 63); 196 /// 197 /// // Same using signed values. 198 /// let v = Bounded::<i32, 8>::new::<-128>(); 199 /// assert_eq!(i8::from(v), -128); 200 /// 201 /// // This however does not build, as 10 bits won't fit into a `u8` (regardless of the actually 202 /// // contained value). 203 /// let _v = Bounded::<u32, 10>::new::<10>(); 204 /// // assert_eq!(u8::from(_v), 10); 205 /// 206 /// // Single-bit `Bounded`s can be converted into a boolean. 207 /// let v = Bounded::<u8, 1>::new::<1>(); 208 /// assert_eq!(bool::from(v), true); 209 /// 210 /// let v = Bounded::<u8, 1>::new::<0>(); 211 /// assert_eq!(bool::from(v), false); 212 /// ``` 213 /// 214 /// Fallible conversions from any primitive integer to any [`Bounded`] are also supported using the 215 /// [`TryIntoBounded`] trait. 216 /// 217 /// ``` 218 /// use kernel::num::{Bounded, TryIntoBounded}; 219 /// 220 /// // Succeeds because `128` fits into 8 bits. 221 /// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded(); 222 /// assert_eq!(v.as_deref().copied(), Some(128)); 223 /// 224 /// // Fails because `128` doesn't fit into 6 bits. 225 /// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded(); 226 /// assert_eq!(v, None); 227 /// ``` 228 #[repr(transparent)] 229 #[derive(Clone, Copy, Debug, Default, Hash)] 230 pub struct Bounded<T: Integer, const N: u32>(T); 231 232 /// Validating the value as a const expression cannot be done as a regular method, as the 233 /// arithmetic operations we rely on to check the bounds are not const. Thus, implement 234 /// [`Bounded::new`] using a macro. 235 macro_rules! impl_const_new { 236 ($($type:ty)*) => { 237 $( 238 impl<const N: u32> Bounded<$type, N> { 239 /// Creates a [`Bounded`] for the constant `VALUE`. 240 /// 241 /// Fails at build time if `VALUE` cannot be represented with `N` bits. 242 /// 243 /// This method should be preferred to [`Self::from_expr`] whenever possible. 244 /// 245 /// # Examples 246 /// 247 /// ``` 248 /// use kernel::num::Bounded; 249 /// 250 #[doc = ::core::concat!( 251 "let v = Bounded::<", 252 ::core::stringify!($type), 253 ", 4>::new::<7>();")] 254 /// assert_eq!(v.get(), 7); 255 /// ``` 256 pub const fn new<const VALUE: $type>() -> Self { 257 // Statically assert that `VALUE` fits within the set number of bits. 258 const { 259 assert!(fits_within!(VALUE, $type, N)); 260 } 261 262 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within 263 // `N` bits. 264 unsafe { Self::__new(VALUE) } 265 } 266 } 267 )* 268 }; 269 } 270 271 impl_const_new!( 272 u8 u16 u32 u64 usize 273 i8 i16 i32 i64 isize 274 ); 275 276 impl<T, const N: u32> Bounded<T, N> 277 where 278 T: Integer, 279 { 280 /// Private constructor enforcing the type invariants. 281 /// 282 /// All instances of [`Bounded`] must be created through this method as it enforces most of the 283 /// type invariants. 284 /// 285 /// The caller remains responsible for checking, either statically or dynamically, that `value` 286 /// can be represented as a `T` using at most `N` bits. 287 /// 288 /// # Safety 289 /// 290 /// The caller must ensure that `value` can be represented within `N` bits. 291 const unsafe fn __new(value: T) -> Self { 292 // Enforce the type invariants. 293 const { 294 // `N` cannot be zero. 295 assert!(N != 0); 296 // The backing type is at least as large as `N` bits. 297 assert!(N <= T::BITS); 298 } 299 300 Self(value) 301 } 302 303 /// Attempts to turn `value` into a `Bounded` using `N` bits. 304 /// 305 /// Returns [`None`] if `value` doesn't fit within `N` bits. 306 /// 307 /// # Examples 308 /// 309 /// ``` 310 /// use kernel::num::Bounded; 311 /// 312 /// let v = Bounded::<u8, 1>::try_new(1); 313 /// assert_eq!(v.as_deref().copied(), Some(1)); 314 /// 315 /// let v = Bounded::<i8, 4>::try_new(-2); 316 /// assert_eq!(v.as_deref().copied(), Some(-2)); 317 /// 318 /// // `0x1ff` doesn't fit into 8 unsigned bits. 319 /// let v = Bounded::<u32, 8>::try_new(0x1ff); 320 /// assert_eq!(v, None); 321 /// 322 /// // The range of values representable with 4 bits is `[-8..=7]`. The following tests these 323 /// // limits. 324 /// let v = Bounded::<i8, 4>::try_new(-8); 325 /// assert_eq!(v.map(Bounded::get), Some(-8)); 326 /// let v = Bounded::<i8, 4>::try_new(-9); 327 /// assert_eq!(v, None); 328 /// let v = Bounded::<i8, 4>::try_new(7); 329 /// assert_eq!(v.map(Bounded::get), Some(7)); 330 /// let v = Bounded::<i8, 4>::try_new(8); 331 /// assert_eq!(v, None); 332 /// ``` 333 pub fn try_new(value: T) -> Option<Self> { 334 fits_within(value, N).then(|| { 335 // SAFETY: `fits_within` confirmed that `value` can be represented within `N` bits. 336 unsafe { Self::__new(value) } 337 }) 338 } 339 340 /// Checks that `expr` is valid for this type at compile-time and build a new value. 341 /// 342 /// This relies on [`build_assert!`] and guaranteed optimization to perform validation at 343 /// compile-time. If `expr` cannot be proved to be within the requested bounds at compile-time, 344 /// use the fallible [`Self::try_new`] instead. 345 /// 346 /// Limit this to simple, easily provable expressions, and prefer one of the [`Self::new`] 347 /// constructors whenever possible as they statically validate the value instead of relying on 348 /// compiler optimizations. 349 /// 350 /// # Examples 351 /// 352 /// ``` 353 /// use kernel::num::Bounded; 354 /// # fn some_number() -> u32 { 0xffffffff } 355 /// 356 /// // Some undefined number. 357 /// let v: u32 = some_number(); 358 /// 359 /// // Triggers a build error as `v` cannot be asserted to fit within 4 bits... 360 /// // let _ = Bounded::<u32, 4>::from_expr(v); 361 /// 362 /// // ... but this works as the compiler can assert the range from the mask. 363 /// let _ = Bounded::<u32, 4>::from_expr(v & 0xf); 364 /// 365 /// // These expressions are simple enough to be proven correct, but since they are static the 366 /// // `new` constructor should be preferred. 367 /// assert_eq!(Bounded::<u8, 1>::from_expr(1).get(), 1); 368 /// assert_eq!(Bounded::<u16, 8>::from_expr(0xff).get(), 0xff); 369 /// ``` 370 // Always inline to optimize out error path of `build_assert`. 371 #[inline(always)] 372 pub fn from_expr(expr: T) -> Self { 373 crate::build_assert!( 374 fits_within(expr, N), 375 "Requested value larger than maximal representable value." 376 ); 377 378 // SAFETY: `fits_within` confirmed that `expr` can be represented within `N` bits. 379 unsafe { Self::__new(expr) } 380 } 381 382 /// Returns the wrapped value as the backing type. 383 /// 384 /// # Examples 385 /// 386 /// ``` 387 /// use kernel::num::Bounded; 388 /// 389 /// let v = Bounded::<u32, 4>::new::<7>(); 390 /// assert_eq!(v.get(), 7u32); 391 /// ``` 392 pub fn get(self) -> T { 393 *self.deref() 394 } 395 396 /// Increases the number of bits usable for `self`. 397 /// 398 /// This operation cannot fail. 399 /// 400 /// # Examples 401 /// 402 /// ``` 403 /// use kernel::num::Bounded; 404 /// 405 /// let v = Bounded::<u32, 4>::new::<7>(); 406 /// let larger_v = v.extend::<12>(); 407 /// // The contained values are equal even though `larger_v` has a bigger capacity. 408 /// assert_eq!(larger_v, v); 409 /// ``` 410 pub const fn extend<const M: u32>(self) -> Bounded<T, M> { 411 const { 412 assert!( 413 M >= N, 414 "Requested number of bits is less than the current representation." 415 ); 416 } 417 418 // SAFETY: The value did fit within `N` bits, so it will all the more fit within 419 // the larger `M` bits. 420 unsafe { Bounded::__new(self.0) } 421 } 422 423 /// Attempts to shrink the number of bits usable for `self`. 424 /// 425 /// Returns [`None`] if the value of `self` cannot be represented within `M` bits. 426 /// 427 /// # Examples 428 /// 429 /// ``` 430 /// use kernel::num::Bounded; 431 /// 432 /// let v = Bounded::<u32, 12>::new::<7>(); 433 /// 434 /// // `7` can be represented using 3 unsigned bits... 435 /// let smaller_v = v.try_shrink::<3>(); 436 /// assert_eq!(smaller_v.as_deref().copied(), Some(7)); 437 /// 438 /// // ... but doesn't fit within `2` bits. 439 /// assert_eq!(v.try_shrink::<2>(), None); 440 /// ``` 441 pub fn try_shrink<const M: u32>(self) -> Option<Bounded<T, M>> { 442 Bounded::<T, M>::try_new(self.get()) 443 } 444 445 /// Casts `self` into a [`Bounded`] backed by a different storage type, but using the same 446 /// number of valid bits. 447 /// 448 /// Both `T` and `U` must be of same signedness, and `U` must be at least as large as 449 /// `N` bits, or a build error will occur. 450 /// 451 /// # Examples 452 /// 453 /// ``` 454 /// use kernel::num::Bounded; 455 /// 456 /// let v = Bounded::<u32, 12>::new::<127>(); 457 /// 458 /// let u16_v: Bounded<u16, 12> = v.cast(); 459 /// assert_eq!(u16_v.get(), 127); 460 /// 461 /// // This won't build: a `u8` is smaller than the required 12 bits. 462 /// // let _: Bounded<u8, 12> = v.cast(); 463 /// ``` 464 pub fn cast<U>(self) -> Bounded<U, N> 465 where 466 U: TryFrom<T> + Integer, 467 T: Integer, 468 U: Integer<Signedness = T::Signedness>, 469 { 470 // SAFETY: The converted value is represented using `N` bits, `U` can contain `N` bits, and 471 // `U` and `T` have the same sign, hence this conversion cannot fail. 472 let value = unsafe { U::try_from(self.get()).unwrap_unchecked() }; 473 474 // SAFETY: Although the backing type has changed, the value is still represented within 475 // `N` bits, and with the same signedness. 476 unsafe { Bounded::__new(value) } 477 } 478 } 479 480 impl<T, const N: u32> Deref for Bounded<T, N> 481 where 482 T: Integer, 483 { 484 type Target = T; 485 486 fn deref(&self) -> &Self::Target { 487 // Enforce the invariant to inform the compiler of the bounds of the value. 488 if !fits_within(self.0, N) { 489 // SAFETY: Per the `Bounded` invariants, `fits_within` can never return `false` on the 490 // value of a valid instance. 491 unsafe { core::hint::unreachable_unchecked() } 492 } 493 494 &self.0 495 } 496 } 497 498 /// Trait similar to [`TryInto`] but for [`Bounded`], to avoid conflicting implementations. 499 /// 500 /// # Examples 501 /// 502 /// ``` 503 /// use kernel::num::{Bounded, TryIntoBounded}; 504 /// 505 /// // Succeeds because `128` fits into 8 bits. 506 /// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded(); 507 /// assert_eq!(v.as_deref().copied(), Some(128)); 508 /// 509 /// // Fails because `128` doesn't fit into 6 bits. 510 /// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded(); 511 /// assert_eq!(v, None); 512 /// ``` 513 pub trait TryIntoBounded<T: Integer, const N: u32> { 514 /// Attempts to convert `self` into a [`Bounded`] using `N` bits. 515 /// 516 /// Returns [`None`] if `self` does not fit into the target type. 517 fn try_into_bounded(self) -> Option<Bounded<T, N>>; 518 } 519 520 /// Any integer value can be attempted to be converted into a [`Bounded`] of any size. 521 impl<T, U, const N: u32> TryIntoBounded<T, N> for U 522 where 523 T: Integer, 524 U: TryInto<T>, 525 { 526 fn try_into_bounded(self) -> Option<Bounded<T, N>> { 527 self.try_into().ok().and_then(Bounded::try_new) 528 } 529 } 530 531 // Comparisons between `Bounded`s. 532 533 impl<T, U, const N: u32, const M: u32> PartialEq<Bounded<U, M>> for Bounded<T, N> 534 where 535 T: Integer, 536 U: Integer, 537 T: PartialEq<U>, 538 { 539 fn eq(&self, other: &Bounded<U, M>) -> bool { 540 self.get() == other.get() 541 } 542 } 543 544 impl<T, const N: u32> Eq for Bounded<T, N> where T: Integer {} 545 546 impl<T, U, const N: u32, const M: u32> PartialOrd<Bounded<U, M>> for Bounded<T, N> 547 where 548 T: Integer, 549 U: Integer, 550 T: PartialOrd<U>, 551 { 552 fn partial_cmp(&self, other: &Bounded<U, M>) -> Option<cmp::Ordering> { 553 self.get().partial_cmp(&other.get()) 554 } 555 } 556 557 impl<T, const N: u32> Ord for Bounded<T, N> 558 where 559 T: Integer, 560 T: Ord, 561 { 562 fn cmp(&self, other: &Self) -> cmp::Ordering { 563 self.get().cmp(&other.get()) 564 } 565 } 566 567 // Comparisons between a `Bounded` and its backing type. 568 569 impl<T, const N: u32> PartialEq<T> for Bounded<T, N> 570 where 571 T: Integer, 572 T: PartialEq, 573 { 574 fn eq(&self, other: &T) -> bool { 575 self.get() == *other 576 } 577 } 578 579 impl<T, const N: u32> PartialOrd<T> for Bounded<T, N> 580 where 581 T: Integer, 582 T: PartialOrd, 583 { 584 fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> { 585 self.get().partial_cmp(other) 586 } 587 } 588 589 // Implementations of `core::ops` for two `Bounded` with the same backing type. 590 591 impl<T, const N: u32, const M: u32> ops::Add<Bounded<T, M>> for Bounded<T, N> 592 where 593 T: Integer, 594 T: ops::Add<Output = T>, 595 { 596 type Output = T; 597 598 fn add(self, rhs: Bounded<T, M>) -> Self::Output { 599 self.get() + rhs.get() 600 } 601 } 602 603 impl<T, const N: u32, const M: u32> ops::BitAnd<Bounded<T, M>> for Bounded<T, N> 604 where 605 T: Integer, 606 T: ops::BitAnd<Output = T>, 607 { 608 type Output = T; 609 610 fn bitand(self, rhs: Bounded<T, M>) -> Self::Output { 611 self.get() & rhs.get() 612 } 613 } 614 615 impl<T, const N: u32, const M: u32> ops::BitOr<Bounded<T, M>> for Bounded<T, N> 616 where 617 T: Integer, 618 T: ops::BitOr<Output = T>, 619 { 620 type Output = T; 621 622 fn bitor(self, rhs: Bounded<T, M>) -> Self::Output { 623 self.get() | rhs.get() 624 } 625 } 626 627 impl<T, const N: u32, const M: u32> ops::BitXor<Bounded<T, M>> for Bounded<T, N> 628 where 629 T: Integer, 630 T: ops::BitXor<Output = T>, 631 { 632 type Output = T; 633 634 fn bitxor(self, rhs: Bounded<T, M>) -> Self::Output { 635 self.get() ^ rhs.get() 636 } 637 } 638 639 impl<T, const N: u32, const M: u32> ops::Div<Bounded<T, M>> for Bounded<T, N> 640 where 641 T: Integer, 642 T: ops::Div<Output = T>, 643 { 644 type Output = T; 645 646 fn div(self, rhs: Bounded<T, M>) -> Self::Output { 647 self.get() / rhs.get() 648 } 649 } 650 651 impl<T, const N: u32, const M: u32> ops::Mul<Bounded<T, M>> for Bounded<T, N> 652 where 653 T: Integer, 654 T: ops::Mul<Output = T>, 655 { 656 type Output = T; 657 658 fn mul(self, rhs: Bounded<T, M>) -> Self::Output { 659 self.get() * rhs.get() 660 } 661 } 662 663 impl<T, const N: u32, const M: u32> ops::Rem<Bounded<T, M>> for Bounded<T, N> 664 where 665 T: Integer, 666 T: ops::Rem<Output = T>, 667 { 668 type Output = T; 669 670 fn rem(self, rhs: Bounded<T, M>) -> Self::Output { 671 self.get() % rhs.get() 672 } 673 } 674 675 impl<T, const N: u32, const M: u32> ops::Sub<Bounded<T, M>> for Bounded<T, N> 676 where 677 T: Integer, 678 T: ops::Sub<Output = T>, 679 { 680 type Output = T; 681 682 fn sub(self, rhs: Bounded<T, M>) -> Self::Output { 683 self.get() - rhs.get() 684 } 685 } 686 687 // Implementations of `core::ops` between a `Bounded` and its backing type. 688 689 impl<T, const N: u32> ops::Add<T> for Bounded<T, N> 690 where 691 T: Integer, 692 T: ops::Add<Output = T>, 693 { 694 type Output = T; 695 696 fn add(self, rhs: T) -> Self::Output { 697 self.get() + rhs 698 } 699 } 700 701 impl<T, const N: u32> ops::BitAnd<T> for Bounded<T, N> 702 where 703 T: Integer, 704 T: ops::BitAnd<Output = T>, 705 { 706 type Output = T; 707 708 fn bitand(self, rhs: T) -> Self::Output { 709 self.get() & rhs 710 } 711 } 712 713 impl<T, const N: u32> ops::BitOr<T> for Bounded<T, N> 714 where 715 T: Integer, 716 T: ops::BitOr<Output = T>, 717 { 718 type Output = T; 719 720 fn bitor(self, rhs: T) -> Self::Output { 721 self.get() | rhs 722 } 723 } 724 725 impl<T, const N: u32> ops::BitXor<T> for Bounded<T, N> 726 where 727 T: Integer, 728 T: ops::BitXor<Output = T>, 729 { 730 type Output = T; 731 732 fn bitxor(self, rhs: T) -> Self::Output { 733 self.get() ^ rhs 734 } 735 } 736 737 impl<T, const N: u32> ops::Div<T> for Bounded<T, N> 738 where 739 T: Integer, 740 T: ops::Div<Output = T>, 741 { 742 type Output = T; 743 744 fn div(self, rhs: T) -> Self::Output { 745 self.get() / rhs 746 } 747 } 748 749 impl<T, const N: u32> ops::Mul<T> for Bounded<T, N> 750 where 751 T: Integer, 752 T: ops::Mul<Output = T>, 753 { 754 type Output = T; 755 756 fn mul(self, rhs: T) -> Self::Output { 757 self.get() * rhs 758 } 759 } 760 761 impl<T, const N: u32> ops::Neg for Bounded<T, N> 762 where 763 T: Integer, 764 T: ops::Neg<Output = T>, 765 { 766 type Output = T; 767 768 fn neg(self) -> Self::Output { 769 -self.get() 770 } 771 } 772 773 impl<T, const N: u32> ops::Not for Bounded<T, N> 774 where 775 T: Integer, 776 T: ops::Not<Output = T>, 777 { 778 type Output = T; 779 780 fn not(self) -> Self::Output { 781 !self.get() 782 } 783 } 784 785 impl<T, const N: u32> ops::Rem<T> for Bounded<T, N> 786 where 787 T: Integer, 788 T: ops::Rem<Output = T>, 789 { 790 type Output = T; 791 792 fn rem(self, rhs: T) -> Self::Output { 793 self.get() % rhs 794 } 795 } 796 797 impl<T, const N: u32> ops::Sub<T> for Bounded<T, N> 798 where 799 T: Integer, 800 T: ops::Sub<Output = T>, 801 { 802 type Output = T; 803 804 fn sub(self, rhs: T) -> Self::Output { 805 self.get() - rhs 806 } 807 } 808 809 // Proxy implementations of `core::fmt`. 810 811 impl<T, const N: u32> fmt::Display for Bounded<T, N> 812 where 813 T: Integer, 814 T: fmt::Display, 815 { 816 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 817 self.get().fmt(f) 818 } 819 } 820 821 impl<T, const N: u32> fmt::Binary for Bounded<T, N> 822 where 823 T: Integer, 824 T: fmt::Binary, 825 { 826 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 827 self.get().fmt(f) 828 } 829 } 830 831 impl<T, const N: u32> fmt::LowerExp for Bounded<T, N> 832 where 833 T: Integer, 834 T: fmt::LowerExp, 835 { 836 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 837 self.get().fmt(f) 838 } 839 } 840 841 impl<T, const N: u32> fmt::LowerHex for Bounded<T, N> 842 where 843 T: Integer, 844 T: fmt::LowerHex, 845 { 846 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 847 self.get().fmt(f) 848 } 849 } 850 851 impl<T, const N: u32> fmt::Octal for Bounded<T, N> 852 where 853 T: Integer, 854 T: fmt::Octal, 855 { 856 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 857 self.get().fmt(f) 858 } 859 } 860 861 impl<T, const N: u32> fmt::UpperExp for Bounded<T, N> 862 where 863 T: Integer, 864 T: fmt::UpperExp, 865 { 866 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 867 self.get().fmt(f) 868 } 869 } 870 871 impl<T, const N: u32> fmt::UpperHex for Bounded<T, N> 872 where 873 T: Integer, 874 T: fmt::UpperHex, 875 { 876 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 877 self.get().fmt(f) 878 } 879 } 880 881 /// Implements `$trait` for all [`Bounded`] types represented using `$num_bits`. 882 /// 883 /// This is used to declare size properties as traits that we can constrain against in impl blocks. 884 macro_rules! impl_size_rule { 885 ($trait:ty, $($num_bits:literal)*) => { 886 $( 887 impl<T> $trait for Bounded<T, $num_bits> where T: Integer {} 888 )* 889 }; 890 } 891 892 /// Local trait expressing the fact that a given [`Bounded`] has at least `N` bits used for value 893 /// representation. 894 trait AtLeastXBits<const N: usize> {} 895 896 /// Implementations for infallibly converting a primitive type into a [`Bounded`] that can contain 897 /// it. 898 /// 899 /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent 900 /// module. 901 mod atleast_impls { 902 use super::*; 903 904 // Number of bits at least as large as 64. 905 impl_size_rule!(AtLeastXBits<64>, 64); 906 907 // Anything 64 bits or more is also larger than 32. 908 impl<T> AtLeastXBits<32> for T where T: AtLeastXBits<64> {} 909 // Other numbers of bits at least as large as 32. 910 impl_size_rule!(AtLeastXBits<32>, 911 32 33 34 35 36 37 38 39 912 40 41 42 43 44 45 46 47 913 48 49 50 51 52 53 54 55 914 56 57 58 59 60 61 62 63 915 ); 916 917 // Anything 32 bits or more is also larger than 16. 918 impl<T> AtLeastXBits<16> for T where T: AtLeastXBits<32> {} 919 // Other numbers of bits at least as large as 16. 920 impl_size_rule!(AtLeastXBits<16>, 921 16 17 18 19 20 21 22 23 922 24 25 26 27 28 29 30 31 923 ); 924 925 // Anything 16 bits or more is also larger than 8. 926 impl<T> AtLeastXBits<8> for T where T: AtLeastXBits<16> {} 927 // Other numbers of bits at least as large as 8. 928 impl_size_rule!(AtLeastXBits<8>, 8 9 10 11 12 13 14 15); 929 } 930 931 /// Generates `From` implementations from a primitive type into a [`Bounded`] with 932 /// enough bits to store any value of that type. 933 /// 934 /// Note: The only reason for having this macro is that if we pass `$type` as a generic 935 /// parameter, we cannot use it in the const context of [`AtLeastXBits`]'s generic parameter. This 936 /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a 937 /// regular `impl` block. 938 macro_rules! impl_from_primitive { 939 ($($type:ty)*) => { 940 $( 941 #[doc = ::core::concat!( 942 "Conversion from a [`", 943 ::core::stringify!($type), 944 "`] into a [`Bounded`] of same signedness with enough bits to store it.")] 945 impl<T, const N: u32> From<$type> for Bounded<T, N> 946 where 947 $type: Integer, 948 T: Integer<Signedness = <$type as Integer>::Signedness> + From<$type>, 949 Self: AtLeastXBits<{ <$type as Integer>::BITS as usize }>, 950 { 951 fn from(value: $type) -> Self { 952 // SAFETY: The trait bound on `Self` guarantees that `N` bits is 953 // enough to hold any value of the source type. 954 unsafe { Self::__new(T::from(value)) } 955 } 956 } 957 )* 958 } 959 } 960 961 impl_from_primitive!( 962 u8 u16 u32 u64 usize 963 i8 i16 i32 i64 isize 964 ); 965 966 /// Local trait expressing the fact that a given [`Bounded`] fits into a primitive type of `N` bits, 967 /// provided they have the same signedness. 968 trait FitsInXBits<const N: usize> {} 969 970 /// Implementations for infallibly converting a [`Bounded`] into a primitive type that can contain 971 /// it. 972 /// 973 /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent 974 /// module. 975 mod fits_impls { 976 use super::*; 977 978 // Number of bits that fit into a 8-bits primitive. 979 impl_size_rule!(FitsInXBits<8>, 1 2 3 4 5 6 7 8); 980 981 // Anything that fits into 8 bits also fits into 16. 982 impl<T> FitsInXBits<16> for T where T: FitsInXBits<8> {} 983 // Other number of bits that fit into a 16-bits primitive. 984 impl_size_rule!(FitsInXBits<16>, 9 10 11 12 13 14 15 16); 985 986 // Anything that fits into 16 bits also fits into 32. 987 impl<T> FitsInXBits<32> for T where T: FitsInXBits<16> {} 988 // Other number of bits that fit into a 32-bits primitive. 989 impl_size_rule!(FitsInXBits<32>, 990 17 18 19 20 21 22 23 24 991 25 26 27 28 29 30 31 32 992 ); 993 994 // Anything that fits into 32 bits also fits into 64. 995 impl<T> FitsInXBits<64> for T where T: FitsInXBits<32> {} 996 // Other number of bits that fit into a 64-bits primitive. 997 impl_size_rule!(FitsInXBits<64>, 998 33 34 35 36 37 38 39 40 999 41 42 43 44 45 46 47 48 1000 49 50 51 52 53 54 55 56 1001 57 58 59 60 61 62 63 64 1002 ); 1003 } 1004 1005 /// Generates [`From`] implementations from a [`Bounded`] into a primitive type that is 1006 /// guaranteed to contain it. 1007 /// 1008 /// Note: The only reason for having this macro is that if we pass `$type` as a generic 1009 /// parameter, we cannot use it in the const context of `AtLeastXBits`'s generic parameter. This 1010 /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a 1011 /// regular `impl` block. 1012 macro_rules! impl_into_primitive { 1013 ($($type:ty)*) => { 1014 $( 1015 #[doc = ::core::concat!( 1016 "Conversion from a [`Bounded`] with no more bits than a [`", 1017 ::core::stringify!($type), 1018 "`] and of same signedness into [`", 1019 ::core::stringify!($type), 1020 "`]")] 1021 impl<T, const N: u32> From<Bounded<T, N>> for $type 1022 where 1023 $type: Integer + TryFrom<T>, 1024 T: Integer<Signedness = <$type as Integer>::Signedness>, 1025 Bounded<T, N>: FitsInXBits<{ <$type as Integer>::BITS as usize }>, 1026 { 1027 fn from(value: Bounded<T, N>) -> $type { 1028 // SAFETY: The trait bound on `Bounded` ensures that any value it holds (which 1029 // is constrained to `N` bits) can fit into the destination type, so this 1030 // conversion cannot fail. 1031 unsafe { <$type>::try_from(value.get()).unwrap_unchecked() } 1032 } 1033 } 1034 )* 1035 } 1036 } 1037 1038 impl_into_primitive!( 1039 u8 u16 u32 u64 usize 1040 i8 i16 i32 i64 isize 1041 ); 1042 1043 // Single-bit `Bounded`s can be converted from/to a boolean. 1044 1045 impl<T> From<Bounded<T, 1>> for bool 1046 where 1047 T: Integer + Zeroable, 1048 { 1049 fn from(value: Bounded<T, 1>) -> Self { 1050 value.get() != Zeroable::zeroed() 1051 } 1052 } 1053 1054 impl<T, const N: u32> From<bool> for Bounded<T, N> 1055 where 1056 T: Integer + From<bool>, 1057 { 1058 fn from(value: bool) -> Self { 1059 // SAFETY: A boolean can be represented using a single bit, and thus fits within any 1060 // integer type for any `N` > 0. 1061 unsafe { Self::__new(T::from(value)) } 1062 } 1063 } 1064