/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 | | } |