diff options
Diffstat (limited to 'vendor/memoffset/src/raw_field.rs')
-rw-r--r-- | vendor/memoffset/src/raw_field.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/vendor/memoffset/src/raw_field.rs b/vendor/memoffset/src/raw_field.rs index a8dd2b359..e16df9f28 100644 --- a/vendor/memoffset/src/raw_field.rs +++ b/vendor/memoffset/src/raw_field.rs @@ -39,6 +39,21 @@ macro_rules! _memoffset__addr_of { } /// Deref-coercion protection macro. +/// +/// Prevents complilation if the specified field name is not a part of the +/// struct definition. +/// +/// ```compile_fail +/// use memoffset::_memoffset__field_check; +/// +/// struct Foo { +/// foo: i32, +/// } +/// +/// type BoxedFoo = Box<Foo>; +/// +/// _memoffset__field_check!(BoxedFoo, foo); +/// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] @@ -64,6 +79,25 @@ macro_rules! _memoffset__field_check { } /// Deref-coercion protection macro. +/// +/// Prevents complilation if the specified type is not a tuple. +/// +/// ```compile_fail +/// use memoffset::_memoffset__field_check_tuple; +/// +/// _memoffset__field_check_tuple!(i32, 0); +/// ``` +#[cfg(allow_clippy)] +#[macro_export] +#[doc(hidden)] +macro_rules! _memoffset__field_check_tuple { + ($type:ty, $field:tt) => { + // Make sure the type argument is a tuple + #[allow(clippy::unneeded_wildcard_pattern)] + let (_, ..): $type; + }; +} +#[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_tuple { @@ -73,6 +107,53 @@ macro_rules! _memoffset__field_check_tuple { }; } +/// Deref-coercion protection macro for unions. +/// Unfortunately accepts single-field structs as well, which is not ideal, +/// but ultimately pretty harmless. +/// +/// ```compile_fail +/// use memoffset::_memoffset__field_check_union; +/// +/// union Foo { +/// variant_a: i32, +/// } +/// +/// type BoxedFoo = Box<Foo>; +/// +/// _memoffset__field_check_union!(BoxedFoo, variant_a); +/// ``` +#[cfg(allow_clippy)] +#[macro_export] +#[doc(hidden)] +macro_rules! _memoffset__field_check_union { + ($type:path, $field:tt) => { + // Make sure the field actually exists. This line ensures that a + // compile-time error is generated if $field is accessed through a + // Deref impl. + #[allow(clippy::unneeded_wildcard_pattern)] + // rustc1.19 requires unsafe here for the pattern; not needed in newer versions + #[allow(unused_unsafe)] + unsafe { + let $type { $field: _ }; + } + }; +} +#[cfg(not(allow_clippy))] +#[macro_export] +#[doc(hidden)] +macro_rules! _memoffset__field_check_union { + ($type:path, $field:tt) => { + // Make sure the field actually exists. This line ensures that a + // compile-time error is generated if $field is accessed through a + // Deref impl. + // rustc1.19 requires unsafe here for the pattern; not needed in newer versions + #[allow(unused_unsafe)] + unsafe { + let $type { $field: _ }; + } + }; +} + /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent type. /// @@ -115,3 +196,31 @@ macro_rules! raw_field_tuple { } }}; } + +/// Computes a const raw pointer to the given field of the given base pointer +/// to the given parent tuple typle. +/// +/// The `base` pointer *must not* be dangling, but it *may* point to +/// uninitialized memory. +/// +/// ## Note +/// This macro is the same as `raw_field`, except for a different Deref-coercion check that +/// supports unions. +/// Due to macro_rules limitations, this check will accept structs with a single field as well as unions. +/// This is not a stable guarantee, and future versions of this crate might fail +/// on any use of this macro with a struct, without a semver bump. +#[macro_export(local_inner_macros)] +macro_rules! raw_field_union { + ($base:expr, $parent:path, $field:tt) => {{ + _memoffset__field_check_union!($parent, $field); + let base = $base; // evaluate $base outside the `unsafe` block + + // Get the field address. + // Crucially, we know that this will not trigger a deref coercion because + // of the field check we did above. + #[allow(unused_unsafe)] // for when the macro is used in an unsafe block + unsafe { + _memoffset__addr_of!((*(base as *const $parent)).$field) + } + }}; +} |