diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-12-19 12:17:17 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-12-19 12:17:17 +0000 |
commit | 9713804664dbfecf14b1329382458f7a2d7a11f0 (patch) | |
tree | 579e9f3356eaf9c19b7f8ebb8619cdb44bc97aa8 | |
parent | f2b9410a8415c62a6214ae6e0e1c2806862d742c (diff) | |
parent | 6def8aef466810503607ee115fc36f5b56b518c0 (diff) | |
download | memoffset-main-16k-with-phones.tar.gz |
Merge "Upgrade memoffset to 0.7.1"main-16k-with-phones
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | .github/workflows/ci.yml | 9 | ||||
-rw-r--r-- | Android.bp | 4 | ||||
-rw-r--r-- | Cargo.toml | 11 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 12 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rwxr-xr-x | ci/miri.sh | 14 | ||||
-rw-r--r-- | src/offset_of.rs | 74 | ||||
-rw-r--r-- | src/raw_field.rs | 109 | ||||
-rw-r--r-- | src/span_of.rs | 9 |
11 files changed, 225 insertions, 30 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index b737620..057a882 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,6 @@ { "git": { - "sha1": "01e2e42ef0d833682c27b0f40a2cc748d86b2dc3" - } -} + "sha1": "d8accb76712984e2ab069193f392e5a7b6c5e78c" + }, + "path_in_vcs": "" +}
\ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97fcf98..ea6b607 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,8 +67,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Install Miri + run: | + rustup toolchain install nightly --component miri + rustup override set nightly + cargo miri setup - name: Test with Miri - run: ci/miri.sh + run: | + cargo miri test + cargo miri test --all-features style: name: lints and formatting @@ -23,7 +23,7 @@ rust_library { host_supported: true, crate_name: "memoffset", cargo_env_compat: true, - cargo_pkg_version: "0.6.5", + cargo_pkg_version: "0.7.1", srcs: ["src/lib.rs"], edition: "2015", features: ["default"], @@ -49,7 +49,7 @@ rust_test { host_supported: true, crate_name: "memoffset", cargo_env_compat: true, - cargo_pkg_version: "0.6.5", + cargo_pkg_version: "0.7.1", srcs: ["src/lib.rs"], test_suites: ["general-tests"], auto_gen_config: true, @@ -11,16 +11,23 @@ [package] name = "memoffset" -version = "0.6.5" +version = "0.7.1" authors = ["Gilad Naaman <gilad.naaman@gmail.com>"] description = "offset_of functionality for Rust structs." readme = "README.md" -keywords = ["mem", "offset", "offset_of", "offsetof"] +keywords = [ + "mem", + "offset", + "offset_of", + "offsetof", +] categories = ["no-std"] license = "MIT" repository = "https://github.com/Gilnaa/memoffset" + [dev-dependencies.doc-comment] version = "0.3" + [build-dependencies.autocfg] version = "1" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 7a62858..90620e2 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "memoffset" -version = "0.6.5" +version = "0.7.1" authors = ["Gilad Naaman <gilad.naaman@gmail.com>"] description = "offset_of functionality for Rust structs." license = "MIT" @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/memoffset +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "memoffset" description: "offset_of functionality for Rust structs." third_party { @@ -7,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/memoffset/memoffset-0.6.5.crate" + value: "https://static.crates.io/crates/memoffset/memoffset-0.7.1.crate" } - version: "0.6.5" + version: "0.7.1" license_type: NOTICE last_upgrade_date { year: 2022 - month: 3 - day: 1 + month: 12 + day: 12 } } @@ -16,7 +16,7 @@ Add the following dependency to your `Cargo.toml`: ```toml [dependencies] -memoffset = "0.6" +memoffset = "0.7" ``` These versions will compile fine with rustc versions greater or equal to 1.19. @@ -55,7 +55,7 @@ In order to use it, you must enable the `unstable_const` crate feature and sever Cargo.toml: ```toml [dependencies.memoffset] -version = "0.6" +version = "0.7" features = ["unstable_const"] ``` diff --git a/ci/miri.sh b/ci/miri.sh deleted file mode 100755 index 5aea2ec..0000000 --- a/ci/miri.sh +++ /dev/null @@ -1,14 +0,0 @@ -set -ex - -# Install Miri. -MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) -echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" -rustup default "$MIRI_NIGHTLY" -rustup component add miri - -# Run tests. -cargo miri test -cargo miri test --all-features - -# Restore old state in case Travis uses this cache for other jobs. -rustup default nightly diff --git a/src/offset_of.rs b/src/offset_of.rs index 8596e45..d070181 100644 --- a/src/offset_of.rs +++ b/src/offset_of.rs @@ -86,6 +86,16 @@ macro_rules! _memoffset_offset_from_unsafe { /// assert_eq!(offset_of!(Foo, b), 4); /// } /// ``` +/// +/// ## Notes +/// Rust's ABI is unstable, and [type layout can be changed with each +/// compilation](https://doc.rust-lang.org/reference/type-layout.html). +/// +/// Using `offset_of!` with a `repr(Rust)` struct will return the correct offset of the +/// specified `field` for a particular compilation, but the exact value may change +/// based on the compiler version, concrete struct type, time of day, or rustc's mood. +/// +/// As a result, the value should not be retained and used between different compilations. #[macro_export(local_inner_macros)] macro_rules! offset_of { ($parent:path, $field:tt) => {{ @@ -121,6 +131,39 @@ macro_rules! offset_of_tuple { }}; } +/// Calculates the offset of the specified union member from the start of the union. +/// +/// ## Examples +/// ``` +/// use memoffset::offset_of_union; +/// +/// #[repr(C, packed)] +/// union Foo { +/// foo32: i32, +/// foo64: i64, +/// } +/// +/// fn main() { +/// assert!(offset_of_union!(Foo, foo64) == 0); +/// } +/// ``` +/// +/// ## Note +/// Due to macro_rules limitations, this macro 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! offset_of_union { + ($parent:path, $field:tt) => {{ + // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). + _memoffset__let_base_ptr!(base_ptr, $parent); + // Get field pointer. + let field_ptr = raw_field_union!(base_ptr, $parent, $field); + // Compute offset. + _memoffset_offset_from_unsafe!(field_ptr, base_ptr) + }}; +} + #[cfg(test)] mod tests { #[test] @@ -162,6 +205,21 @@ mod tests { } #[test] + fn offset_union() { + // Since we're specifying repr(C), all fields are supposed to be at offset 0 + #[repr(C)] + union Foo { + a: u32, + b: [u8; 2], + c: i64, + } + + assert_eq!(offset_of_union!(Foo, a), 0); + assert_eq!(offset_of_union!(Foo, b), 0); + assert_eq!(offset_of_union!(Foo, c), 0); + } + + #[test] fn path() { mod sub { #[repr(C)] @@ -238,6 +296,22 @@ mod tests { ); } + #[test] + fn test_raw_field_union() { + #[repr(C)] + union Foo { + a: u32, + b: [u8; 2], + c: i64, + } + + let f = Foo { a: 0 }; + let f_ptr = &f as *const _; + assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, a) as usize); + assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, b) as usize); + assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, c) as usize); + } + #[cfg(feature = "unstable_const")] #[test] fn const_offset() { diff --git a/src/raw_field.rs b/src/raw_field.rs index a8dd2b3..e16df9f 100644 --- a/src/raw_field.rs +++ b/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) + } + }}; +} diff --git a/src/span_of.rs b/src/span_of.rs index a3663d5..c2030b7 100644 --- a/src/span_of.rs +++ b/src/span_of.rs @@ -52,11 +52,18 @@ macro_rules! _memoffset__compile_error { /// span_of!(Struct, start ..) /// ``` /// -/// *Note*: +/// ### Note /// This macro uses recursion in order to resolve the range expressions, so there is a limit to /// the complexity of the expression. /// In order to raise the limit, the compiler's recursion limit should be lifted. /// +/// ### Safety +/// The inter-field form mentioned above assumes that the first field is positioned before the +/// second. +/// This is only guarenteed for `repr(C)` structs. +/// Usage with `repr(Rust)` structs may yield unexpected results, like downward-going ranges, +/// spans that include unexpected fields, empty spans, or spans that include *unexpected* padding bytes. +/// /// ## Examples /// ``` /// use memoffset::span_of; |