mju_bits/
bitfield.rs

1/*
2bitfield.rs - Type defining a range of bits for an owning type
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//! Type definition of an owned bitfield with compile-time calculation of mask and shift
20
21use core::marker::PhantomData;
22
23use typenum;
24use typenum::{
25    Shleft,
26    Sub1,
27    Minimum,
28    Or,
29    Unsigned,
30    U1,
31    Xor,
32};
33
34/// Marker type representing an owned bitfield.  `TOwner` is the owning type of the
35/// bitfield.  `Shift` and `Mask` are `typenum::Unsigned` types representing the shift and mask
36/// values used to access the bitfield.  These are both converted to constants in the `BitFieldTrait`
37/// implemented for this struct.
38///
39/// While this type can be used directly, it is more convenient to use the `BitField` type
40/// alias to define a bit range rather than the lower-level shift and mask.
41pub struct BitFieldImpl<TOwner, Shift, Mask> {
42    owner: PhantomData<TOwner>,
43    shift: PhantomData<Shift>,
44    mask: PhantomData<Mask>,
45}
46
47/// Tracks the `Owner`, shift and mask used by the `Storage::*` methods to provide access
48/// to an owned bit field.
49///
50/// Note: this trait is sealed against implementation outside this crate. This
51/// restriction will be lifted once the API has stabilized.
52pub trait BitFieldTrait : private::Sealed {
53    /// The owner, typically a `Storage`, bound to this bit field
54    type Owner;
55
56    /// The number of bits the field is shifted in the owner
57    const SHIFT: u32;
58
59    /// The bit mask used to to select or clear the field bits in the owner
60    const MASK: u64;
61}
62
63// Seal the BitFieldTrait trait
64mod private {
65    pub trait Sealed { }
66
67    impl<TOwner, Shift, Mask> Sealed for super::BitFieldImpl<TOwner, Shift, Mask> { }
68}
69
70/// Implementation for `BitFieldImpl` explicitly converts the typenum shift and mask calculations
71/// into constants. Forcing the conversion here prevents infinite recursion by the compiler when
72/// these values are used by `Storage` to provide access to the field.
73impl<TOwner, TShift, TMask> BitFieldTrait for BitFieldImpl<TOwner, TShift, TMask>
74where
75    TShift: Unsigned,
76    TMask: Unsigned
77{
78    type Owner = TOwner;
79    const SHIFT: u32 = TShift::U32;
80    const MASK: u64 = TMask::U64;
81}
82
83type BitMask<X> = Shleft<U1, X>;
84type RightMask<X> = Sub1<BitMask<X>>;
85
86/// Define a BitField bound to `TOWner` (typically a `Storage`).  The bit range of
87/// the field includes bits from `X` to `Y` inclusively.  The ordering of bit positions
88/// does not matter: `BitField<Owner, B0, B7>` defines the same field as `BitField<Owner, B7, B0>`
89/// although technically the two are distinct types.
90pub type BitField<TOwner, X, Y> = BitFieldImpl<
91    TOwner,
92
93    // Shift
94    Minimum<X, Y>,
95
96    // Mask
97    Or<
98        Or<
99            Xor<
100                RightMask<X>,
101                RightMask<Y>
102            >,
103            BitMask<X>
104        >,
105        BitMask<Y>
106    >
107>;