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 /// # Safety 286 /// 287 /// The caller must ensure that `value` can be represented within `N` bits. 288 const unsafe fn __new(value: T) -> Self { 289 // Enforce the type invariants. 290 const { 291 // `N` cannot be zero. 292 assert!(N != 0); 293 // The backing type is at least as large as `N` bits. 294 assert!(N <= T::BITS); 295 } 296 297 // INVARIANT: The caller ensures `value` fits within `N` bits. 298 Self(value) 299 } 300 301 /// Attempts to turn `value` into a `Bounded` using `N` bits. 302 /// 303 /// Returns [`None`] if `value` doesn't fit within `N` bits. 304 /// 305 /// # Examples 306 /// 307 /// ``` 308 /// use kernel::num::Bounded; 309 /// 310 /// let v = Bounded::<u8, 1>::try_new(1); 311 /// assert_eq!(v.as_deref().copied(), Some(1)); 312 /// 313 /// let v = Bounded::<i8, 4>::try_new(-2); 314 /// assert_eq!(v.as_deref().copied(), Some(-2)); 315 /// 316 /// // `0x1ff` doesn't fit into 8 unsigned bits. 317 /// let v = Bounded::<u32, 8>::try_new(0x1ff); 318 /// assert_eq!(v, None); 319 /// 320 /// // The range of values representable with 4 bits is `[-8..=7]`. The following tests these 321 /// // limits. 322 /// let v = Bounded::<i8, 4>::try_new(-8); 323 /// assert_eq!(v.map(Bounded::get), Some(-8)); 324 /// let v = Bounded::<i8, 4>::try_new(-9); 325 /// assert_eq!(v, None); 326 /// let v = Bounded::<i8, 4>::try_new(7); 327 /// assert_eq!(v.map(Bounded::get), Some(7)); 328 /// let v = Bounded::<i8, 4>::try_new(8); 329 /// assert_eq!(v, None); 330 /// ``` 331 pub fn try_new(value: T) -> Option<Self> { 332 fits_within(value, N).then(|| { 333 // SAFETY: `fits_within` confirmed that `value` can be represented within `N` bits. 334 unsafe { Self::__new(value) } 335 }) 336 } 337 338 /// Checks that `expr` is valid for this type at compile-time and build a new value. 339 /// 340 /// This relies on [`build_assert!`] and guaranteed optimization to perform validation at 341 /// compile-time. If `expr` cannot be proved to be within the requested bounds at compile-time, 342 /// use the fallible [`Self::try_new`] instead. 343 /// 344 /// Limit this to simple, easily provable expressions, and prefer one of the [`Self::new`] 345 /// constructors whenever possible as they statically validate the value instead of relying on 346 /// compiler optimizations. 347 /// 348 /// # Examples 349 /// 350 /// ``` 351 /// use kernel::num::Bounded; 352 /// # fn some_number() -> u32 { 0xffffffff } 353 /// 354 /// // Some undefined number. 355 /// let v: u32 = some_number(); 356 /// 357 /// // Triggers a build error as `v` cannot be asserted to fit within 4 bits... 358 /// // let _ = Bounded::<u32, 4>::from_expr(v); 359 /// 360 /// // ... but this works as the compiler can assert the range from the mask. 361 /// let _ = Bounded::<u32, 4>::from_expr(v & 0xf); 362 /// 363 /// // These expressions are simple enough to be proven correct, but since they are static the 364 /// // `new` constructor should be preferred. 365 /// assert_eq!(Bounded::<u8, 1>::from_expr(1).get(), 1); 366 /// assert_eq!(Bounded::<u16, 8>::from_expr(0xff).get(), 0xff); 367 /// ``` 368 // Always inline to optimize out error path of `build_assert`. 369 #[inline(always)] 370 pub fn from_expr(expr: T) -> Self { 371 crate::build_assert!( 372 fits_within(expr, N), 373 "Requested value larger than maximal representable value." 374 ); 375 376 // SAFETY: `fits_within` confirmed that `expr` can be represented within `N` bits. 377 unsafe { Self::__new(expr) } 378 } 379 380 /// Returns the wrapped value as the backing type. 381 /// 382 /// # Examples 383 /// 384 /// ``` 385 /// use kernel::num::Bounded; 386 /// 387 /// let v = Bounded::<u32, 4>::new::<7>(); 388 /// assert_eq!(v.get(), 7u32); 389 /// ``` 390 pub fn get(self) -> T { 391 *self.deref() 392 } 393 394 /// Increases the number of bits usable for `self`. 395 /// 396 /// This operation cannot fail. 397 /// 398 /// # Examples 399 /// 400 /// ``` 401 /// use kernel::num::Bounded; 402 /// 403 /// let v = Bounded::<u32, 4>::new::<7>(); 404 /// let larger_v = v.extend::<12>(); 405 /// // The contained values are equal even though `larger_v` has a bigger capacity. 406 /// assert_eq!(larger_v, v); 407 /// ``` 408 pub const fn extend<const M: u32>(self) -> Bounded<T, M> { 409 const { 410 assert!( 411 M >= N, 412 "Requested number of bits is less than the current representation." 413 ); 414 } 415 416 // SAFETY: The value did fit within `N` bits, so it will all the more fit within 417 // the larger `M` bits. 418 unsafe { Bounded::__new(self.0) } 419 } 420 421 /// Attempts to shrink the number of bits usable for `self`. 422 /// 423 /// Returns [`None`] if the value of `self` cannot be represented within `M` bits. 424 /// 425 /// # Examples 426 /// 427 /// ``` 428 /// use kernel::num::Bounded; 429 /// 430 /// let v = Bounded::<u32, 12>::new::<7>(); 431 /// 432 /// // `7` can be represented using 3 unsigned bits... 433 /// let smaller_v = v.try_shrink::<3>(); 434 /// assert_eq!(smaller_v.as_deref().copied(), Some(7)); 435 /// 436 /// // ... but doesn't fit within `2` bits. 437 /// assert_eq!(v.try_shrink::<2>(), None); 438 /// ``` 439 pub fn try_shrink<const M: u32>(self) -> Option<Bounded<T, M>> { 440 Bounded::<T, M>::try_new(self.get()) 441 } 442 443 /// Casts `self` into a [`Bounded`] backed by a different storage type, but using the same 444 /// number of valid bits. 445 /// 446 /// Both `T` and `U` must be of same signedness, and `U` must be at least as large as 447 /// `N` bits, or a build error will occur. 448 /// 449 /// # Examples 450 /// 451 /// ``` 452 /// use kernel::num::Bounded; 453 /// 454 /// let v = Bounded::<u32, 12>::new::<127>(); 455 /// 456 /// let u16_v: Bounded<u16, 12> = v.cast(); 457 /// assert_eq!(u16_v.get(), 127); 458 /// 459 /// // This won't build: a `u8` is smaller than the required 12 bits. 460 /// // let _: Bounded<u8, 12> = v.cast(); 461 /// ``` 462 pub fn cast<U>(self) -> Bounded<U, N> 463 where 464 U: TryFrom<T> + Integer, 465 T: Integer, 466 U: Integer<Signedness = T::Signedness>, 467 { 468 // SAFETY: The converted value is represented using `N` bits, `U` can contain `N` bits, and 469 // `U` and `T` have the same sign, hence this conversion cannot fail. 470 let value = unsafe { U::try_from(self.get()).unwrap_unchecked() }; 471 472 // SAFETY: Although the backing type has changed, the value is still represented within 473 // `N` bits, and with the same signedness. 474 unsafe { Bounded::__new(value) } 475 } 476 } 477 478 impl<T, const N: u32> Deref for Bounded<T, N> 479 where 480 T: Integer, 481 { 482 type Target = T; 483 484 fn deref(&self) -> &Self::Target { 485 // Enforce the invariant to inform the compiler of the bounds of the value. 486 if !fits_within(self.0, N) { 487 // SAFETY: Per the `Bounded` invariants, `fits_within` can never return `false` on the 488 // value of a valid instance. 489 unsafe { core::hint::unreachable_unchecked() } 490 } 491 492 &self.0 493 } 494 } 495 496 /// Trait similar to [`TryInto`] but for [`Bounded`], to avoid conflicting implementations. 497 /// 498 /// # Examples 499 /// 500 /// ``` 501 /// use kernel::num::{Bounded, TryIntoBounded}; 502 /// 503 /// // Succeeds because `128` fits into 8 bits. 504 /// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded(); 505 /// assert_eq!(v.as_deref().copied(), Some(128)); 506 /// 507 /// // Fails because `128` doesn't fit into 6 bits. 508 /// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded(); 509 /// assert_eq!(v, None); 510 /// ``` 511 pub trait TryIntoBounded<T: Integer, const N: u32> { 512 /// Attempts to convert `self` into a [`Bounded`] using `N` bits. 513 /// 514 /// Returns [`None`] if `self` does not fit into the target type. 515 fn try_into_bounded(self) -> Option<Bounded<T, N>>; 516 } 517 518 /// Any integer value can be attempted to be converted into a [`Bounded`] of any size. 519 impl<T, U, const N: u32> TryIntoBounded<T, N> for U 520 where 521 T: Integer, 522 U: TryInto<T>, 523 { 524 fn try_into_bounded(self) -> Option<Bounded<T, N>> { 525 self.try_into().ok().and_then(Bounded::try_new) 526 } 527 } 528 529 // Comparisons between `Bounded`s. 530 531 impl<T, U, const N: u32, const M: u32> PartialEq<Bounded<U, M>> for Bounded<T, N> 532 where 533 T: Integer, 534 U: Integer, 535 T: PartialEq<U>, 536 { 537 fn eq(&self, other: &Bounded<U, M>) -> bool { 538 self.get() == other.get() 539 } 540 } 541 542 impl<T, const N: u32> Eq for Bounded<T, N> where T: Integer {} 543 544 impl<T, U, const N: u32, const M: u32> PartialOrd<Bounded<U, M>> for Bounded<T, N> 545 where 546 T: Integer, 547 U: Integer, 548 T: PartialOrd<U>, 549 { 550 fn partial_cmp(&self, other: &Bounded<U, M>) -> Option<cmp::Ordering> { 551 self.get().partial_cmp(&other.get()) 552 } 553 } 554 555 impl<T, const N: u32> Ord for Bounded<T, N> 556 where 557 T: Integer, 558 T: Ord, 559 { 560 fn cmp(&self, other: &Self) -> cmp::Ordering { 561 self.get().cmp(&other.get()) 562 } 563 } 564 565 // Comparisons between a `Bounded` and its backing type. 566 567 impl<T, const N: u32> PartialEq<T> for Bounded<T, N> 568 where 569 T: Integer, 570 T: PartialEq, 571 { 572 fn eq(&self, other: &T) -> bool { 573 self.get() == *other 574 } 575 } 576 577 impl<T, const N: u32> PartialOrd<T> for Bounded<T, N> 578 where 579 T: Integer, 580 T: PartialOrd, 581 { 582 fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> { 583 self.get().partial_cmp(other) 584 } 585 } 586 587 // Implementations of `core::ops` for two `Bounded` with the same backing type. 588 589 impl<T, const N: u32, const M: u32> ops::Add<Bounded<T, M>> for Bounded<T, N> 590 where 591 T: Integer, 592 T: ops::Add<Output = T>, 593 { 594 type Output = T; 595 596 fn add(self, rhs: Bounded<T, M>) -> Self::Output { 597 self.get() + rhs.get() 598 } 599 } 600 601 impl<T, const N: u32, const M: u32> ops::BitAnd<Bounded<T, M>> for Bounded<T, N> 602 where 603 T: Integer, 604 T: ops::BitAnd<Output = T>, 605 { 606 type Output = T; 607 608 fn bitand(self, rhs: Bounded<T, M>) -> Self::Output { 609 self.get() & rhs.get() 610 } 611 } 612 613 impl<T, const N: u32, const M: u32> ops::BitOr<Bounded<T, M>> for Bounded<T, N> 614 where 615 T: Integer, 616 T: ops::BitOr<Output = T>, 617 { 618 type Output = T; 619 620 fn bitor(self, rhs: Bounded<T, M>) -> Self::Output { 621 self.get() | rhs.get() 622 } 623 } 624 625 impl<T, const N: u32, const M: u32> ops::BitXor<Bounded<T, M>> for Bounded<T, N> 626 where 627 T: Integer, 628 T: ops::BitXor<Output = T>, 629 { 630 type Output = T; 631 632 fn bitxor(self, rhs: Bounded<T, M>) -> Self::Output { 633 self.get() ^ rhs.get() 634 } 635 } 636 637 impl<T, const N: u32, const M: u32> ops::Div<Bounded<T, M>> for Bounded<T, N> 638 where 639 T: Integer, 640 T: ops::Div<Output = T>, 641 { 642 type Output = T; 643 644 fn div(self, rhs: Bounded<T, M>) -> Self::Output { 645 self.get() / rhs.get() 646 } 647 } 648 649 impl<T, const N: u32, const M: u32> ops::Mul<Bounded<T, M>> for Bounded<T, N> 650 where 651 T: Integer, 652 T: ops::Mul<Output = T>, 653 { 654 type Output = T; 655 656 fn mul(self, rhs: Bounded<T, M>) -> Self::Output { 657 self.get() * rhs.get() 658 } 659 } 660 661 impl<T, const N: u32, const M: u32> ops::Rem<Bounded<T, M>> for Bounded<T, N> 662 where 663 T: Integer, 664 T: ops::Rem<Output = T>, 665 { 666 type Output = T; 667 668 fn rem(self, rhs: Bounded<T, M>) -> Self::Output { 669 self.get() % rhs.get() 670 } 671 } 672 673 impl<T, const N: u32, const M: u32> ops::Sub<Bounded<T, M>> for Bounded<T, N> 674 where 675 T: Integer, 676 T: ops::Sub<Output = T>, 677 { 678 type Output = T; 679 680 fn sub(self, rhs: Bounded<T, M>) -> Self::Output { 681 self.get() - rhs.get() 682 } 683 } 684 685 // Implementations of `core::ops` between a `Bounded` and its backing type. 686 687 impl<T, const N: u32> ops::Add<T> for Bounded<T, N> 688 where 689 T: Integer, 690 T: ops::Add<Output = T>, 691 { 692 type Output = T; 693 694 fn add(self, rhs: T) -> Self::Output { 695 self.get() + rhs 696 } 697 } 698 699 impl<T, const N: u32> ops::BitAnd<T> for Bounded<T, N> 700 where 701 T: Integer, 702 T: ops::BitAnd<Output = T>, 703 { 704 type Output = T; 705 706 fn bitand(self, rhs: T) -> Self::Output { 707 self.get() & rhs 708 } 709 } 710 711 impl<T, const N: u32> ops::BitOr<T> for Bounded<T, N> 712 where 713 T: Integer, 714 T: ops::BitOr<Output = T>, 715 { 716 type Output = T; 717 718 fn bitor(self, rhs: T) -> Self::Output { 719 self.get() | rhs 720 } 721 } 722 723 impl<T, const N: u32> ops::BitXor<T> for Bounded<T, N> 724 where 725 T: Integer, 726 T: ops::BitXor<Output = T>, 727 { 728 type Output = T; 729 730 fn bitxor(self, rhs: T) -> Self::Output { 731 self.get() ^ rhs 732 } 733 } 734 735 impl<T, const N: u32> ops::Div<T> for Bounded<T, N> 736 where 737 T: Integer, 738 T: ops::Div<Output = T>, 739 { 740 type Output = T; 741 742 fn div(self, rhs: T) -> Self::Output { 743 self.get() / rhs 744 } 745 } 746 747 impl<T, const N: u32> ops::Mul<T> for Bounded<T, N> 748 where 749 T: Integer, 750 T: ops::Mul<Output = T>, 751 { 752 type Output = T; 753 754 fn mul(self, rhs: T) -> Self::Output { 755 self.get() * rhs 756 } 757 } 758 759 impl<T, const N: u32> ops::Neg for Bounded<T, N> 760 where 761 T: Integer, 762 T: ops::Neg<Output = T>, 763 { 764 type Output = T; 765 766 fn neg(self) -> Self::Output { 767 -self.get() 768 } 769 } 770 771 impl<T, const N: u32> ops::Not for Bounded<T, N> 772 where 773 T: Integer, 774 T: ops::Not<Output = T>, 775 { 776 type Output = T; 777 778 fn not(self) -> Self::Output { 779 !self.get() 780 } 781 } 782 783 impl<T, const N: u32> ops::Rem<T> for Bounded<T, N> 784 where 785 T: Integer, 786 T: ops::Rem<Output = T>, 787 { 788 type Output = T; 789 790 fn rem(self, rhs: T) -> Self::Output { 791 self.get() % rhs 792 } 793 } 794 795 impl<T, const N: u32> ops::Sub<T> for Bounded<T, N> 796 where 797 T: Integer, 798 T: ops::Sub<Output = T>, 799 { 800 type Output = T; 801 802 fn sub(self, rhs: T) -> Self::Output { 803 self.get() - rhs 804 } 805 } 806 807 // Proxy implementations of `core::fmt`. 808 809 impl<T, const N: u32> fmt::Display for Bounded<T, N> 810 where 811 T: Integer, 812 T: fmt::Display, 813 { 814 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 815 self.get().fmt(f) 816 } 817 } 818 819 impl<T, const N: u32> fmt::Binary for Bounded<T, N> 820 where 821 T: Integer, 822 T: fmt::Binary, 823 { 824 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 825 self.get().fmt(f) 826 } 827 } 828 829 impl<T, const N: u32> fmt::LowerExp for Bounded<T, N> 830 where 831 T: Integer, 832 T: fmt::LowerExp, 833 { 834 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 835 self.get().fmt(f) 836 } 837 } 838 839 impl<T, const N: u32> fmt::LowerHex for Bounded<T, N> 840 where 841 T: Integer, 842 T: fmt::LowerHex, 843 { 844 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 845 self.get().fmt(f) 846 } 847 } 848 849 impl<T, const N: u32> fmt::Octal for Bounded<T, N> 850 where 851 T: Integer, 852 T: fmt::Octal, 853 { 854 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 855 self.get().fmt(f) 856 } 857 } 858 859 impl<T, const N: u32> fmt::UpperExp for Bounded<T, N> 860 where 861 T: Integer, 862 T: fmt::UpperExp, 863 { 864 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 865 self.get().fmt(f) 866 } 867 } 868 869 impl<T, const N: u32> fmt::UpperHex for Bounded<T, N> 870 where 871 T: Integer, 872 T: fmt::UpperHex, 873 { 874 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 875 self.get().fmt(f) 876 } 877 } 878 879 /// Implements `$trait` for all [`Bounded`] types represented using `$num_bits`. 880 /// 881 /// This is used to declare size properties as traits that we can constrain against in impl blocks. 882 macro_rules! impl_size_rule { 883 ($trait:ty, $($num_bits:literal)*) => { 884 $( 885 impl<T> $trait for Bounded<T, $num_bits> where T: Integer {} 886 )* 887 }; 888 } 889 890 /// Local trait expressing the fact that a given [`Bounded`] has at least `N` bits used for value 891 /// representation. 892 trait AtLeastXBits<const N: usize> {} 893 894 /// Implementations for infallibly converting a primitive type into a [`Bounded`] that can contain 895 /// it. 896 /// 897 /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent 898 /// module. 899 mod atleast_impls { 900 use super::*; 901 902 // Number of bits at least as large as 64. 903 impl_size_rule!(AtLeastXBits<64>, 64); 904 905 // Anything 64 bits or more is also larger than 32. 906 impl<T> AtLeastXBits<32> for T where T: AtLeastXBits<64> {} 907 // Other numbers of bits at least as large as 32. 908 impl_size_rule!(AtLeastXBits<32>, 909 32 33 34 35 36 37 38 39 910 40 41 42 43 44 45 46 47 911 48 49 50 51 52 53 54 55 912 56 57 58 59 60 61 62 63 913 ); 914 915 // Anything 32 bits or more is also larger than 16. 916 impl<T> AtLeastXBits<16> for T where T: AtLeastXBits<32> {} 917 // Other numbers of bits at least as large as 16. 918 impl_size_rule!(AtLeastXBits<16>, 919 16 17 18 19 20 21 22 23 920 24 25 26 27 28 29 30 31 921 ); 922 923 // Anything 16 bits or more is also larger than 8. 924 impl<T> AtLeastXBits<8> for T where T: AtLeastXBits<16> {} 925 // Other numbers of bits at least as large as 8. 926 impl_size_rule!(AtLeastXBits<8>, 8 9 10 11 12 13 14 15); 927 } 928 929 /// Generates `From` implementations from a primitive type into a [`Bounded`] with 930 /// enough bits to store any value of that type. 931 /// 932 /// Note: The only reason for having this macro is that if we pass `$type` as a generic 933 /// parameter, we cannot use it in the const context of [`AtLeastXBits`]'s generic parameter. This 934 /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a 935 /// regular `impl` block. 936 macro_rules! impl_from_primitive { 937 ($($type:ty)*) => { 938 $( 939 #[doc = ::core::concat!( 940 "Conversion from a [`", 941 ::core::stringify!($type), 942 "`] into a [`Bounded`] of same signedness with enough bits to store it.")] 943 impl<T, const N: u32> From<$type> for Bounded<T, N> 944 where 945 $type: Integer, 946 T: Integer<Signedness = <$type as Integer>::Signedness> + From<$type>, 947 Self: AtLeastXBits<{ <$type as Integer>::BITS as usize }>, 948 { 949 fn from(value: $type) -> Self { 950 // SAFETY: The trait bound on `Self` guarantees that `N` bits is 951 // enough to hold any value of the source type. 952 unsafe { Self::__new(T::from(value)) } 953 } 954 } 955 )* 956 } 957 } 958 959 impl_from_primitive!( 960 u8 u16 u32 u64 usize 961 i8 i16 i32 i64 isize 962 ); 963 964 /// Local trait expressing the fact that a given [`Bounded`] fits into a primitive type of `N` bits, 965 /// provided they have the same signedness. 966 trait FitsInXBits<const N: usize> {} 967 968 /// Implementations for infallibly converting a [`Bounded`] into a primitive type that can contain 969 /// it. 970 /// 971 /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent 972 /// module. 973 mod fits_impls { 974 use super::*; 975 976 // Number of bits that fit into a 8-bits primitive. 977 impl_size_rule!(FitsInXBits<8>, 1 2 3 4 5 6 7 8); 978 979 // Anything that fits into 8 bits also fits into 16. 980 impl<T> FitsInXBits<16> for T where T: FitsInXBits<8> {} 981 // Other number of bits that fit into a 16-bits primitive. 982 impl_size_rule!(FitsInXBits<16>, 9 10 11 12 13 14 15 16); 983 984 // Anything that fits into 16 bits also fits into 32. 985 impl<T> FitsInXBits<32> for T where T: FitsInXBits<16> {} 986 // Other number of bits that fit into a 32-bits primitive. 987 impl_size_rule!(FitsInXBits<32>, 988 17 18 19 20 21 22 23 24 989 25 26 27 28 29 30 31 32 990 ); 991 992 // Anything that fits into 32 bits also fits into 64. 993 impl<T> FitsInXBits<64> for T where T: FitsInXBits<32> {} 994 // Other number of bits that fit into a 64-bits primitive. 995 impl_size_rule!(FitsInXBits<64>, 996 33 34 35 36 37 38 39 40 997 41 42 43 44 45 46 47 48 998 49 50 51 52 53 54 55 56 999 57 58 59 60 61 62 63 64 1000 ); 1001 } 1002 1003 /// Generates [`From`] implementations from a [`Bounded`] into a primitive type that is 1004 /// guaranteed to contain it. 1005 /// 1006 /// Note: The only reason for having this macro is that if we pass `$type` as a generic 1007 /// parameter, we cannot use it in the const context of `AtLeastXBits`'s generic parameter. This 1008 /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a 1009 /// regular `impl` block. 1010 macro_rules! impl_into_primitive { 1011 ($($type:ty)*) => { 1012 $( 1013 #[doc = ::core::concat!( 1014 "Conversion from a [`Bounded`] with no more bits than a [`", 1015 ::core::stringify!($type), 1016 "`] and of same signedness into [`", 1017 ::core::stringify!($type), 1018 "`]")] 1019 impl<T, const N: u32> From<Bounded<T, N>> for $type 1020 where 1021 $type: Integer + TryFrom<T>, 1022 T: Integer<Signedness = <$type as Integer>::Signedness>, 1023 Bounded<T, N>: FitsInXBits<{ <$type as Integer>::BITS as usize }>, 1024 { 1025 fn from(value: Bounded<T, N>) -> $type { 1026 // SAFETY: The trait bound on `Bounded` ensures that any value it holds (which 1027 // is constrained to `N` bits) can fit into the destination type, so this 1028 // conversion cannot fail. 1029 unsafe { <$type>::try_from(value.get()).unwrap_unchecked() } 1030 } 1031 } 1032 )* 1033 } 1034 } 1035 1036 impl_into_primitive!( 1037 u8 u16 u32 u64 usize 1038 i8 i16 i32 i64 isize 1039 ); 1040 1041 // Single-bit `Bounded`s can be converted from/to a boolean. 1042 1043 impl<T> From<Bounded<T, 1>> for bool 1044 where 1045 T: Integer + Zeroable, 1046 { 1047 fn from(value: Bounded<T, 1>) -> Self { 1048 value.get() != Zeroable::zeroed() 1049 } 1050 } 1051 1052 impl<T, const N: u32> From<bool> for Bounded<T, N> 1053 where 1054 T: Integer + From<bool>, 1055 { 1056 fn from(value: bool) -> Self { 1057 // SAFETY: A boolean can be represented using a single bit, and thus fits within any 1058 // integer type for any `N` > 0. 1059 unsafe { Self::__new(T::from(value)) } 1060 } 1061 } 1062