Skip to main content

wgpu_types/
bitflags_array.rs

1macro_rules! bitflags_array_impl {
2        ($impl_name:ident $inner_name:ident $name:ident $op:tt $($struct_names:ident)*) => (
3            impl core::ops::$impl_name for $name {
4                type Output = Self;
5
6                #[inline]
7                fn $inner_name(self, other: Self) -> Self {
8                    Self {
9                        $($struct_names: self.$struct_names $op other.$struct_names,)*
10                    }
11                }
12            }
13        )
14    }
15pub(crate) use bitflags_array_impl;
16
17macro_rules! bitflags_array_impl_assign {
18        ($impl_name:ident $inner_name:ident $name:ident $op:tt $($struct_names:ident)*) => (
19            impl core::ops::$impl_name for $name {
20                #[inline]
21                fn $inner_name(&mut self, other: Self) {
22                    $(self.$struct_names $op other.$struct_names;)*
23                }
24            }
25        )
26    }
27pub(crate) use bitflags_array_impl_assign;
28
29macro_rules! bit_array_impl {
30        ($impl_name:ident $inner_name:ident $name:ident $op:tt) => (
31            impl core::ops::$impl_name for $name {
32                type Output = Self;
33
34                #[inline]
35                fn $inner_name(mut self, other: Self) -> Self {
36                    for (inner, other) in self.0.iter_mut().zip(other.0.iter()) {
37                        *inner $op *other;
38                    }
39                    self
40                }
41            }
42        )
43    }
44pub(crate) use bit_array_impl;
45
46macro_rules! bitflags_independent_two_arg {
47        ($(#[$meta:meta])* $func_name:ident $($struct_names:ident)*) => (
48            $(#[$meta])*
49            pub const fn $func_name(self, other:Self) -> Self {
50                Self { $($struct_names: self.$struct_names.$func_name(other.$struct_names),)* }
51            }
52        )
53    }
54pub(crate) use bitflags_independent_two_arg;
55
56// For the most part this macro should not be modified, most configuration should be possible
57// without changing this macro.
58/// Macro for creating sets of bitflags, we need this because there are almost more flags than bits
59/// in a u64, we can't use a u128 because of FFI, and the number of flags is increasing.
60///
61/// Alternatively we also want to separate WebGPU features from native WGPU features.
62macro_rules! bitflags_array {
63        (
64            $(#[$outer:meta])*
65            pub struct ($name:ident, $name_bits:ident): [$T:ty; $Len:expr];
66
67            $(
68                $(#[$bit_outer:meta])*
69                $vis:vis struct $inner_name:ident $lower_inner_name:ident {
70                    $(
71                        $(#[doc $($args:tt)*])*
72                        const $Flag:tt = $value:expr;
73                    )*
74                }
75            )*
76        ) => {
77            $(
78                bitflags::bitflags! {
79                    $(#[$bit_outer])*
80                    $vis struct $inner_name: $T {
81                        $(
82                            $(#[doc $($args)*])*
83                            const $Flag = $value;
84                        )*
85                    }
86                }
87            )*
88
89            $(#[$outer])*
90            pub struct $name {
91                $(
92                    #[allow(missing_docs)]
93                    $vis $lower_inner_name: $inner_name,
94                )*
95            }
96
97            #[doc = concat!("Bits from [`", stringify!($name), "`] in array form")]
98            #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
99            #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
100            pub struct $name_bits(pub [$T; $Len]);
101
102            $crate::bitflags_array_impl! { BitOr bitor $name | $($lower_inner_name)* }
103            $crate::bitflags_array_impl! { BitAnd bitand $name & $($lower_inner_name)* }
104            $crate::bitflags_array_impl! { BitXor bitxor $name ^ $($lower_inner_name)* }
105            impl core::ops::Not for $name {
106                type Output = Self;
107
108                #[inline]
109                fn not(self) -> Self {
110                    Self {
111                    $($lower_inner_name: !self.$lower_inner_name,)*
112                    }
113                }
114            }
115            $crate::bitflags_array_impl! { Sub sub $name - $($lower_inner_name)* }
116
117            #[cfg(feature = "serde")]
118            impl Serialize for $name {
119                fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120                where
121                    S: serde::Serializer,
122                {
123                    bitflags::serde::serialize(self, serializer)
124                }
125            }
126
127            #[cfg(feature = "serde")]
128            impl<'de> Deserialize<'de> for $name {
129                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
130                where
131                    D: serde::Deserializer<'de>,
132                {
133                    bitflags::serde::deserialize(deserializer)
134                }
135            }
136
137            impl core::fmt::Display for $name {
138                fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
139                    let mut iter = self.iter_names();
140                    // simple look ahead
141                    let mut next = iter.next();
142                    while let Some((name, _)) = next {
143                        f.write_str(name)?;
144                        next = iter.next();
145                        if next.is_some() {
146                            f.write_str(" | ")?;
147                        }
148                    }
149                    Ok(())
150                }
151            }
152
153            $crate::bitflags_array_impl_assign! { BitOrAssign bitor_assign $name |= $($lower_inner_name)* }
154            $crate::bitflags_array_impl_assign! { BitAndAssign bitand_assign $name &= $($lower_inner_name)* }
155            $crate::bitflags_array_impl_assign! { BitXorAssign bitxor_assign $name ^= $($lower_inner_name)* }
156
157            $crate::bit_array_impl! { BitOr bitor $name_bits |= }
158            $crate::bit_array_impl! { BitAnd bitand $name_bits &= }
159            $crate::bit_array_impl! { BitXor bitxor $name_bits ^= }
160
161            impl core::ops::Not for $name_bits {
162                type Output = Self;
163
164                #[inline]
165                fn not(self) -> Self {
166                    let [$($lower_inner_name,)*] = self.0;
167                    Self([$(!$lower_inner_name,)*])
168                }
169            }
170
171            #[cfg(feature = "serde")]
172            impl bitflags::parser::WriteHex for $name_bits {
173                fn write_hex<W: core::fmt::Write>(&self, mut writer: W) -> core::fmt::Result {
174                    let [$($lower_inner_name,)*] = self.0;
175                    let mut wrote = false;
176                    let mut stager = alloc::string::String::with_capacity(size_of::<$T>() * 2);
177                    // we don't want to write it if it's just zero as there may be multiple zeros
178                    // resulting in something like "00" being written out. We do want to write it if
179                    // there has already been something written though.
180                    $(if ($lower_inner_name != 0) || wrote {
181                        // First we write to a staging string, then we add any zeros (e.g if #1
182                        // is f and a u8 and #2 is a then the two combined would be f0a which requires
183                        // a 0 inserted)
184                        $lower_inner_name.write_hex(&mut stager)?;
185                        if (stager.len() != size_of::<$T>() * 2) && wrote {
186                            let zeros_to_write = (size_of::<$T>() * 2) - stager.len();
187                            for _ in 0..zeros_to_write {
188                                writer.write_char('0')?
189                            }
190                        }
191                        writer.write_str(&stager)?;
192                        stager.clear();
193                        wrote = true;
194                    })*
195                    if !wrote {
196                        writer.write_str("0")?;
197                    }
198                    Ok(())
199                }
200            }
201
202            #[cfg(feature = "serde")]
203            impl bitflags::parser::ParseHex for $name_bits {
204                fn parse_hex(input: &str) -> Result<Self, bitflags::parser::ParseError> {
205                    use bitflags::Bits;
206
207                    let mut unset = Self::EMPTY;
208                    let mut end = input.len();
209                    if end == 0 {
210                        return Err(bitflags::parser::ParseError::empty_flag())
211                    }
212                    // we iterate starting at the least significant places and going up
213                    for (idx, _) in [$(stringify!($lower_inner_name),)*].iter().enumerate().rev() {
214                        // A byte is two hex places - u8 (1 byte) = 0x00 (2 hex places).
215                        let checked_start = end.checked_sub(size_of::<$T>() * 2);
216                        let start = checked_start.unwrap_or(0);
217
218                        let cur_input = &input[start..end];
219                        unset.0[idx] = <$T>::from_str_radix(cur_input, 16)
220                            .map_err(|_|bitflags::parser::ParseError::invalid_hex_flag(cur_input))?;
221
222                        end = start;
223
224                        if let None = checked_start {
225                            break;
226                        }
227                    }
228                    Ok(unset)
229                }
230            }
231
232            impl bitflags::Bits for $name_bits {
233                const EMPTY: Self = $name::empty().bits();
234
235                const ALL: Self = $name::all().bits();
236            }
237
238            impl bitflags::Flags for $name {
239                const FLAGS: &'static [bitflags::Flag<Self>] = $name::FLAGS;
240
241                type Bits = $name_bits;
242
243                fn bits(&self) -> $name_bits {
244                    $name_bits([
245                        $(self.$lower_inner_name.bits(),)*
246                    ])
247                }
248
249                fn from_bits_retain(bits: $name_bits) -> Self {
250                    let [$($lower_inner_name,)*] = bits.0;
251                    Self {
252                        $($lower_inner_name: $inner_name::from_bits_retain($lower_inner_name),)*
253                    }
254                }
255
256                fn empty() -> Self {
257                    Self::empty()
258                }
259
260                fn all() -> Self {
261                    Self::all()
262                }
263            }
264
265            impl $name {
266                pub(crate) const FLAGS: &'static [bitflags::Flag<Self>] = &[
267                    $(
268                        $(
269                            bitflags::Flag::new(stringify!($Flag), $name::$Flag),
270                        )*
271                    )*
272                ];
273
274                /// Gets the set flags as a container holding an array of bits.
275                pub const fn bits(&self) -> $name_bits {
276                    $name_bits([
277                        $(self.$lower_inner_name.bits(),)*
278                    ])
279                }
280
281                /// Returns self with no flags set.
282                pub const fn empty() -> Self {
283                    Self {
284                        $($lower_inner_name: $inner_name::empty(),)*
285                    }
286                }
287
288                /// Returns self with all flags set.
289                pub const fn all() -> Self {
290                    Self {
291                        $($lower_inner_name: $inner_name::all(),)*
292                    }
293                }
294
295                /// Whether all the bits set in `other` are all set in `self`
296                pub const fn contains(self, other:Self) -> bool {
297                    // we need an annoying true to catch the last && >:(
298                    $(self.$lower_inner_name.contains(other.$lower_inner_name) &&)* true
299                }
300
301                /// Returns whether any bit set in `self` matched any bit set in `other`.
302                pub const fn intersects(self, other:Self) -> bool {
303                    $(self.$lower_inner_name.intersects(other.$lower_inner_name) ||)* false
304                }
305
306                /// Returns whether there is no flag set.
307                pub const fn is_empty(self) -> bool {
308                    $(self.$lower_inner_name.is_empty() &&)* true
309                }
310
311                /// Returns whether the struct has all flags set.
312                pub const fn is_all(self) -> bool {
313                    $(self.$lower_inner_name.is_all() &&)* true
314                }
315
316                $crate::bitflags_independent_two_arg! {
317                    /// Bitwise or - `self | other`
318                    union $($lower_inner_name)*
319                }
320
321                $crate::bitflags_independent_two_arg! {
322                    /// Bitwise and - `self & other`
323                    intersection $($lower_inner_name)*
324                }
325
326                $crate::bitflags_independent_two_arg! {
327                    /// Bitwise and of the complement of other - `self & !other`
328                    difference $($lower_inner_name)*
329                }
330
331                $crate::bitflags_independent_two_arg! {
332                    /// Bitwise xor - `self ^ other`
333                    symmetric_difference $($lower_inner_name)*
334                }
335
336                /// Bitwise not - `!self`
337                pub const fn complement(self) -> Self {
338                    Self {
339                        $($lower_inner_name: self.$lower_inner_name.complement(),)*
340                    }
341                }
342
343                /// Calls [`Self::insert`] if `set` is true and otherwise calls [`Self::remove`].
344                pub fn set(&mut self, other:Self, set: bool) {
345                    $(self.$lower_inner_name.set(other.$lower_inner_name, set);)*
346                }
347
348                /// Inserts specified flag(s) into self
349                pub fn insert(&mut self, other:Self) {
350                    $(self.$lower_inner_name.insert(other.$lower_inner_name);)*
351                }
352
353                /// Removes specified flag(s) from self
354                pub fn remove(&mut self, other:Self) {
355                    $(self.$lower_inner_name.remove(other.$lower_inner_name);)*
356                }
357
358                /// Toggles specified flag(s) in self
359                pub fn toggle(&mut self, other:Self) {
360                    $(self.$lower_inner_name.toggle(other.$lower_inner_name);)*
361                }
362
363                #[doc = concat!("Takes in [`", stringify!($name_bits), "`] and returns")]
364                /// None if there are invalid bits or otherwise Self with those bits set
365                pub const fn from_bits(bits: $name_bits) -> Option<Self> {
366                    let [$($lower_inner_name,)*] = bits.0;
367                    // The ? operator does not work in a const context.
368                    Some(Self {
369                        $(
370                            $lower_inner_name: match $inner_name::from_bits($lower_inner_name) {
371                                Some(some) => some,
372                                None => return None,
373                            },
374                        )*
375                    })
376                }
377
378                #[doc = concat!("Takes in [`", stringify!($name_bits), "`] and returns Self with only valid bits (all other bits removed)")]
379                pub const fn from_bits_truncate(bits: $name_bits) -> Self {
380                    let [$($lower_inner_name,)*] = bits.0;
381                    Self { $($lower_inner_name: $inner_name::from_bits_truncate($lower_inner_name),)* }
382                }
383
384                #[doc = concat!("Takes in [`", stringify!($name_bits), "`] and returns Self with all bits that were set without removing invalid bits")]
385                pub const fn from_bits_retain(bits: $name_bits) -> Self {
386                    let [$($lower_inner_name,)*] = bits.0;
387                    Self { $($lower_inner_name: $inner_name::from_bits_retain($lower_inner_name),)* }
388                }
389
390                /// Takes in a bitflags flag name (in `SCREAMING_SNAKE_CASE`) and returns Self
391                /// if it matches or none if the name does not match the name of any of the
392                /// flags. Name is capitalisation dependent.
393                ///
394                /// [`impl FromStr`] can be used to recognize kebab-case names, like are used in
395                /// the WebGPU spec.
396                pub fn from_name(name: &str) -> Option<Self> {
397                    match name {
398                        $(
399                            $(
400                                stringify!($Flag) => Some(Self::$Flag),
401                            )*
402                        )*
403                        _ => None,
404                    }
405                }
406
407                /// Combines the flags from the internal flags into the entire flags struct
408                pub fn from_internal_flags($($lower_inner_name: $inner_name,)*) -> Self {
409                    Self {
410                        $($lower_inner_name,)*
411                    }
412                }
413
414                /// Returns an iterator over the set flags.
415                pub const fn iter(&self) -> bitflags::iter::Iter<$name> {
416                    bitflags::iter::Iter::__private_const_new($name::FLAGS, *self, *self)
417                }
418
419                /// Returns an iterator over the set flags and their names.
420                ///
421                /// These are bitflags names in `SCREAMING_SNAKE_CASE`.
422                pub const fn iter_names(&self) -> bitflags::iter::IterNames<$name> {
423                    bitflags::iter::IterNames::__private_const_new($name::FLAGS, *self, *self)
424                }
425
426                $(
427                    $(
428                        $(#[doc $($args)*])*
429                        #[allow(clippy::needless_update, reason = "only useless if there is 1 member")]
430                        pub const $Flag: Self = Self {
431                            $lower_inner_name: $inner_name::from_bits_truncate($value),
432                            ..Self::empty()
433                        };
434                    )*
435                )*
436            }
437
438            $(
439                impl From<$inner_name> for $name {
440                    #[allow(clippy::needless_update, reason = "only useless if there is 1 member")]
441                    fn from($lower_inner_name: $inner_name) -> Self {
442                        Self {
443                            $lower_inner_name,
444                            ..Self::empty()
445                        }
446                    }
447                }
448            )*
449        };
450    }
451pub(crate) use bitflags_array;