Coverage Report

Created: 2025-07-23 07:29

/rust/registry/src/index.crates.io-6f17d22bba15001f/sawp-flags-0.13.1/src/lib.rs
Line
Count
Source (jump to first uncovered line)
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
14.6M
    pub fn from_flag(flag: Enum) -> Self {
141
14.6M
        Self {
142
14.6M
            val: flag.bits(),
143
14.6M
            marker: std::marker::PhantomData,
144
14.6M
        }
145
14.6M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_flag
Line
Count
Source
140
1.16M
    pub fn from_flag(flag: Enum) -> Self {
141
1.16M
        Self {
142
1.16M
            val: flag.bits(),
143
1.16M
            marker: std::marker::PhantomData,
144
1.16M
        }
145
1.16M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_flag
Line
Count
Source
140
44.6k
    pub fn from_flag(flag: Enum) -> Self {
141
44.6k
        Self {
142
44.6k
            val: flag.bits(),
143
44.6k
            marker: std::marker::PhantomData,
144
44.6k
        }
145
44.6k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_flag
Line
Count
Source
140
9.26M
    pub fn from_flag(flag: Enum) -> Self {
141
9.26M
        Self {
142
9.26M
            val: flag.bits(),
143
9.26M
            marker: std::marker::PhantomData,
144
9.26M
        }
145
9.26M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_flag
Line
Count
Source
140
11.0k
    pub fn from_flag(flag: Enum) -> Self {
141
11.0k
        Self {
142
11.0k
            val: flag.bits(),
143
11.0k
            marker: std::marker::PhantomData,
144
11.0k
        }
145
11.0k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_flag
Line
Count
Source
140
827k
    pub fn from_flag(flag: Enum) -> Self {
141
827k
        Self {
142
827k
            val: flag.bits(),
143
827k
            marker: std::marker::PhantomData,
144
827k
        }
145
827k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_flag
Line
Count
Source
140
2.72M
    pub fn from_flag(flag: Enum) -> Self {
141
2.72M
        Self {
142
2.72M
            val: flag.bits(),
143
2.72M
            marker: std::marker::PhantomData,
144
2.72M
        }
145
2.72M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_flag
Line
Count
Source
140
550k
    pub fn from_flag(flag: Enum) -> Self {
141
550k
        Self {
142
550k
            val: flag.bits(),
143
550k
            marker: std::marker::PhantomData,
144
550k
        }
145
550k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_flag
Line
Count
Source
140
67.2k
    pub fn from_flag(flag: Enum) -> Self {
141
67.2k
        Self {
142
67.2k
            val: flag.bits(),
143
67.2k
            marker: std::marker::PhantomData,
144
67.2k
        }
145
67.2k
    }
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
35.9M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
35.9M
        Self {
154
35.9M
            val: bits,
155
35.9M
            marker: std::marker::PhantomData,
156
35.9M
        }
157
35.9M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_bits
Line
Count
Source
152
14.1k
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
14.1k
        Self {
154
14.1k
            val: bits,
155
14.1k
            marker: std::marker::PhantomData,
156
14.1k
        }
157
14.1k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_bits
Line
Count
Source
152
1.16M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
1.16M
        Self {
154
1.16M
            val: bits,
155
1.16M
            marker: std::marker::PhantomData,
156
1.16M
        }
157
1.16M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_bits
Line
Count
Source
152
4.44M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
4.44M
        Self {
154
4.44M
            val: bits,
155
4.44M
            marker: std::marker::PhantomData,
156
4.44M
        }
157
4.44M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_bits
Line
Count
Source
152
18.9M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
18.9M
        Self {
154
18.9M
            val: bits,
155
18.9M
            marker: std::marker::PhantomData,
156
18.9M
        }
157
18.9M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_bits
Line
Count
Source
152
4.09M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
4.09M
        Self {
154
4.09M
            val: bits,
155
4.09M
            marker: std::marker::PhantomData,
156
4.09M
        }
157
4.09M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_bits
Line
Count
Source
152
4.86M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
4.86M
        Self {
154
4.86M
            val: bits,
155
4.86M
            marker: std::marker::PhantomData,
156
4.86M
        }
157
4.86M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, 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_pop3::ErrorFlag, u8>>::from_bits
Line
Count
Source
152
360k
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
360k
        Self {
154
360k
            val: bits,
155
360k
            marker: std::marker::PhantomData,
156
360k
        }
157
360k
    }
158
159
    /// Numeric representation of the variant
160
58.0M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
58.0M
        self.val
162
58.0M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::bits
Line
Count
Source
160
4.64M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
4.64M
        self.val
162
4.64M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::bits
Line
Count
Source
160
6.01M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
6.01M
        self.val
162
6.01M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::bits
Line
Count
Source
160
37.5M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
37.5M
        self.val
162
37.5M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::bits
Line
Count
Source
160
47.1k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
47.1k
        self.val
162
47.1k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::bits
Line
Count
Source
160
3.28M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
3.28M
        self.val
162
3.28M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::bits
Line
Count
Source
160
5.59M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
5.59M
        self.val
162
5.59M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::bits
Line
Count
Source
160
794k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
794k
        self.val
162
794k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::bits
Line
Count
Source
160
134k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
134k
        self.val
162
134k
    }
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
11.5M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
11.5M
        (self & rhs.into()).bits() != Enum::none().bits()
172
11.5M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::AccessType, u8>>
Line
Count
Source
170
1.46M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
1.46M
        (self & rhs.into()).bits() != Enum::none().bits()
172
1.46M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_modbus::ErrorFlags>
Line
Count
Source
170
9.25M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
9.25M
        (self & rhs.into()).bits() != Enum::none().bits()
172
9.25M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>
Line
Count
Source
170
128k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
128k
        (self & rhs.into()).bits() != Enum::none().bits()
172
128k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>
Line
Count
Source
170
1.16k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
1.16k
        (self & rhs.into()).bits() != Enum::none().bits()
172
1.16k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::intersects::<sawp_modbus::AccessType>
Line
Count
Source
170
647k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
647k
        (self & rhs.into()).bits() != Enum::none().bits()
172
647k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_modbus::ErrorFlags>
Line
Count
Source
170
73.9k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
73.9k
        (self & rhs.into()).bits() != Enum::none().bits()
172
73.9k
    }
173
174
    /// Check if all flags provided in `rhs` are set
175
1.37M
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
1.37M
        let rhs = rhs.into();
177
1.37M
        (self & rhs).bits() == rhs.bits()
178
1.37M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::contains::<sawp_pop3::ErrorFlag>
Line
Count
Source
175
1.16M
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
1.16M
        let rhs = rhs.into();
177
1.16M
        (self & rhs).bits() == rhs.bits()
178
1.16M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::contains::<sawp_modbus::AccessType>
Line
Count
Source
175
28.3k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
28.3k
        let rhs = rhs.into();
177
28.3k
        (self & rhs).bits() == rhs.bits()
178
28.3k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::contains::<sawp_modbus::ErrorFlags>
Line
Count
Source
175
11.7k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
11.7k
        let rhs = rhs.into();
177
11.7k
        (self & rhs).bits() == rhs.bits()
178
11.7k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::contains::<sawp_modbus::CodeCategory>
Line
Count
Source
175
9.43k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
9.43k
        let rhs = rhs.into();
177
9.43k
        (self & rhs).bits() == rhs.bits()
178
9.43k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::contains::<sawp_modbus::AccessType>
Line
Count
Source
175
167k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
167k
        let rhs = rhs.into();
177
167k
        (self & rhs).bits() == rhs.bits()
178
167k
    }
179
180
2.28k
    pub fn is_empty(&self) -> bool {
181
2.28k
        self.bits() == <Enum as Flag>::none().bits()
182
2.28k
    }
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
14.6M
    fn from(flag: Enum) -> Self {
191
14.6M
        Self::from_flag(flag)
192
14.6M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::convert::From<sawp_pop3::ErrorFlag>>::from
Line
Count
Source
190
1.16M
    fn from(flag: Enum) -> Self {
191
1.16M
        Self::from_flag(flag)
192
1.16M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::convert::From<sawp_modbus::AccessType>>::from
Line
Count
Source
190
44.6k
    fn from(flag: Enum) -> Self {
191
44.6k
        Self::from_flag(flag)
192
44.6k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::convert::From<sawp_modbus::ErrorFlags>>::from
Line
Count
Source
190
9.26M
    fn from(flag: Enum) -> Self {
191
9.26M
        Self::from_flag(flag)
192
9.26M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::convert::From<sawp_modbus::CodeCategory>>::from
Line
Count
Source
190
11.0k
    fn from(flag: Enum) -> Self {
191
11.0k
        Self::from_flag(flag)
192
11.0k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::convert::From<sawp_modbus::AccessType>>::from
Line
Count
Source
190
827k
    fn from(flag: Enum) -> Self {
191
827k
        Self::from_flag(flag)
192
827k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::convert::From<sawp_modbus::ErrorFlags>>::from
Line
Count
Source
190
2.72M
    fn from(flag: Enum) -> Self {
191
2.72M
        Self::from_flag(flag)
192
2.72M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::convert::From<sawp_modbus::CodeCategory>>::from
Line
Count
Source
190
550k
    fn from(flag: Enum) -> Self {
191
550k
        Self::from_flag(flag)
192
550k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::convert::From<sawp_pop3::ErrorFlag>>::from
Line
Count
Source
190
67.2k
    fn from(flag: Enum) -> Self {
191
67.2k
        Self::from_flag(flag)
192
67.2k
    }
193
}
194
195
impl<Enum: Flag> PartialEq<Enum> for Flags<Enum> {
196
794k
    fn eq(&self, other: &Enum) -> bool {
197
794k
        self.bits() == other.bits()
198
794k
    }
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
794k
    fn eq(&self, other: &Enum) -> bool {
197
794k
        self.bits() == other.bits()
198
794k
    }
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
16.8k
    fn bitor(self, other: B) -> Flags<T> {
208
16.8k
        Flags::from_bits(self.bits() | other.into().bits())
209
16.8k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitOr<sawp_modbus::AccessType>>::bitor
Line
Count
Source
207
4.80k
    fn bitor(self, other: B) -> Flags<T> {
208
4.80k
        Flags::from_bits(self.bits() | other.into().bits())
209
4.80k
    }
Unexecuted instantiation: <sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::ops::bit::BitOr<sawp_modbus::CodeCategory>>::bitor
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitOr<sawp_modbus::AccessType>>::bitor
Line
Count
Source
207
12.0k
    fn bitor(self, other: B) -> Flags<T> {
208
12.0k
        Flags::from_bits(self.bits() | other.into().bits())
209
12.0k
    }
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.71M
    fn bitor_assign(&mut self, rhs: B) {
218
2.71M
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
2.71M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitOrAssign<sawp_modbus::ErrorFlags>>::bitor_assign
Line
Count
Source
217
2.65M
    fn bitor_assign(&mut self, rhs: B) {
218
2.65M
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
2.65M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::ops::bit::BitOrAssign<sawp_pop3::ErrorFlag>>::bitor_assign
Line
Count
Source
217
67.2k
    fn bitor_assign(&mut self, rhs: B) {
218
67.2k
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
67.2k
    }
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
12.9M
    fn bitand(self, other: B) -> Flags<T> {
229
12.9M
        Flags::from_bits(self.bits() & other.into().bits())
230
12.9M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
1.16M
    fn bitand(self, other: B) -> Flags<T> {
229
1.16M
        Flags::from_bits(self.bits() & other.into().bits())
230
1.16M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd<sawp_modbus::AccessType>>::bitand
Line
Count
Source
228
2.17k
    fn bitand(self, other: B) -> Flags<T> {
229
2.17k
        Flags::from_bits(self.bits() & other.into().bits())
230
2.17k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
1.49M
    fn bitand(self, other: B) -> Flags<T> {
229
1.49M
        Flags::from_bits(self.bits() & other.into().bits())
230
1.49M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
9.39M
    fn bitand(self, other: B) -> Flags<T> {
229
9.39M
        Flags::from_bits(self.bits() & other.into().bits())
230
9.39M
    }
<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_modbus::AccessType, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
815k
    fn bitand(self, other: B) -> Flags<T> {
229
815k
        Flags::from_bits(self.bits() & other.into().bits())
230
815k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
73.9k
    fn bitand(self, other: B) -> Flags<T> {
229
73.9k
        Flags::from_bits(self.bits() & other.into().bits())
230
73.9k
    }
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
0
    fn not(self) -> Self::Output {
268
0
        Flags::from_bits(!self.bits())
269
0
    }
270
}
271
272
impl<T: Flag> std::fmt::Display for Flags<T> {
273
    /// A pipe-separated list of set flags.
274
7.07k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
7.07k
        let none = self.bits() == T::none().bits();
276
7.07k
        let mut first = true;
277
7.07k
        for val in <T as Flag>::ITEMS
278
7.07k
            .iter()
279
7.07k
            .cloned()
280
49.5k
            .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.3k
            .filter(move |&flag| self.contains(flag))
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::fmt::Display>::fmt::{closure#0}
Line
Count
Source
280
11.7k
            .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.43k
            .filter(move |&flag| self.contains(flag))
281
        {
282
3.24k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
3.24k
            first = false;
284
3.24k
285
3.24k
            if none {
286
0
                return Ok(());
287
3.24k
            }
288
        }
289
290
7.07k
        if none {
291
4.47k
            write!(f, "NONE")?;
292
2.60k
        }
293
294
7.07k
        Ok(())
295
7.07k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.35k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.35k
        let none = self.bits() == T::none().bits();
276
2.35k
        let mut first = true;
277
2.35k
        for val in <T as Flag>::ITEMS
278
2.35k
            .iter()
279
2.35k
            .cloned()
280
2.35k
            .filter(move |&flag| self.contains(flag))
281
        {
282
982
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
982
            first = false;
284
982
285
982
            if none {
286
0
                return Ok(());
287
982
            }
288
        }
289
290
2.35k
        if none {
291
1.98k
            write!(f, "NONE")?;
292
370
        }
293
294
2.35k
        Ok(())
295
2.35k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.35k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.35k
        let none = self.bits() == T::none().bits();
276
2.35k
        let mut first = true;
277
2.35k
        for val in <T as Flag>::ITEMS
278
2.35k
            .iter()
279
2.35k
            .cloned()
280
2.35k
            .filter(move |&flag| self.contains(flag))
281
        {
282
560
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
560
            first = false;
284
560
285
560
            if none {
286
0
                return Ok(());
287
560
            }
288
        }
289
290
2.35k
        if none {
291
1.82k
            write!(f, "NONE")?;
292
532
        }
293
294
2.35k
        Ok(())
295
2.35k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.35k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.35k
        let none = self.bits() == T::none().bits();
276
2.35k
        let mut first = true;
277
2.35k
        for val in <T as Flag>::ITEMS
278
2.35k
            .iter()
279
2.35k
            .cloned()
280
2.35k
            .filter(move |&flag| self.contains(flag))
281
        {
282
1.70k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
1.70k
            first = false;
284
1.70k
285
1.70k
            if none {
286
0
                return Ok(());
287
1.70k
            }
288
        }
289
290
2.35k
        if none {
291
656
            write!(f, "NONE")?;
292
1.70k
        }
293
294
2.35k
        Ok(())
295
2.35k
    }
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
}