Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 1 | //! Generate the internal `bitflags`-facing flags type. |
| 2 | //! |
| 3 | //! The code generated here is owned by `bitflags`, but still part of its public API. |
| 4 | //! Changes to the types generated here need to be considered like any other public API change. |
| 5 | |
| 6 | /// Declare the `bitflags`-facing bitflags struct. |
| 7 | /// |
| 8 | /// This type is part of the `bitflags` crate's public API, but not part of the user's. |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 9 | #[macro_export] |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 10 | #[doc(hidden)] |
| 11 | macro_rules! __declare_internal_bitflags { |
| 12 | ( |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 13 | $vis:vis struct $InternalBitFlags:ident: $T:ty |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 14 | ) => { |
| 15 | // NOTE: The ABI of this type is _guaranteed_ to be the same as `T` |
| 16 | // This is relied on by some external libraries like `bytemuck` to make |
| 17 | // its `unsafe` trait impls sound. |
| 18 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| 19 | #[repr(transparent)] |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 20 | $vis struct $InternalBitFlags($T); |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 21 | }; |
| 22 | } |
| 23 | |
| 24 | /// Implement functions on the private (bitflags-facing) bitflags type. |
| 25 | /// |
| 26 | /// Methods and trait implementations can be freely added here without breaking end-users. |
| 27 | /// If we want to expose new functionality to `#[derive]`, this is the place to do it. |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 28 | #[macro_export] |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 29 | #[doc(hidden)] |
| 30 | macro_rules! __impl_internal_bitflags { |
| 31 | ( |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 32 | $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident { |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 33 | $( |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 34 | $(#[$inner:ident $($args:tt)*])* |
| 35 | const $Flag:tt = $value:expr; |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 36 | )* |
| 37 | } |
| 38 | ) => { |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 39 | // NOTE: This impl is also used to prevent using bits types from non-primitive types |
| 40 | // in the `bitflags` macro. If this approach is changed, this guard will need to be |
| 41 | // retained somehow |
| 42 | impl $crate::__private::PublicFlags for $PublicBitFlags { |
| 43 | type Primitive = $T; |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 44 | type Internal = $InternalBitFlags; |
| 45 | } |
| 46 | |
| 47 | impl $crate::__private::core::default::Default for $InternalBitFlags { |
| 48 | #[inline] |
| 49 | fn default() -> Self { |
| 50 | $InternalBitFlags::empty() |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | impl $crate::__private::core::fmt::Debug for $InternalBitFlags { |
| 55 | fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter<'_>) -> $crate::__private::core::fmt::Result { |
| 56 | if self.is_empty() { |
| 57 | // If no flags are set then write an empty hex flag to avoid |
| 58 | // writing an empty string. In some contexts, like serialization, |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 59 | // an empty string is preferable, but it may be unexpected in |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 60 | // others for a format not to produce any output. |
| 61 | // |
| 62 | // We can remove this `0x0` and remain compatible with `FromStr`, |
| 63 | // because an empty string will still parse to an empty set of flags, |
| 64 | // just like `0x0` does. |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 65 | $crate::__private::core::write!(f, "{:#x}", <$T as $crate::Bits>::EMPTY) |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 66 | } else { |
| 67 | $crate::__private::core::fmt::Display::fmt(self, f) |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | impl $crate::__private::core::fmt::Display for $InternalBitFlags { |
| 73 | fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter<'_>) -> $crate::__private::core::fmt::Result { |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 74 | $crate::parser::to_writer(&$PublicBitFlags(*self), f) |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 75 | } |
| 76 | } |
| 77 | |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 78 | impl $crate::__private::core::str::FromStr for $InternalBitFlags { |
| 79 | type Err = $crate::parser::ParseError; |
| 80 | |
| 81 | fn from_str(s: &str) -> $crate::__private::core::result::Result<Self, Self::Err> { |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 82 | $crate::parser::from_str::<$PublicBitFlags>(s).map(|flags| flags.0) |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 83 | } |
| 84 | } |
| 85 | |
| 86 | impl $crate::__private::core::convert::AsRef<$T> for $InternalBitFlags { |
| 87 | fn as_ref(&self) -> &$T { |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 88 | &self.0 |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | |
| 92 | impl $crate::__private::core::convert::From<$T> for $InternalBitFlags { |
| 93 | fn from(bits: $T) -> Self { |
| 94 | Self::from_bits_retain(bits) |
| 95 | } |
| 96 | } |
| 97 | |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 98 | // The internal flags type offers a similar API to the public one |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 99 | |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 100 | $crate::__impl_public_bitflags! { |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 101 | $InternalBitFlags: $T, $PublicBitFlags { |
| 102 | $( |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 103 | $(#[$inner $($args)*])* |
| 104 | const $Flag = $value; |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 105 | )* |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 106 | } |
| 107 | } |
| 108 | |
Stephen Hines | 5fc2b79 | 2024-02-21 12:13:08 -0800 | [diff] [blame] | 109 | $crate::__impl_public_bitflags_ops! { |
| 110 | $InternalBitFlags |
| 111 | } |
| 112 | |
| 113 | $crate::__impl_public_bitflags_iter! { |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 114 | $InternalBitFlags: $T, $PublicBitFlags |
| 115 | } |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 116 | |
Andrew Walbran | ff6563b | 2023-06-13 10:21:55 +0000 | [diff] [blame] | 117 | impl $InternalBitFlags { |
| 118 | /// Returns a mutable reference to the raw value of the flags currently stored. |
| 119 | #[inline] |
| 120 | pub fn bits_mut(&mut self) -> &mut $T { |
| 121 | &mut self.0 |
Jakob Vukalovic | fa6723a | 2023-04-26 10:38:55 +0100 | [diff] [blame] | 122 | } |
| 123 | } |
| 124 | }; |
| 125 | } |