bitutils/
lib.rs

1#![cfg_attr(not(feature="use_std"), no_std)]
2extern crate bf_impl;
3
4/// Sign extend a `size`-bit number (stored in a u32) to an i32.
5/// ```
6/// let i5bit = 0b11110;
7/// let i32bit = bitutils::sign_extend32(i5bit, 5);
8/// assert_eq!(i32bit, -2);
9/// ```
10#[inline]
11pub fn sign_extend32(data: u32, size: u32) -> i32 {
12    assert!(size > 0 && size <= 32);
13    ((data << (32 - size)) as i32) >> (32 - size)
14}
15
16/// Extract a range of bits from a value.
17/// Syntax: `bits!(val, lowbit:hibit);`
18/// ```
19/// #[macro_use]
20/// extern crate bitutils;
21/// 
22/// # fn main() {
23/// let bits = bits!(0b0101000u8, 3:5);
24/// assert_eq!(bits, 0b101);
25/// # }
26/// ```
27#[macro_export]
28macro_rules! bits {
29    ($val:expr, $low:tt : $hi:tt) => {{
30        let max_bit = $crate::size_of_val(&$val) * 8 - 1;
31        $val << (max_bit - $hi) >> (max_bit - $hi + $low)
32    }};
33}
34
35/// Extract a bit from a value.
36/// ```
37/// #[macro_use]
38/// extern crate bitutils;
39/// 
40/// # fn main() {
41/// let bit = bit!(0b01000u8, 3);
42/// assert_eq!(bit, 1);
43/// # }
44/// ```
45#[macro_export]
46macro_rules! bit {
47    ($val:expr, $bit:expr) => { bits!($val, $bit:$bit) };
48}
49
50/******************************************************************
51 * Bitfield operations
52 */
53
54#[cfg(feature="use_std")]
55#[doc(hidden)]
56pub use std::{
57    mem::size_of_val,
58    ops::{Deref, DerefMut},
59};
60#[cfg(not(feature="use_std"))]
61#[doc(hidden)]
62pub use core::{
63    mem::size_of_val,
64    ops::{Deref, DerefMut},
65};
66
67/// Declare a bitfield type.
68/// ```
69/// #[macro_use]
70/// extern crate bitutils;
71/// 
72/// bf!(BitfieldName[u8] {
73///     field1: 0:3, // lower nibble
74///     field2: 4:6,
75///     field3: 7:7
76/// });
77/// 
78/// # fn main() {
79/// let mut bf = BitfieldName::new(0);
80/// bf.set_field3(0xF);
81/// assert_eq!(bf.val, 0x80);
82/// 
83/// bf.val = 0xF0;
84/// assert_eq!(bf.field1(), 0);
85/// assert_eq!(bf.field2(), 7);
86/// assert_eq!(bf.field3(), 1);
87/// # }
88/// ```
89/// 
90/// This declares a module `BitfieldName` with the members:
91/// - `pub struct Bf { pub val: T, pub field1: Field1, pub field2... }`
92/// - `pub fn new(val: T) -> Bf`
93/// - `pub fn alias(val: &'a T) -> &'a Bf`
94/// - `pub fn alias_mut(val: &'a mut T) -> &'a mut Bf`
95/// 
96/// Each field has the impl:
97/// - `pub fn(&self) -> T`
98/// - `pub set_fn(&mut self, val: T)`
99/// - `pub upd_fn(&mut self, func: FnOnce(T) -> T)`
100#[macro_export]
101macro_rules! bf {
102    ($($args:tt)*) => {
103        $crate::bf_inner!($($args)*);
104    };
105}
106
107#[doc(hidden)]
108pub use bf_impl::bf as bf_inner;
109
110#[cfg(test)]
111mod test {
112    use super::*;
113
114    bf!(TestField[u8] {
115        bottom: 0:5,
116        top: 6:7,
117    });
118
119    #[test]
120    fn bitfield() {
121        let field = TestField::new(0b10100000);
122        assert_eq!(field.top(), 0b10);
123    }
124
125    #[test]
126    fn set_bitfield() {
127        let mut bf = TestField::new(0);
128        bf.set_top(0b11);
129        assert_eq!(bf.val, 0b11000000);
130    }
131
132    #[test]
133    fn upd_bitfield() {
134        let mut bf = TestField::new(0);
135        bf.upd_top(|x| x + 1);
136        assert_eq!(bf.val, 0b01000000);
137    }
138
139    #[test]
140    fn bitfield_alias() {
141        let mut val = 0b10100000;
142        {
143            let bf = TestField::alias(&val);
144            assert_eq!(bf.top(), 0b10);
145        }
146        let bf = TestField::alias_mut(&mut val);
147        bf.set_top(0b11);
148        assert_eq!(bf.val, 0b11100000);
149    }
150
151    #[test]
152    fn bitfield_copyable() {
153        fn takes_copy<T: Copy>(_t: T) {
154        }
155
156        takes_copy(TestField::new(0));
157    }
158
159    #[test]
160    fn bitfield_formattable() {
161        let out = format!("{:x?}", TestField::new(!0));
162        assert_eq!(out, "TestField { bottom: 3f, top: 3 }");
163    }
164}