Coverage Report

Created: 2025-12-31 06:43

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
13.1M
    pub fn from_flag(flag: Enum) -> Self {
141
13.1M
        Self {
142
13.1M
            val: flag.bits(),
143
13.1M
            marker: std::marker::PhantomData,
144
13.1M
        }
145
13.1M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_flag
Line
Count
Source
140
42.6k
    pub fn from_flag(flag: Enum) -> Self {
141
42.6k
        Self {
142
42.6k
            val: flag.bits(),
143
42.6k
            marker: std::marker::PhantomData,
144
42.6k
        }
145
42.6k
    }
<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_pop3::ErrorFlag, u8>>::from_flag
Line
Count
Source
140
1.75M
    pub fn from_flag(flag: Enum) -> Self {
141
1.75M
        Self {
142
1.75M
            val: flag.bits(),
143
1.75M
            marker: std::marker::PhantomData,
144
1.75M
        }
145
1.75M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_flag
Line
Count
Source
140
8.17M
    pub fn from_flag(flag: Enum) -> Self {
141
8.17M
        Self {
142
8.17M
            val: flag.bits(),
143
8.17M
            marker: std::marker::PhantomData,
144
8.17M
        }
145
8.17M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_flag
Line
Count
Source
140
130k
    pub fn from_flag(flag: Enum) -> Self {
141
130k
        Self {
142
130k
            val: flag.bits(),
143
130k
            marker: std::marker::PhantomData,
144
130k
        }
145
130k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_flag
Line
Count
Source
140
608k
    pub fn from_flag(flag: Enum) -> Self {
141
608k
        Self {
142
608k
            val: flag.bits(),
143
608k
            marker: std::marker::PhantomData,
144
608k
        }
145
608k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_flag
Line
Count
Source
140
2.12M
    pub fn from_flag(flag: Enum) -> Self {
141
2.12M
        Self {
142
2.12M
            val: flag.bits(),
143
2.12M
            marker: std::marker::PhantomData,
144
2.12M
        }
145
2.12M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_flag
Line
Count
Source
140
289k
    pub fn from_flag(flag: Enum) -> Self {
141
289k
        Self {
142
289k
            val: flag.bits(),
143
289k
            marker: std::marker::PhantomData,
144
289k
        }
145
289k
    }
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
31.9M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
31.9M
        Self {
154
31.9M
            val: bits,
155
31.9M
            marker: std::marker::PhantomData,
156
31.9M
        }
157
31.9M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_bits
Line
Count
Source
152
4.15M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
4.15M
        Self {
154
4.15M
            val: bits,
155
4.15M
            marker: std::marker::PhantomData,
156
4.15M
        }
157
4.15M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_bits
Line
Count
Source
152
13.8k
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
13.8k
        Self {
154
13.8k
            val: bits,
155
13.8k
            marker: std::marker::PhantomData,
156
13.8k
        }
157
13.8k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_bits
Line
Count
Source
152
1.75M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
1.75M
        Self {
154
1.75M
            val: bits,
155
1.75M
            marker: std::marker::PhantomData,
156
1.75M
        }
157
1.75M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_bits
Line
Count
Source
152
16.5M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
16.5M
        Self {
154
16.5M
            val: bits,
155
16.5M
            marker: std::marker::PhantomData,
156
16.5M
        }
157
16.5M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::from_bits
Line
Count
Source
152
571k
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
571k
        Self {
154
571k
            val: bits,
155
571k
            marker: std::marker::PhantomData,
156
571k
        }
157
571k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::from_bits
Line
Count
Source
152
3.13M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
3.13M
        Self {
154
3.13M
            val: bits,
155
3.13M
            marker: std::marker::PhantomData,
156
3.13M
        }
157
3.13M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::from_bits
Line
Count
Source
152
3.93M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
3.93M
        Self {
154
3.93M
            val: bits,
155
3.93M
            marker: std::marker::PhantomData,
156
3.93M
        }
157
3.93M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::from_bits
Line
Count
Source
152
1.79M
    pub fn from_bits(bits: <Enum as Flag>::Primitive) -> Self {
153
1.79M
        Self {
154
1.79M
            val: bits,
155
1.79M
            marker: std::marker::PhantomData,
156
1.79M
        }
157
1.79M
    }
158
159
    /// Numeric representation of the variant
160
53.1M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
53.1M
        self.val
162
53.1M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::bits
Line
Count
Source
160
46.1k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
46.1k
        self.val
162
46.1k
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::bits
Line
Count
Source
160
7.00M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
7.00M
        self.val
162
7.00M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::bits
Line
Count
Source
160
5.61M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
5.61M
        self.val
162
5.61M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::bits
Line
Count
Source
160
33.0M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
33.0M
        self.val
162
33.0M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::bits
Line
Count
Source
160
260k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
260k
        self.val
162
260k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::bits
Line
Count
Source
160
2.41M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
2.41M
        self.val
162
2.41M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::bits
Line
Count
Source
160
4.27M
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
4.27M
        self.val
162
4.27M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::bits
Line
Count
Source
160
434k
    pub fn bits(&self) -> <Enum as Flag>::Primitive {
161
434k
        self.val
162
434k
    }
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
10.0M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
10.0M
        (self & rhs.into()).bits() != Enum::none().bits()
172
10.0M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::AccessType, u8>>
Line
Count
Source
170
1.37M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
1.37M
        (self & rhs.into()).bits() != Enum::none().bits()
172
1.37M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_modbus::ErrorFlags>
Line
Count
Source
170
8.16M
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
8.16M
        (self & rhs.into()).bits() != Enum::none().bits()
172
8.16M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>
Line
Count
Source
170
81.2k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
81.2k
        (self & rhs.into()).bits() != Enum::none().bits()
172
81.2k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::intersects::<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>
Line
Count
Source
170
1.13k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
1.13k
        (self & rhs.into()).bits() != Enum::none().bits()
172
1.13k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::intersects::<sawp_modbus::AccessType>
Line
Count
Source
170
440k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
440k
        (self & rhs.into()).bits() != Enum::none().bits()
172
440k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::intersects::<sawp_modbus::ErrorFlags>
Line
Count
Source
170
12.8k
    pub fn intersects<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
171
12.8k
        (self & rhs.into()).bits() != Enum::none().bits()
172
12.8k
    }
173
174
    /// Check if all flags provided in `rhs` are set
175
1.95M
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
1.95M
        let rhs = rhs.into();
177
1.95M
        (self & rhs).bits() == rhs.bits()
178
1.95M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8>>::contains::<sawp_pop3::ErrorFlag>
Line
Count
Source
175
1.75M
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
1.75M
        let rhs = rhs.into();
177
1.75M
        (self & rhs).bits() == rhs.bits()
178
1.75M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::contains::<sawp_modbus::AccessType>
Line
Count
Source
175
27.7k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
27.7k
        let rhs = rhs.into();
177
27.7k
        (self & rhs).bits() == rhs.bits()
178
27.7k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8>>::contains::<sawp_modbus::ErrorFlags>
Line
Count
Source
175
11.5k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
11.5k
        let rhs = rhs.into();
177
11.5k
        (self & rhs).bits() == rhs.bits()
178
11.5k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8>>::contains::<sawp_modbus::CodeCategory>
Line
Count
Source
175
9.24k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
9.24k
        let rhs = rhs.into();
177
9.24k
        (self & rhs).bits() == rhs.bits()
178
9.24k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8>>::contains::<sawp_modbus::AccessType>
Line
Count
Source
175
158k
    pub fn contains<B: Into<Flags<Enum>>>(self, rhs: B) -> bool {
176
158k
        let rhs = rhs.into();
177
158k
        (self & rhs).bits() == rhs.bits()
178
158k
    }
179
180
2.07k
    pub fn is_empty(&self) -> bool {
181
2.07k
        self.bits() == <Enum as Flag>::none().bits()
182
2.07k
    }
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
13.1M
    fn from(flag: Enum) -> Self {
191
13.1M
        Self::from_flag(flag)
192
13.1M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::convert::From<sawp_modbus::AccessType>>::from
Line
Count
Source
190
42.6k
    fn from(flag: Enum) -> Self {
191
42.6k
        Self::from_flag(flag)
192
42.6k
    }
<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_pop3::ErrorFlag, u8> as core::convert::From<sawp_pop3::ErrorFlag>>::from
Line
Count
Source
190
1.75M
    fn from(flag: Enum) -> Self {
191
1.75M
        Self::from_flag(flag)
192
1.75M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::convert::From<sawp_modbus::ErrorFlags>>::from
Line
Count
Source
190
8.17M
    fn from(flag: Enum) -> Self {
191
8.17M
        Self::from_flag(flag)
192
8.17M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::convert::From<sawp_pop3::ErrorFlag>>::from
Line
Count
Source
190
130k
    fn from(flag: Enum) -> Self {
191
130k
        Self::from_flag(flag)
192
130k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::convert::From<sawp_modbus::AccessType>>::from
Line
Count
Source
190
608k
    fn from(flag: Enum) -> Self {
191
608k
        Self::from_flag(flag)
192
608k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::convert::From<sawp_modbus::ErrorFlags>>::from
Line
Count
Source
190
2.12M
    fn from(flag: Enum) -> Self {
191
2.12M
        Self::from_flag(flag)
192
2.12M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::convert::From<sawp_modbus::CodeCategory>>::from
Line
Count
Source
190
289k
    fn from(flag: Enum) -> Self {
191
289k
        Self::from_flag(flag)
192
289k
    }
193
}
194
195
impl<Enum: Flag> PartialEq<Enum> for Flags<Enum> {
196
434k
    fn eq(&self, other: &Enum) -> bool {
197
434k
        self.bits() == other.bits()
198
434k
    }
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
434k
    fn eq(&self, other: &Enum) -> bool {
197
434k
        self.bits() == other.bits()
198
434k
    }
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
13.5k
    fn bitor(self, other: B) -> Flags<T> {
208
13.5k
        Flags::from_bits(self.bits() | other.into().bits())
209
13.5k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitOr<sawp_modbus::AccessType>>::bitor
Line
Count
Source
207
4.44k
    fn bitor(self, other: B) -> Flags<T> {
208
4.44k
        Flags::from_bits(self.bits() | other.into().bits())
209
4.44k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::ops::bit::BitOr<sawp_modbus::CodeCategory>>::bitor
Line
Count
Source
207
8
    fn bitor(self, other: B) -> Flags<T> {
208
8
        Flags::from_bits(self.bits() | other.into().bits())
209
8
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitOr<sawp_modbus::AccessType>>::bitor
Line
Count
Source
207
9.07k
    fn bitor(self, other: B) -> Flags<T> {
208
9.07k
        Flags::from_bits(self.bits() | other.into().bits())
209
9.07k
    }
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.24M
    fn bitor_assign(&mut self, rhs: B) {
218
2.24M
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
2.24M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::ops::bit::BitOrAssign<sawp_pop3::ErrorFlag>>::bitor_assign
Line
Count
Source
217
130k
    fn bitor_assign(&mut self, rhs: B) {
218
130k
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
130k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitOrAssign<sawp_modbus::ErrorFlags>>::bitor_assign
Line
Count
Source
217
2.11M
    fn bitor_assign(&mut self, rhs: B) {
218
2.11M
        *self = Flags::from_bits(self.bits() | rhs.into().bits())
219
2.11M
    }
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.0M
    fn bitand(self, other: B) -> Flags<T> {
229
12.0M
        Flags::from_bits(self.bits() & other.into().bits())
230
12.0M
    }
<sawp_flags::Flags<sawp_pop3::ErrorFlag, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
1.75M
    fn bitand(self, other: B) -> Flags<T> {
229
1.75M
        Flags::from_bits(self.bits() & other.into().bits())
230
1.75M
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd<sawp_modbus::AccessType>>::bitand
Line
Count
Source
228
1.98k
    fn bitand(self, other: B) -> Flags<T> {
229
1.98k
        Flags::from_bits(self.bits() & other.into().bits())
230
1.98k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
1.40M
    fn bitand(self, other: B) -> Flags<T> {
229
1.40M
        Flags::from_bits(self.bits() & other.into().bits())
230
1.40M
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
8.25M
    fn bitand(self, other: B) -> Flags<T> {
229
8.25M
        Flags::from_bits(self.bits() & other.into().bits())
230
8.25M
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
10.3k
    fn bitand(self, other: B) -> Flags<T> {
229
10.3k
        Flags::from_bits(self.bits() & other.into().bits())
230
10.3k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
599k
    fn bitand(self, other: B) -> Flags<T> {
229
599k
        Flags::from_bits(self.bits() & other.into().bits())
230
599k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::ops::bit::BitAnd>::bitand
Line
Count
Source
228
12.8k
    fn bitand(self, other: B) -> Flags<T> {
229
12.8k
        Flags::from_bits(self.bits() & other.into().bits())
230
12.8k
    }
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
6.93k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
6.93k
        let none = self.bits() == T::none().bits();
276
6.93k
        let mut first = true;
277
6.93k
        for val in <T as Flag>::ITEMS
278
6.93k
            .iter()
279
6.93k
            .cloned()
280
48.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
27.7k
            .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.5k
            .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.24k
            .filter(move |&flag| self.contains(flag))
281
        {
282
2.99k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
2.99k
            first = false;
284
285
2.99k
            if none {
286
0
                return Ok(());
287
2.99k
            }
288
        }
289
290
6.93k
        if none {
291
4.45k
            write!(f, "NONE")?;
292
2.48k
        }
293
294
6.93k
        Ok(())
295
6.93k
    }
<sawp_flags::Flags<sawp_modbus::AccessType, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.31k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.31k
        let none = self.bits() == T::none().bits();
276
2.31k
        let mut first = true;
277
2.31k
        for val in <T as Flag>::ITEMS
278
2.31k
            .iter()
279
2.31k
            .cloned()
280
2.31k
            .filter(move |&flag| self.contains(flag))
281
        {
282
796
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
796
            first = false;
284
285
796
            if none {
286
0
                return Ok(());
287
796
            }
288
        }
289
290
2.31k
        if none {
291
2.00k
            write!(f, "NONE")?;
292
305
        }
293
294
2.31k
        Ok(())
295
2.31k
    }
<sawp_flags::Flags<sawp_modbus::ErrorFlags, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.31k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.31k
        let none = self.bits() == T::none().bits();
276
2.31k
        let mut first = true;
277
2.31k
        for val in <T as Flag>::ITEMS
278
2.31k
            .iter()
279
2.31k
            .cloned()
280
2.31k
            .filter(move |&flag| self.contains(flag))
281
        {
282
561
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
561
            first = false;
284
285
561
            if none {
286
0
                return Ok(());
287
561
            }
288
        }
289
290
2.31k
        if none {
291
1.77k
            write!(f, "NONE")?;
292
535
        }
293
294
2.31k
        Ok(())
295
2.31k
    }
<sawp_flags::Flags<sawp_modbus::CodeCategory, u8> as core::fmt::Display>::fmt
Line
Count
Source
274
2.31k
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275
2.31k
        let none = self.bits() == T::none().bits();
276
2.31k
        let mut first = true;
277
2.31k
        for val in <T as Flag>::ITEMS
278
2.31k
            .iter()
279
2.31k
            .cloned()
280
2.31k
            .filter(move |&flag| self.contains(flag))
281
        {
282
1.64k
            write!(f, "{}{:?}", if first { "" } else { " | " }, val)?;
283
1.64k
            first = false;
284
285
1.64k
            if none {
286
0
                return Ok(());
287
1.64k
            }
288
        }
289
290
2.31k
        if none {
291
670
            write!(f, "NONE")?;
292
1.64k
        }
293
294
2.31k
        Ok(())
295
2.31k
    }
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
}