bitops/lib.rs
1//! Miscellaneous bit operations for any [`Integer`].
2//!
3//! See the [`BitOps`] trait for examples.
4//!
5//! [`Integer`]: ../num_integer/trait.Integer.html
6//! [`BitOps`]: ./trait.BitOps.html
7
8extern crate num_integer;
9
10use num_integer::Integer;
11use std::ops::{BitAnd, Shl, Shr};
12
13/// Miscellaneous bit operations for any [`Integer`].
14///
15/// # Examples
16///
17/// ```
18/// use bitops::BitOps;
19///
20/// let x = 0b1010_1011_0000_1100; // 0xab0c
21/// let flag = 0b1000;
22///
23/// assert!(flag.is_flag());
24/// assert!(flag.is_bit_set(3));
25///
26/// assert!(x.is_flag_set(flag));
27/// assert_eq!(x.bits_as_int(8, 4), 0xb);
28/// ```
29///
30/// [`Integer`]: ../num_integer/trait.Integer.html
31pub trait BitOps:
32 Copy + Integer + BitAnd<Output = Self> + Shl<Output = Self> + Shr<Output = Self> + From<u8>
33{
34 /// Returns whether this number only has one bit set.
35 ///
36 /// # Examples
37 ///
38 /// ```
39 /// use bitops::BitOps;
40 ///
41 /// assert!(0b1000.is_flag());
42 /// assert!(!0b1001.is_flag());
43 /// ```
44 #[inline]
45 fn is_flag(&self) -> bool {
46 *self > Self::zero() && (*self & (*self - Self::one())) == Self::zero()
47 }
48
49 /// Returns whether the given bit number is set.
50 ///
51 /// # Panics
52 ///
53 /// Panics if `bit` is greater than the number of bits in this Integer.
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use bitops::BitOps;
59 ///
60 /// assert!(0b1000.is_bit_set(3));
61 /// ```
62 #[inline]
63 fn is_bit_set(&self, bit: u8) -> bool {
64 self.is_flag_set(Self::one() << Self::from(bit))
65 }
66
67 /// Returns whether the given flag is set.
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use bitops::BitOps;
73 ///
74 /// assert!(0b11010.is_flag_set(0b11000));
75 /// ```
76 #[inline]
77 fn is_flag_set(&self, flag: Self) -> bool {
78 *self & flag > Self::zero()
79 }
80
81 /// Returns a number with bit 0 starting at the given bit and up to `count` left most bits.
82 /// This is basically a right shift by `bit` and masked with `(1 << count) - 1`.
83 ///
84 /// # Panics
85 ///
86 /// Panics if `bit` is greater than the number of bits in this Integer.
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// use bitops::BitOps;
92 ///
93 /// assert_eq!(0xab000.bits_as_int(12, 8), 0xab);
94 /// ```
95 #[inline]
96 fn bits_as_int(&self, bit: u8, count: u8) -> Self {
97 (*self >> Self::from(bit)) & ((Self::one() << Self::from(count)) - Self::one())
98 }
99}
100
101/// Implements the [`BitOps`] trait for all types that meet the requirements.
102impl<N> BitOps for N
103where
104 N: Copy + Integer + BitAnd<Output = Self> + Shl<Output = Self> + Shr<Output = Self> + From<u8>,
105{
106}
107
108mod tests {
109 #[allow(unused_imports)]
110 use super::BitOps;
111
112 #[test]
113 fn flag_zero() {
114 assert!(!0.is_flag());
115 }
116
117 #[test]
118 fn flag_set_blank() {
119 assert!(!0x0000.is_flag_set(0));
120 }
121
122 #[test]
123 fn bits_at_zero() {
124 assert_eq!(0xabcd.bits_as_int(0, 8), 0xcd);
125 }
126
127 #[test]
128 #[should_panic]
129 fn bits_overflow() {
130 0u16.bits_as_int(16, 0);
131 }
132}