Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sawp-flags-0.13.1/src/lib.rs
Line
Count
Source
1
//! Bitflags handling and storage.
2
//!
3
//! This crate allows you to define flag values using an enum and derive
4
//! `BitFlags` to add convenience methods.
5
//!
6
//! This implementation was heavily inspired by
7
//! [enumflags2](https://crates.io/crates/enumflags2) and
8
//! [bitflags](https://crates.io/crates/bitflags) and customized for use in a
9
//! sawp parser. Consider using those two open source projects before resorting
10
//! to this one. One key feature is that we are automatically generating ffi
11
//! accessors using the [sawp-ffi](https://crates.io/crates/sawp-ffi) crate.
12
//!
13
//! This crate works as follows:
14
//! - `enum YourEnum` with a numeric representation (e.g. `#[repr(u8)]`) is used
15
//!   to define bit fields.
16
//! - deriving `BitFlags` on this enum will add convenience methods for bitwise
17
//!   operations and implement the `Flag` trait.
18
//! - Flag values are transparently stored as `Flags<YourEnum>` so you can perform
19
//!   more operations on this type.
20
//!
21
//! # Example
22
//! See `example` module for a generated example as well.
23
//! ```
24
//! use sawp_flags::{BitFlags, Flags, Flag};
25
//!
26
//! /// Example enum
27
//! #[derive(Debug, Clone, Copy, PartialEq, BitFlags)]
28
//! #[repr(u8)]
29
//! pub enum Test {
30
//!     A = 0b0001,
31
//!     B = 0b0010,
32
//!     C = 0b0100,
33
//!     D = 0b1000,
34
//!     /// Variants can be a bitmask of the other fields like so
35
//!     E = Test::A as u8 | Test::B as u8 | Test::C as u8 | Test::D as u8,
36
//! }
37
//!
38
//! // `flags` will be of transparent type `Flags<Test>`
39
//! let flags : Flags<Test> = Test::A | Test::C;
40
//!
41
//! // convert a number to flags using `from_bits()`
42
//! assert_eq!(flags, Flags::<Test>::from_bits(0b101));
43
//!
44
//! // convert flags to a number using `bits()`
45
//! assert_eq!(0b101, flags.bits());
46
//!
47
//! // perform bitwise operations
48
//! assert_eq!(Test::A | Test::B | Test::C, flags | Test::B);
49
//! assert_eq!(Test::A, flags & Test::A);
50
//! assert_eq!(Test::C, flags ^ Test::A);
51
//!
52
//! // check which flags are set
53
//! assert!(flags.contains(Test::A));
54
//! assert!(!flags.contains(Test::A | Test::B));
55
//! assert!(flags.intersects(Test::A));
56
//! assert!(flags.intersects(Test::A | Test::B));
57
//! ```
58
59
use std::ops::*;
60
61
/// The `BitFlags` derive macro will implement the `Flags` Trait on your enum and
62
/// provide convenience methods for bit operations and type conversions.
63
///
64
// Re-export derive macro for convenience.
65
pub use sawp_flags_derive::BitFlags;
66
67
/// A primitive numeric type to be used for flag storage.
68
pub trait Primitive:
69
    Default
70
    + BitOr<Self, Output = Self>
71
    + BitAnd<Self, Output = Self>
72
    + BitXor<Self, Output = Self>
73
    + Not<Output = Self>
74
    + PartialOrd<Self>
75
    + std::fmt::Debug
76
    + std::fmt::Binary
77
    + Copy
78
    + Clone
79
{
80
}
81
82
impl Primitive for u8 {}
83
impl Primitive for u16 {}
84
impl Primitive for u32 {}
85
impl Primitive for u64 {}
86
impl Primitive for u128 {}
87
88
/// A trait implemented by all flag enums.
89
pub trait Flag: Copy + Clone + std::fmt::Debug + std::fmt::Display + 'static {
90
    /// Associated primitive numeric type
91
    type Primitive: Primitive;
92
93
    /// A list of all flag variants in the enum
94
    const ITEMS: &'static [Self];
95
96
    /// Numeric representation of the variant
97
    fn bits(self) -> Self::Primitive;
98
99
    /// Flag value when no variants are set
100
    fn none() -> Flags<Self>;
101
102
    /// Flag value when all variants are set
103
    fn all() -> Flags<Self>;
