aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2022-12-19 12:17:17 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-12-19 12:17:17 +0000
commit9713804664dbfecf14b1329382458f7a2d7a11f0 (patch)
tree579e9f3356eaf9c19b7f8ebb8619cdb44bc97aa8
parentf2b9410a8415c62a6214ae6e0e1c2806862d742c (diff)
parent6def8aef466810503607ee115fc36f5b56b518c0 (diff)
downloadmemoffset-main-16k-with-phones.tar.gz
Merge "Upgrade memoffset to 0.7.1"main-16k-with-phones
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--.github/workflows/ci.yml9
-rw-r--r--Android.bp4
-rw-r--r--Cargo.toml11
-rw-r--r--Cargo.toml.orig2
-rw-r--r--METADATA12
-rw-r--r--README.md4
-rwxr-xr-xci/miri.sh14
-rw-r--r--src/offset_of.rs74
-rw-r--r--src/raw_field.rs109
-rw-r--r--src/span_of.rs9
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
diff --git a/Android.bp b/Android.bp
index 5c7ee3a..e22342d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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,
diff --git a/Cargo.toml b/Cargo.toml
index 2874e31..1677446 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/METADATA b/METADATA
index 7b4d9f1..e30f02d 100644
--- a/METADATA
+++ b/METADATA
@@ -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
}
}
diff --git a/README.md b/README.md
index 9e93c2b..e297b33 100644
--- a/README.md
+++ b/README.md
@@ -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;