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