104
}
105
106
/// Storage type for handling flags
107
#[derive(Copy, Clone, PartialEq, Eq)]
108
#[repr(transparent)]
109
pub struct Flags<Enum, Primitive = <Enum as Flag>::Primitive> {
110
    val: Primitive,
111
    marker: std::marker::PhantomData<Enum>,
112
}
113
114
impl<Enum> std::fmt::Debug for Flags<Enum>
115
where
116
    Enum: Flag,
117
{
118
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119
        self.val.fmt(f)
120
    }
121
}
122
123
impl<Enum> Default for Flags<Enum>
124
where
125
    Enum: Flag,
126
{
127
    fn default() -> Self {
128
        Self {
129
            val: <Enum as Flag>::Primitive::default(),
130
            marker: std::marker::PhantomData,
131
        }
132
    }
133
}
134
135
impl<Enum> Flags<Enum>
136
where
137
    Enum: Flag,
138
{
139
    /// Get a flag from a single enum value
140
11.9M
    pub fn from_flag(flag: Enum) -> Self {
141
11.9M
        Self {
142
11.9M
            val: flag.bits(),
143
11.9M
            marker: std::marker::PhantomData,
144
11.9M
        }
145
11.9M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_flag
Line
Count
Source
140
6.81M
    pub fn from_flag(flag: Enum) -> Self {
141
6.81M
        Self {
142
6.81M
            val: flag.bits(),
143
6.81M
            marker: std::marker::PhantomData,
144
6.81M
        }
145
6.81M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_flag
Line
Count
Source
140
2.06M
    pub fn from_flag(flag: Enum) -> Self {
141
2.06M
        Self {
142
2.06M
            val: flag.bits(),
143
2.06M
            marker: std::marker::PhantomData,
144
2.06M
        }
145
2.06M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_flag
Line
Count
Source
140
38.6k
    pub fn from_flag(flag: Enum) -> Self {
141
38.6k
        Self {
142
38.6k
            val: flag.bits(),
143
38.6k
            marker: std::marker::PhantomData,
144
38.6k
        }
145
38.6k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_flag
Line
Count
Source
140
10.9k
    pub fn from_flag(flag: Enum) -> Self {
141
10.9k
        Self {
142
10.9k
            val: flag.bits(),
143
10.9k
            marker: std::marker::PhantomData,
144
10.9k
        }
145
10.9k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_flag
Line
Count
Source
140
737k
    pub fn from_flag(flag: Enum) -> Self {
141
737k
        Self {
142
737k
            val: flag.bits(),
143
737k
            marker: std::marker::PhantomData,
144
737k
        }
145
737k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_flag
Line
Count
Source
140
1.85M
    pub fn from_flag(flag: Enum) -> Self {
141
1.85M
        Self {
142
1.85M
            val: flag.bits(),
143
1.85M
            marker: std::marker::PhantomData,
144
1.85M
        }
145
1.85M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_flag
Line
Count
Source
140
241k
    pub fn from_flag(flag: Enum) -> Self {
141
241k
        Self {
142
241k
            val: flag.bits(),
143
241k
            marker: std::marker::PhantomData,
144
241k
        }
145
241k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_flag
Line
Count
Source
140
187k
    pub fn from_flag(flag: Enum) -> Self {
141
187k
        Self {
142
187k
            val: flag.bits(),
143
187k
            marker: std::marker::PhantomData,
144
187k
        }
145
187k
    }
146
147
    /// Get a flag from a numeric value
148
    ///
149
    /// Note: the value is unchecked so any bit may be set. Be
150
    /// careful because `PartialEq` is a direct comparison of
151
    /// underlying bits.
152
27.9M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
27.9M
        Self {
154
27.9M
            val: bits,
155
27.9M
            marker: std::marker::PhantomData,
156
27.9M
        }
157
27.9M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_bits
Line
Count
Source
152
2.06M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
2.06M
        Self {
154
2.06M
            val: bits,
155
2.06M
            marker: std::marker::PhantomData,
156
2.06M
        }
157
2.06M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_bits
Line
Count
Source
152
14.2k
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
14.2k
        Self {
154
14.2k
            val: bits,
155
14.2k
            marker: std::marker::PhantomData,
156
14.2k
        }
157
14.2k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_bits
Line
Count
Source
152
13.8M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
13.8M
        Self {
154
13.8M
            val: bits,
155
13.8M
            marker: std::marker::PhantomData,
156
13.8M
        }
157
13.8M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_bits
Line
Count
Source
152
3.41M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
3.41M
        Self {
154
3.41M
            val: bits,
155
3.41M
            marker: std::marker::PhantomData,
156
3.41M
        }
157
3.41M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_bits
Line
Count
Source
152
705k
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
705k
        Self {
154
705k
            val: bits,
155
705k
            marker: std::marker::PhantomData,
156
705k
        }
157
705k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_bits
Line
Count
Source
152
3.00M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
3.00M
        Self {
154
3.00M
            val: bits,
155
3.00M
            marker: std::marker::PhantomData,
156
3.00M
        }
157
3.00M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_bits
Line
Count
Source
152
3.39M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
3.39M
        Self {
154
3.39M
            val: bits,
155
3.39M
            marker: std::marker::PhantomData,
156
3.39M
        }
157
3.39M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_bits
Line
Count
Source
152
1.53M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
1.53M
        Self {
154
1.53M
            val: bits,
155
1.53M
            marker: std::marker::PhantomData,
156
1.53M
        }
157
1.53M
    }
158
159
    /// Numeric representation of the variant
160
47.9M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
47.9M
        self.val
162
47.9M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::bits
Line
Count
Source
160
4.63M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
4.63M
        self.val
162
4.63M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::bits
Line
Count
Source
160
27.5M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
27.5M
        self.val
162
27.5M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::bits
Line
Count
Source
160
8.24M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
8.24M
        self.val
162
8.24M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::bits
Line
Count
Source
160
47.5k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
47.5k
        self.val
162
47.5k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::bits
Line
Count
Source
160
374k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
374k
        self.val
162
374k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::bits
Line
Count
Source
160
2.92M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
2.92M
        self.val
162
2.92M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::bits
Line
Count
Source
160
3.77M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
3.77M
        self.val
162
3.77M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::bits
Line
Count
Source
160
381k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
381k
        self.val
162
381k
    }
163
164
    /// Reference to numeric representation of the variant
165
    pub fn bits_ref(&self) -> &<Enum as Flag>::Primitive {
166
        &self.val
167
    }
168
169
    /// Check if at least one flag in common is set
170
8.52M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
8.52M
        (self & rhs.into()).bits() != Enum::none().bits()
172
8.52M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::AccessType, u8>>
Line
Count
Source
170
1.12M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
1.12M
        (self & rhs.into()).bits() != Enum::none().bits()
172
1.12M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_modbus::ErrorFlags>
Line
Count
Source
170
6.80M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
6.80M
        (self & rhs.into()).bits() != Enum::none().bits()
172
6.80M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>
Line
Count
Source
170
73.8k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
73.8k
        (self & rhs.into()).bits() != Enum::none().bits()
172
73.8k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>
Line
Count
Source
170
1.05k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
1.05k
        (self & rhs.into()).bits() != Enum::none().bits()
172
1.05k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::intersects::<sawp_modbus::AccessType>
Line
Count
Source
170
493k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
493k
        (self & rhs.into()).bits() != Enum::none().bits()
172
493k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_modbus::ErrorFlags>
Line
Count
Source
170
28.6k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
28.6k
        (self & rhs.into()).bits() != Enum::none().bits()
172
28.6k
    }
173
174
    /// Check if all flags provided in `rhs` are set
175
2.34M
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
2.34M
        let rhs = rhs.into();
177
2.34M
        (self & rhs).bits() == rhs.bits()
178
2.34M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::contains::<sawp_modbus::AccessType>
Line
Count
Source
175
28.8k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
28.8k
        let rhs = rhs.into();
177
28.8k
        (self & rhs).bits() == rhs.bits()
178
28.8k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::contains::<sawp_modbus::ErrorFlags>
Line
Count
Source
175
12.0k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
12.0k
        let rhs = rhs.into();
177
12.0k
        (self & rhs).bits() == rhs.bits()
178
12.0k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::contains::<sawp_modbus::CodeCategory>
Line
Count
Source
175
9.60k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
9.60k
        let rhs = rhs.into();
177
9.60k
        (self & rhs).bits() == rhs.bits()
178
9.60k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::contains::<sawp_pop3::ErrorFlag>
Line
Count
Source
175
2.06M
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
2.06M
        let rhs = rhs.into();
177
2.06M
        (self & rhs).bits() == rhs.bits()
178
2.06M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::contains::<sawp_modbus::AccessType>
Line
Count
Source
175
232k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
232k
        let rhs = rhs.into();
177
232k
        (self & rhs).bits() == rhs.bits()
178
232k
    }
179
180
2.36k
    pub fn is_empty(&self) -> bool {
181
2.36k
        self.bits() == <Enum as Flag>::none().bits()
182
2.36k
    }
183
184
    pub fn is_all(&self) -> bool {
185
        self.bits() == <Enum as Flag>::all().bits()
186
    }
187
}
188
189
impl<Enum: Flag> From<Enum> for Flags<Enum> {
190
11.9M
    fn from(flag: Enum) -> Self {
191
11.9M
        Self::from_flag(flag)
192
11.9M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::convert::From<sawp_modbus::ErrorFlags>>::from
Line
Count
Source
190
6.81M
    fn from(flag: Enum) -> Self {
191
6.81M
        Self::from_flag(flag)
192
6.81M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::convert::From<sawp_pop3::ErrorFlag>>::from
Line
Count
Source
190
2.06M
    fn from(flag: Enum) -> Self {
191
2.06M
        Self::from_flag(flag)
192
2.06M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::convert::From<sawp_modbus::AccessType>>::from
Line
Count
Source
190
38.6k
    fn from(flag: Enum) -> Self {
191
38.6k
        Self::from_flag(flag)
192
38.6k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::convert::From<sawp_modbus::CodeCategory>>::from
Line
Count
Source
190
10.9k
    fn from(flag: Enum) -> Self {
191
10.9k
        Self::from_flag(flag)
192
10.9k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::convert::From<sawp_modbus::AccessType>>::from
Line
Count
Source
190
737k
    fn from(flag: Enum) -> Self {
191
737k
        Self::from_flag(flag)
192
737k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::convert::From<sawp_modbus::ErrorFlags>>::from
Line
Count
Source
190
1.85M
    fn from(flag: Enum) -> Self {
191
1.85M
        Self::from_flag(flag)
192
1.85M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::convert::From<sawp_modbus::CodeCategory>>::from
Line
Count
Source
190
241k
    fn from(flag: Enum) -> Self {
191
241k
        Self::from_flag(flag)
192
241k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::convert::From<sawp_pop3::ErrorFlag>>::from
Line
Count
Source
190
187k
    fn from(flag: Enum) -> Self {
191
187k
        Self::from_flag(flag)
192
187k
    }
193
}
194
195
impl<Enum: Flag> PartialEq<Enum> for Flags<Enum> {
196
381k
    fn eq(&self, other: &Enum) -> bool {
197
381k
        self.bits() == other.bits()
198
381k
    }
Unexecuted instantiation: <sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::cmp::PartialEq<sawp_modbus::AccessType>>::eq
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::cmp::PartialEq<sawp_modbus::CodeCategory>>::eq
Line
Count
Source
196
381k
    fn eq(&self, other: &Enum) -> bool {
197
381k
        self.bits() == other.bits()
198
381k
    }
199
}
200
201
impl<T, B> std::ops::BitOr<B> for Flags<T>
202
where
203
    T: Flag,
204
    B: Into<Flags<T>>,
205
{
206
    type Output = Flags<T>;
207
14.3k
    fn bitor(self, other: B) -> Flags<T> {
208
14.3k
        Flags::from_bits(self.bits() | other.into().bits())
209
14.3k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitOr<sawp_modbus::AccessType>>::bitor
Line
Count
Source
207
2.78k
    fn bitor(self, other: B) -> Flags<T> {
208
2.78k
        Flags::from_bits(self.bits() | other.into().bits())
209
2.78k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::ops::bit::BitOr<sawp_modbus::CodeCategory>>::bitor
Line
Count
Source
207
40
    fn bitor(self, other: B) -> Flags<T> {
208
40
        Flags::from_bits(self.bits() | other.into().bits())
209
40
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitOr<sawp_modbus::AccessType>>::bitor
Line
Count
Source
207
11.5k
    fn bitor(self, other: B) -> Flags<T> {
208
11.5k
        Flags::from_bits(self.bits() | other.into().bits())
209
11.5k
    }
210
}
211
212
impl<T, B> std::ops::BitOrAssign<B> for Flags<T>
213
where
214
    T: Flag,
215
    B: Into<Flags<T>>,
216
{
217
2.01M
    fn bitor_assign(&mut self, rhs: B) {
218
2.01M
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
2.01M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitOrAssign<sawp_modbus::ErrorFlags>>::bitor_assign
Line
Count
Source
217
1.82M
    fn bitor_assign(&mut self, rhs: B) {
218
1.82M
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
1.82M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::ops::bit::BitOrAssign<sawp_pop3::ErrorFlag>>::bitor_assign
Line
Count
Source
217
187k
    fn bitor_assign(&mut self, rhs: B) {
218
187k
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
187k
    }
220
}
221
222
impl<T, B> std::ops::BitAnd<B> for Flags<T>
223
where
224
    T: Flag,
225
    B: Into<Flags<T>>,
226
{
227
    type Output = Flags<T>;
228
10.8M
    fn bitand(self, other: B) -> Flags<T> {
229
10.8M
        Flags::from_bits(self.bits() & other.into().bits())
230
10.8M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd<sawp_modbus::AccessType>>::bitand
Line
Count
Source
228
2.23k
    fn bitand(self, other: B) -> Flags<T> {
229
2.23k
        Flags::from_bits(self.bits() & other.into().bits())
230
2.23k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
1.15M
    fn bitand(self, other: B) -> Flags<T> {
229
1.15M
        Flags::from_bits(self.bits() & other.into().bits())
230
1.15M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
6.89M
    fn bitand(self, other: B) -> Flags<T> {
229
6.89M
        Flags::from_bits(self.bits() & other.into().bits())
230
6.89M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
10.6k
    fn bitand(self, other: B) -> Flags<T> {
229
10.6k
        Flags::from_bits(self.bits() & other.into().bits())
230
10.6k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
2.06M
    fn bitand(self, other: B) -> Flags<T> {
229
2.06M
        Flags::from_bits(self.bits() & other.into().bits())
230
2.06M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
725k
    fn bitand(self, other: B) -> Flags<T> {
229
725k
        Flags::from_bits(self.bits() & other.into().bits())
230
725k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
28.6k
    fn bitand(self, other: B) -> Flags<T> {
229
28.6k
        Flags::from_bits(self.bits() & other.into().bits())
230
28.6k
    }
231
}
232
233
impl<T, B> std::ops::BitAndAssign<B> for Flags<T>
234
where
235
    T: Flag,
236
    B: Into<Flags<T>>,
237
{
238
    fn bitand_assign(&mut self, rhs: B) {
239
        *self = Flags::from_bits(self.bits() & rhs.into().bits())
240
    }
241
}
242
243
impl<T, B> std::ops::BitXor<B> for Flags<T>
244
where
245
    T: Flag,
246
    B: Into<Flags<T>>,
247
{
248
    type Output = Flags<T>;
249
    fn bitxor(self, other: B) -> Flags<T> {
250
        Flags::from_bits(self.bits() ^ other.into().bits())
251
    }
252
}
253
254
impl<T, B> std::ops::BitXorAssign<B> for Flags<T>
255
where
256
    T: Flag,
257
    B: Into<Flags<T>>,
258
{
259
    fn bitxor_assign(&mut self, rhs: B) {
260
        *self = Flags::from_bits(self.bits() ^ rhs.into().bits())
261
    }
262
}
263
264
impl<T: Flag> std::ops::Not for Flags<T> {
265
    type Output = Flags<T>;
266
267
2
    fn not(self) -> Self::Output {
268
2
        Flags::from_bits(!self.bits())
269
2
    }
270
}
271
272
impl<T: Flag> std::fmt::Display for Flags<T> {
273
    /// A pipe-separated list of set flags.
274
7.20k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
7.20k
        let none = self.bits() == T::none().bits();
276
7.20k
        let mut first = true;
277
7.20k
        for val in <T as Flag>::ITEMS
278
7.20k
            .iter()
279
7.20k
            .cloned()
280
50.4k
            .filter(move |&flag| self.contains(flag))
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::fmt::Display>::fmt::{closure#0}
Line
Count
Source
280
28.8k
            .filter(move |&flag| self.contains(flag))
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::fmt::Display>::fmt::{closure#0}
Line
Count
Source
280
12.0k
            .filter(move |&flag| self.contains(flag))
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::fmt::Display>::fmt::{closure#0}
Line
Count
Source
280
9.60k
            .filter(move |&flag| self.contains(flag))
281
        {
282
3.51k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
3.51k
            first = false;
284
285
3.51k
            if none {
286
0
                return Ok(());
287
3.51k
            }
288
        }
289
290
7.20k
        if none {
291
4.46k
            write!(f, "NONE")?;
292
2.74k
        }
293
294
7.20k
        Ok(())
295
7.20k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.40k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.40k
        let none = self.bits() == T::none().bits();
276
2.40k
        let mut first = true;
277
2.40k
        for val in <T as Flag>::ITEMS
278
2.40k
            .iter()
279
2.40k
            .cloned()
280
2.40k
            .filter(move |&flag| self.contains(flag))
281
        {
282
1.21k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
1.21k
            first = false;
284
285
1.21k
            if none {
286
0
                return Ok(());
287
1.21k
            }
288
        }
289
290
2.40k
        if none {
291
1.94k
            write!(f, "NONE")?;
292
454
        }
293
294
2.40k
        Ok(())
295
2.40k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.40k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.40k
        let none = self.bits() == T::none().bits();
276
2.40k
        let mut first = true;
277
2.40k
        for val in <T as Flag>::ITEMS
278
2.40k
            .iter()
279
2.40k
            .cloned()
280
2.40k
            .filter(move |&flag| self.contains(flag))
281
        {
282
489
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
489
            first = false;
284
285
489
            if none {
286
0
                return Ok(());
287
489
            }
288
        }
289
290
2.40k
        if none {
291
1.91k
            write!(f, "NONE")?;
292
483
        }
293
294
2.40k
        Ok(())
295
2.40k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.40k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.40k
        let none = self.bits() == T::none().bits();
276
2.40k
        let mut first = true;
277
2.40k
        for val in <T as Flag>::ITEMS
278
2.40k
            .iter()
279
2.40k
            .cloned()
280
2.40k
            .filter(move |&flag| self.contains(flag))
281
        {
282
1.80k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
1.80k
            first = false;
284
285
1.80k
            if none {
286
0
                return Ok(());
287
1.80k
            }
288
        }
289
290
2.40k
        if none {
291
595
            write!(f, "NONE")?;
292
1.80k
        }
293
294
2.40k
        Ok(())
295
2.40k
    }
296
}
297
298
impl<T: Flag> std::fmt::Binary for Flags<T> {
299
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
300
        std::fmt::Binary::fmt(&self.bits(), f)
301
    }
302
}
303
304
/// Example enum deriving `BitFlags`
305
pub mod example {
306
    use super::*;
307
308
    /// Example enum
309
    #[derive(Debug, Clone, Copy, PartialEq, Eq, BitFlags)]
310
    #[repr(u8)]
311
    pub enum Test {
312
        A = 0b0001,
313
        B = 0b0010,
314
        C = 0b0100,
315
        D = 0b1000,
316
        /// Variants can be bitmask of other fields
317
        E = Test::A as u8 | Test::B as u8 | Test::C as u8 | Test::D as u8,
318
    }
319
}
320
321
#[cfg(test)]
322
mod test {
323
    use super::{example::*, *};
324
325
    #[test]
326
    fn test_enum_bits() {
327
        let bits = 0b1010_1010;
328
        let flags = Flags::<Test>::from_bits(bits);
329
        assert_eq!(bits, flags.bits());
330
        assert_eq!(&bits, flags.bits_ref());
331
    }
332
333
    #[test]
334
    fn test_enum_or() {
335
        let mut flags = Test::A | Test::B;
336
        assert_eq!(0b0011, flags.bits());
337
338
        flags |= Test::C;
339
        assert_eq!(0b0111, flags.bits());
340
341
        flags |= Test::C | Test::D;
342
        assert_eq!(0b1111, flags.bits());
343
    }
344
345
    #[test]
346
    fn test_enum_and() {
347
        let mut flags = Test::E & Test::B;
348
        assert_eq!(0b0010, flags.bits());
349
350
        flags &= Test::B;
351
        assert_eq!(0b0010, flags.bits());
352
353
        flags &= Test::E & Test::B;
354
        assert_eq!(0b0010, flags.bits());
355
    }
356
357
    #[test]
358
    fn test_enum_xor() {
359
        let mut flags = Test::A ^ Test::B;
360
        assert_eq!(0b0011, flags.bits());
361
362
        flags ^= Test::C;
363
        assert_eq!(0b0111, flags.bits());
364
365
        flags ^= Test::D ^ Test::B;
366
        assert_eq!(0b1101, flags.bits());
367
    }
368
369
    #[test]
370
    fn test_enum_not() {
371
        let flags = !Test::A;
372
        assert_eq!(0b1111_1110, flags.bits());
373
        let flags = !(Test::A ^ Test::B);
374
        assert_eq!(0b1111_1100, flags.bits());
375
    }
376
377
    #[test]
378
    fn test_contains() {
379
        let flags = Test::A | Test::C;
380
        assert!(flags.contains(Test::A));
381
        assert!(!flags.contains(Test::B));
382
        assert!(!flags.contains(Test::E));
383
        assert!(!flags.contains(Test::B | Test::D));
384
        assert!(!flags.contains(Test::A | Test::B));
385
        assert!(flags.contains(Test::A | Test::C));
386
    }
387
388
    #[test]
389
    fn test_intersects() {
390
        let flags = Test::A | Test::C;
391
        assert!(flags.intersects(Test::A));
392
        assert!(flags.intersects(Test::E));
393
        assert!(flags.intersects(Test::A | Test::B));
394
        assert!(flags.intersects(Test::A | Test::C));
395
        assert!(flags.intersects(Test::A | Test::B | Test::C));
396
        assert!(!flags.intersects(Test::B | Test::D));
397
    }
398
399
    #[test]
400
    fn test_eq() {
401
        let flags = Test::A;
402
        assert_eq!(flags, Test::A);
403
        assert_eq!(Test::A, flags);
404
405
        let flags = Test::A | Test::C;
406
        assert_ne!(flags, Test::A);
407
        assert_ne!(flags, Test::C);
408
        assert_ne!(Test::A, flags);
409
        assert_eq!(flags, Test::A | Test::C);
410
        assert_ne!(flags, Test::A | Test::C | Test::E);
411
412
        let flags = Flags::<Test>::from_bits(0b1000_0001);
413
        assert_ne!(flags, Test::A);
414
    }
415
416
    #[test]
417
    fn test_enum_string() {
418
        assert_eq!("NONE", Test::none().to_string());
419
        assert_eq!("A", Test::A.to_string());
420
        assert_eq!("A | B", (Test::A | Test::B).to_string());
421
        assert_eq!("A | B | C | D | E", Test::E.to_string());
422
        assert_eq!("A | B | C | D | E", Flags::from_flag(Test::E).to_string());
423
    }
424
425
    #[test]
426
    fn test_enum_string_none() {
427
        #[derive(Debug, Clone, Copy, PartialEq, Eq, BitFlags)]
428
        #[repr(u8)]
429
        pub enum Test {
430
            Zero = 0b0000,
431
            A = 0b0001,
432
            B = 0b0010,
433
            C = 0b0100,
434
            D = 0b1000,
435
            /// Variants can be bitmask of other fields
436
            E = Test::A as u8 | Test::B as u8 | Test::C as u8 | Test::D as u8,
437
        }
438
        assert_eq!("Zero", Test::Zero.to_string());
439
        assert_eq!("Zero", Test::none().to_string());
440
        assert_eq!("Zero", Flags::from_flag(Test::Zero).to_string());
441
    }
442
443
    #[test]
444
    fn test_enum_format() {
445
        assert_eq!("A", format!("{:?}", Test::A));
446
        assert_eq!("E", format!("{:?}", Test::E));
447
        assert_eq!("0", format!("{:?}", Test::none()));
448
449
        assert_eq!("0", format!("{:b}", Test::none()));
450
        assert_eq!("1", format!("{:b}", Test::A));
451
        assert_eq!("1111", format!("{:b}", Test::E));
452
    }
453
454
    #[test]
455
    fn test_enum_from_str() {
456
        use std::str::FromStr;
457
        assert_eq!(Err(()), Test::from_str(""));
458
        assert_eq!(Ok(Test::A), Test::from_str("a"));
459
        assert_eq!(Ok(Test::A), Test::from_str("A"));
460
    }
461
462
    #[test]
463
    fn test_all() {
464
        assert_eq!(Test::E, Test::all());
465
        assert!(!Flags::from_flag(Test::A).is_all());
466
        assert!(Flags::from_flag(Test::E).is_all());
467
    }
468
469
    #[test]
470
    fn test_none() {
471
        assert_eq!(Flags::from_bits(0), Test::none());
472
        assert!(Flags::<Test>::from_bits(0).is_empty());
473
        assert!(!Flags::from_flag(Test::A).is_empty());
474
        assert!(!Flags::from_flag(Test::E).is_empty());
475
    }
476
}