new_bitflags/lib.rs
1//! More ergonomic bitflags
2
3#![deny(missing_docs)]
4
5/// Generates a bitflags type, wrapping a given primitive integer type.
6///
7/// # Example
8///
9/// The following macro invocation will create a `struct Foo`:
10///
11/// ```ignore
12/// #[macro_use] extern crate new_bitflags;
13///
14/// new_bitflags!{
15/// pub flags Foo: u32 {
16/// const flag_a = 1 << 0;
17/// const flag_b = 1 << 1;
18/// const flag_c = 1 << 2;
19/// }
20/// }
21///
22/// impl Foo {
23/// pub fn flag_abc() -> Foo {
24/// Foo::flag_a() |
25/// Foo::flag_b() |
26/// Foo::flag_c()
27/// }
28/// }
29///
30/// fn main() {
31/// let f1 = Foo::flag_a() | Foo::flag_c();
32/// let f2 = Foo::flag_b() | Foo::flag_c();
33///
34/// assert_eq!((f1 | f2), Foo::flag_abc()); // union
35/// assert_eq!((f1 & f2), Foo::flag_c()); // intersection
36/// assert_eq!((f1 - f2), Foo::flag_a()); // difference
37/// assert_eq!(!f2, Foo::flag_a()); // complement
38/// }
39/// ```
40///
41/// The generated `struct` can be extended with type and trait `impl`s.
42///
43/// ```ignore
44/// impl Foo {
45/// pub fn is_flag_a(&self) -> bool {
46/// self.contains(Foo::flag_a())
47/// }
48/// }
49/// ```
50///
51/// # Visibility
52///
53/// The visibility of the generated `struct` can be controlled within the
54/// invocation of `new_bitflags!`
55///
56/// ```ignore
57/// #[macro_use] extern crate new_bitflags;
58///
59/// mod example {
60/// // `struct Public` will be visible outside this module.
61/// new_bitflags!{
62/// pub flags Public: u32 {
63/// // ...
64/// }
65/// }
66///
67/// // `struct Private` will not be visible outside this module.
68/// new_bitflags!{
69/// flags Private: u32 {
70/// // ...
71/// }
72/// }
73/// }
74/// ```
75///
76/// # Trait implementations
77///
78/// Generated `struct` types will have derived implementations of the following
79/// traits: `Copy`, `Clone`, `Hash`, `PartialEq`, `Eq`, `PartialOrd`, and `Ord`.
80///
81/// The traits `Extend` and `FromIterator` are implemented for sequences of
82/// `Self` and `&Self`.
83///
84/// The `Debug` trait implementation will display the set of named flags contained
85/// in a set.
86///
87/// # Operators
88///
89/// The following operators are implemented for generated `struct` types:
90///
91/// * `BitOr` and `BitOrAssign` perform union
92/// * `BitAnd` and `BitAndAssign` perform intersection
93/// * `BitXor` and `BitXorAssign` perform toggle
94/// * `Sub` and `SubAssign` perform set difference
95/// * `Not` performs set complement
96///
97/// # Methods
98///
99/// The following methods are implemented for generated `struct` types:
100///
101/// * `fn from_bits(bits) -> Option<Self>` converts from underlying bits,
102/// checking that all bits correspond to defined flags.
103/// * `fn from_bits_truncate(bits) -> Option<Self>` converts from underlying bits,
104/// truncating any bits that do not correspond to defined flags.
105/// * `fn bits(&self) -> bits` returns the underlying bits
106/// * `fn contains(&self, other: Self) -> bool` returns whether the set
107/// contains all flags present in `other`
108/// * `fn clear(&mut self)` clears all flags on the set
109/// * `fn all() -> Self` returns all defined flags
110/// * `fn empty() -> Self` returns an empty set
111/// * `fn is_all(&self) -> bool` returns whether the set contains all flags
112/// * `fn is_empty(&self) -> bool` returns whether the set is empty
113/// * `fn intersects(&self, other: Self) -> bool` returns whether any flags
114/// are common between `self` and `other`.
115/// * `fn insert(&mut self, other: Self)` inserts all flags in `other`
116/// * `fn remove(&mut self, other: Self)` removes all flags in `other`
117/// * `fn toggle(&mut self, other: Self)` toggles all flags in `other`
118/// * `fn set(&mut self, other: Self, value: bool)` sets or removes all flags
119/// in `other`, depending on boolean `value`
120///
121/// Additionally, for each defined flag, a static method of signature
122/// `fn() -> Self` is defined, returning a set containing only the named flag.
123#[macro_export]
124macro_rules! new_bitflags {
125 ( $(#[$attr:meta])* pub flags $name:ident : $inner:ty
126 { $( $(#[$flag_attr:meta])* const $flag:ident = $value:expr ; )* } ) => {
127 #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
128 $(#[$attr])*
129 pub struct $name($inner);
130
131 new_bitflags!{ @_impl $name : $inner
132 { $( $(#[$flag_attr])* const $flag = $value ; )* } }
133 };
134 ( $(#[$attr:meta])* flags $name:ident : $inner:ty
135 { $( $(#[$flag_attr:meta])* const $flag:ident = $value:expr ; )* } ) => {
136 #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
137 $(#[$attr])*
138 struct $name($inner);
139
140 new_bitflags!{ @_impl $name : $inner
141 { $( $(#[$flag_attr])* const $flag = $value ; )* } }
142 };
143 ( @_impl $name:ident : $inner:ty
144 { $( $(#[$flag_attr:meta])* const $flag:ident = $value:expr ; )* } ) => {
145 #[allow(dead_code)]
146 impl $name {
147 /// Converts from a set of bits, only if all set bits correspond
148 /// to defined flags.
149 #[inline]
150 pub fn from_bits(bits: $inner) -> ::std::option::Option<$name> {
151 if (bits & !$name::all().bits()) == 0 {
152 Some($name(bits))
153 } else {
154 None
155 }
156 }
157
158 /// Converts from a set of bits, truncating any invalid bits.
159 #[inline]
160 pub fn from_bits_truncate(bits: $inner) -> $name {
161 $name(bits) & $name::all()
162 }
163
164 /// Returns the underlying bits.
165 #[inline]
166 pub fn bits(&self) -> $inner {
167 self.0
168 }
169
170 /// Returns whether the given flags are set in `self`.
171 #[inline]
172 pub fn contains(&self, flag: $name) -> bool {
173 *self & flag == flag
174 }
175
176 /// Zeroes all bits.
177 #[inline]
178 pub fn clear(&mut self) {
179 self.0 = 0;
180 }
181
182 /// Returns the set of all defined flags.
183 #[inline]
184 pub fn all() -> $name {
185 $name(0 $( | $value )*)
186 }
187
188 /// Returns an empty set.
189 #[inline]
190 pub fn empty() -> $name {
191 $name(0)
192 }
193
194 /// Returns whether all defined flags are set in `self`.
195 #[inline]
196 pub fn is_all(&self) -> bool {
197 self == $name::all()
198 }
199
200 /// Returns whether no defined flags are set in `self`.
201 #[inline]
202 pub fn is_empty(&self) -> bool {
203 self.bits() == 0
204 }
205
206 /// Returns whether any flags contained in `other` are also
207 /// contained in `self`.
208 #[inline]
209 pub fn intersects(&self, other: $name) -> bool {
210 !(*self & other).is_empty()
211 }
212
213 /// Inserts a set of flags in-place.
214 #[inline]
215 pub fn insert(&mut self, other: $name) {
216 self.0 |= other.0;
217 }
218
219 /// Removes a set of flags in-place.
220 #[inline]
221 pub fn remove(&mut self, other: $name) {
222 self.0 &= !other.0;
223 }
224
225 /// Toggles a set of flags in-place.
226 #[inline]
227 pub fn toggle(&mut self, other: $name) {
228 self.0 ^= other.0;
229 }
230
231 /// Inserts or removes the given set of flags.
232 #[inline]
233 pub fn set(&mut self, other: $name, value: bool) {
234 if value {
235 self.insert(other);
236 } else {
237 self.remove(other);
238 }
239 }
240
241 $( $(#[$flag_attr])*
242 #[inline]
243 pub fn $flag() -> $name {
244 $name($value)
245 } )*
246 }
247
248 impl ::std::fmt::Debug for $name {
249 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
250 let mut flags = *self;
251 let mut _first = true;
252
253 f.write_str(concat!(stringify!($name), "("))?;
254
255 $( if !$name::$flag().is_empty() && flags.contains($name::$flag()) {
256 if !_first {
257 f.write_str(" | ")?;
258 }
259 _first = false;
260
261 flags.remove($name::$flag());
262 f.write_str(stringify!($flag))?;
263 } )*
264
265 f.write_str(")")
266 }
267 }
268
269 impl ::std::iter::Extend<$name> for $name {
270 fn extend<I: ::std::iter::IntoIterator<Item=$name>>(&mut self, iter: I) {
271 for flag in iter {
272 self.insert(flag);
273 }
274 }
275 }
276
277 impl<'a> ::std::iter::Extend<&'a $name> for $name {
278 fn extend<I: ::std::iter::IntoIterator<Item=&'a $name>>(&mut self, iter: I) {
279 for flag in iter {
280 self.insert(*flag);
281 }
282 }
283 }
284
285 impl ::std::iter::FromIterator<$name> for $name {
286 fn from_iter<I: IntoIterator<Item=$name>>(iter: I) -> $name {
287 let mut flags = $name::empty();
288 flags.extend(iter);
289 flags
290 }
291 }
292
293 impl<'a> ::std::iter::FromIterator<&'a $name> for $name {
294 fn from_iter<I: IntoIterator<Item=&'a $name>>(iter: I) -> $name {
295 let mut flags = $name::empty();
296 flags.extend(iter);
297 flags
298 }
299 }
300
301 impl ::std::ops::BitOr for $name {
302 type Output = $name;
303
304 #[inline]
305 fn bitor(self, rhs: $name) -> $name {
306 $name(self.0 | rhs.0)
307 }
308 }
309
310 impl ::std::ops::BitOrAssign for $name {
311 #[inline]
312 fn bitor_assign(&mut self, rhs: $name) {
313 self.0 |= rhs.0;
314 }
315 }
316
317 impl ::std::ops::BitAnd for $name {
318 type Output = $name;
319
320 #[inline]
321 fn bitand(self, rhs: $name) -> $name {
322 $name(self.0 & rhs.0)
323 }
324 }
325
326 impl ::std::ops::BitAndAssign for $name {
327 #[inline]
328 fn bitand_assign(&mut self, rhs: $name) {
329 self.0 &= rhs.0;
330 }
331 }
332
333 impl ::std::ops::BitXor for $name {
334 type Output = $name;
335
336 #[inline]
337 fn bitxor(self, rhs: $name) -> $name {
338 $name(self.0 ^ rhs.0)
339 }
340 }
341
342 impl ::std::ops::BitXorAssign for $name {
343 #[inline]
344 fn bitxor_assign(&mut self, rhs: $name) {
345 self.0 ^= rhs.0;
346 }
347 }
348
349 impl ::std::ops::Not for $name {
350 type Output = $name;
351
352 #[inline]
353 fn not(self) -> $name {
354 self ^ $name::all()
355 }
356 }
357
358 impl ::std::ops::Sub for $name {
359 type Output = $name;
360
361 #[inline]
362 fn sub(mut self, rhs: $name) -> $name {
363 self.remove(rhs);
364 self
365 }
366 }
367
368 impl ::std::ops::SubAssign for $name {
369 #[inline]
370 fn sub_assign(&mut self, rhs: $name) {
371 self.remove(rhs);
372 }
373 }
374
375 impl<'a> PartialEq<&'a $name> for $name {
376 #[inline]
377 fn eq(&self, rhs: &&$name) -> bool { *self == **rhs }
378 #[inline]
379 fn ne(&self, rhs: &&$name) -> bool { *self != **rhs }
380 }
381
382 impl<'a> PartialEq<$name> for &'a $name {
383 #[inline]
384 fn eq(&self, rhs: &$name) -> bool { **self == *rhs }
385 #[inline]
386 fn ne(&self, rhs: &$name) -> bool { **self != *rhs }
387 }
388 }
389}