mju_bits/
lib.rs

1/*
2mju-bits - typed bitfield manipulation
3
4Copyright 2019-2020 David Kern <david@mju.io>
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17*/
18
19#![doc(html_root_url = "https://docs.rs/mju-bits/0.3.0")]
20
21//! `#[no_std]` implementation of typed bitfield access for `u8`, `u16`, `u32`, `u64` and `usize`.
22//!
23//!
24//! Usage:
25//!
26//! ```
27//! use typenum::*;
28//! use mju_bits::*;
29//!
30//! struct RegisterMarker;
31//! type Register = Storage<RegisterMarker, u32>;
32//! type RegisterAll = BitField<Register, U0, U31>;
33//! type RegisterFieldA = BitField<Register, U0, U7>;
34//! type RegisterFieldB = BitField<Register, U8, U24>;
35//!
36//! let mut reg = Register::new();
37//! reg.set::<RegisterFieldA>(0x56);
38//! reg.set::<RegisterFieldB>(0x1234);
39//! assert_eq!(reg.get::<RegisterAll>(), 0x00123456);
40//! ```
41//!
42//! The Storage type ensures that a field may only be used with its corresponding storage.
43//!
44//! For example, this won't compile:
45//!
46//! ```compilefail
47//! use mju_bits::*;
48//!
49//! struct FooMarker;
50//! type Foo = Storage<FooMarker, u8>;
51//! type FooField = BitField<Foo, U0, U1>;
52//!
53//! struct BarMarker;
54//! type Bar = Storage<BarMarker, u8>;
55//!
56//! let bar = Bar::new();
57//! bar.get::<FooField>();
58//! ```
59
60#![no_std]
61
62pub mod bitfield;
63pub mod storage;
64
65pub use bitfield::*;
66pub use storage::*;
67
68#[cfg(test)]
69mod test {
70    use super::*;
71    use typenum::{
72        U0, U3, U4, U7, U8, U15, U16, U31, U32, U63,
73    };
74
75    macro_rules! test {
76        ($name:ident, $type:ident, $lo0:ident, $lo1:ident, $hi0:ident, $hi1:ident, $lo:expr, $hi:expr, $all:expr) => {
77            #[test]
78            fn $name() {
79                struct RegisterMarker;
80                type Register = Storage<RegisterMarker, $type>;
81                type RegisterAll = BitField<Register, $lo0, $hi1>;
82                type RegisterFieldLo = BitField<Register, $lo0, $lo1>;
83                type RegisterFieldHi = BitField<Register, $hi0, $hi1>;
84        
85                let mut reg = Register::new();
86                assert_eq!(reg.get::<RegisterFieldLo>(), 0);
87                assert_eq!(reg.get::<RegisterFieldHi>(), 0);
88        
89                reg.set::<RegisterFieldLo>($lo);
90                assert_eq!(reg.get::<RegisterFieldLo>(), $lo);
91                assert_eq!(reg.get::<RegisterFieldHi>(), 0);
92        
93                reg.set::<RegisterFieldHi>($hi);
94                assert_eq!(reg.get::<RegisterFieldLo>(), $lo);
95                assert_eq!(reg.get::<RegisterFieldHi>(), $hi);
96        
97                assert_eq!(reg.get::<RegisterAll>(), $all);
98            }        
99        };
100    }
101
102    test!(
103        test_u8, u8,
104        U0, U3,
105        U4, U7,
106        0b1100, 0b1010,
107        0b10101100
108    );
109
110    test!(
111        test_u16, u16,
112        U0, U7,
113        U8, U15,
114        0b11110000, 0b10101010,
115        0b10101010_11110000
116    );
117
118    test!(
119        test_u32, u32,
120        U0, U15,
121        U16, U31,
122        0b11111111_00000000, 0b10101010_10101010,
123        0b10101010_10101010_11111111_00000000
124    );
125
126    #[cfg(target_pointer_width="64")]
127    test!(
128        test_u64, u64,
129        U0, U31,
130        U32, U63,
131        0b11111111_11111111_00000000_00000000, 0b10101010_10101010_10101010_10101010,
132        0b10101010_10101010_10101010_10101010_11111111_11111111_00000000_00000000
133    );
134}