master
rs 118 lines 3.04 KB
Raw
1 // Copyright (C) 2024 Intel Corporation.
2 // Author(s): Zhao Liu <zhao1.liu@intel.com>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4
5 //! This module provides bit operation extensions to integer types.
6
7 use std::ops::{
8 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
9 Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign,
10 };
11
12 /// Trait for extensions to integer types
13 pub trait IntegerExt:
14 Add<Self, Output = Self> + AddAssign<Self> +
15 BitAnd<Self, Output = Self> + BitAndAssign<Self> +
16 BitOr<Self, Output = Self> + BitOrAssign<Self> +
17 BitXor<Self, Output = Self> + BitXorAssign<Self> +
18 Copy +
19 Div<Self, Output = Self> + DivAssign<Self> +
20 Eq +
21 Mul<Self, Output = Self> + MulAssign<Self> +
22 Not<Output = Self> + Ord + PartialOrd +
23 Rem<Self, Output = Self> + RemAssign<Self> +
24 Shl<Self, Output = Self> + ShlAssign<Self> +
25 Shl<u32, Output = Self> + ShlAssign<u32> + // add more as needed
26 Shr<Self, Output = Self> + ShrAssign<Self> +
27 Shr<u32, Output = Self> + ShrAssign<u32> // add more as needed
28 {
29 const BITS: u32;
30 const MAX: Self;
31 const MIN: Self;
32 const ONE: Self;
33 const ZERO: Self;
34
35 #[inline]
36 #[must_use]
37 fn bit(start: u32) -> Self
38 {
39 debug_assert!(start < Self::BITS);
40
41 Self::ONE << start
42 }
43
44 #[inline]
45 #[must_use]
46 fn mask(start: u32, length: u32) -> Self
47 {
48 /* FIXME: Implement a more elegant check with error handling support? */
49 debug_assert!(start < Self::BITS && length > 0 && length <= Self::BITS - start);
50
51 (Self::MAX >> (Self::BITS - length)) << start
52 }
53
54 #[inline]
55 #[must_use]
56 fn deposit<U: IntegerExt>(self, start: u32, length: u32,
57 fieldval: U) -> Self
58 where Self: From<U>
59 {
60 debug_assert!(length <= U::BITS);
61
62 let mask = Self::mask(start, length);
63 (self & !mask) | ((Self::from(fieldval) << start) & mask)
64 }
65
66 #[inline]
67 #[must_use]
68 fn extract(self, start: u32, length: u32) -> Self
69 {
70 let mask = Self::mask(start, length);
71 (self & mask) >> start
72 }
73 }
74
75 macro_rules! impl_num_ext {
76 ($type:ty) => {
77 impl IntegerExt for $type {
78 const BITS: u32 = <$type>::BITS;
79 const MAX: Self = <$type>::MAX;
80 const MIN: Self = <$type>::MIN;
81 const ONE: Self = 1;
82 const ZERO: Self = 0;
83 }
84 };
85 }
86
87 impl_num_ext!(u8);
88 impl_num_ext!(u16);
89 impl_num_ext!(u32);
90 impl_num_ext!(u64);
91
92 #[cfg(test)]
93 mod tests {
94 use super::*;
95
96 #[test]
97 fn test_deposit() {
98 assert_eq!(15u32.deposit(8, 8, 1u32), 256 + 15);
99 assert_eq!(15u32.deposit(8, 1, 255u8), 256 + 15);
100 }
101
102 #[test]
103 fn test_extract() {
104 assert_eq!(15u32.extract(2, 4), 3);
105 }
106
107 #[test]
108 fn test_bit() {
109 assert_eq!(u8::bit(7), 128);
110 assert_eq!(u32::bit(16), 0x10000);
111 }
112
113 #[test]
114 fn test_mask() {
115 assert_eq!(u8::mask(7, 1), 128);
116 assert_eq!(u32::mask(8, 8), 0xff00);
117 }
118 }