From 967f85487f171b4b733b79be2a865392a8dc4cc1 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 9 Oct 2022 17:05:01 +0000 Subject: [PATCH] Add include_bytes! macro The `include_bytes!` macro is like the macro from `core` of the same name, except that it transmutes the file's contents to an arbitrary type (which implements `FromBytes`). Release 0.7.13. --- Cargo.toml | 8 +-- INTERNAL.md | 9 ++- src/lib.rs | 56 +++++++++++++++++++ testdata/include_value/data | 1 + tests/ui-msrv/include_value_not_from_bytes.rs | 1 + .../include_value_not_from_bytes.stderr | 12 ++++ tests/ui-msrv/include_value_wrong_size.rs | 1 + tests/ui-msrv/include_value_wrong_size.stderr | 9 +++ .../include_value_not_from_bytes.rs | 12 ++++ .../include_value_not_from_bytes.stderr | 22 ++++++++ tests/ui-nightly/include_value_wrong_size.rs | 11 ++++ .../include_value_wrong_size.stderr | 9 +++ .../ui-stable/include_value_not_from_bytes.rs | 1 + .../include_value_not_from_bytes.stderr | 22 ++++++++ tests/ui-stable/include_value_wrong_size.rs | 1 + .../ui-stable/include_value_wrong_size.stderr | 9 +++ zerocopy-derive/Cargo.toml | 2 +- 17 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 testdata/include_value/data create mode 120000 tests/ui-msrv/include_value_not_from_bytes.rs create mode 100644 tests/ui-msrv/include_value_not_from_bytes.stderr create mode 120000 tests/ui-msrv/include_value_wrong_size.rs create mode 100644 tests/ui-msrv/include_value_wrong_size.stderr create mode 100644 tests/ui-nightly/include_value_not_from_bytes.rs create mode 100644 tests/ui-nightly/include_value_not_from_bytes.stderr create mode 100644 tests/ui-nightly/include_value_wrong_size.rs create mode 100644 tests/ui-nightly/include_value_wrong_size.stderr create mode 120000 tests/ui-stable/include_value_not_from_bytes.rs create mode 100644 tests/ui-stable/include_value_not_from_bytes.stderr create mode 120000 tests/ui-stable/include_value_wrong_size.rs create mode 100644 tests/ui-stable/include_value_wrong_size.stderr diff --git a/Cargo.toml b/Cargo.toml index 326c0e9dfe..3e32f85483 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ [package] edition = "2021" name = "zerocopy" -version = "0.7.12" +version = "0.7.13" authors = ["Joshua Liebow-Feeser "] description = "Utilities for zero-copy parsing and serialization" license = "BSD-2-Clause" @@ -41,7 +41,7 @@ simd-nightly = ["simd"] __internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd"] [dependencies] -zerocopy-derive = { version = "=0.7.12", path = "zerocopy-derive", optional = true } +zerocopy-derive = { version = "=0.7.13", path = "zerocopy-derive", optional = true } [dependencies.byteorder] version = "1.3" @@ -52,7 +52,7 @@ optional = true # zerocopy-derive remain equal, even if the 'derive' feature isn't used. # See: https://github.com/matklad/macro-dep-test [target.'cfg(any())'.dependencies] -zerocopy-derive = { version = "=0.7.12", path = "zerocopy-derive" } +zerocopy-derive = { version = "=0.7.13", path = "zerocopy-derive" } [dev-dependencies] assert_matches = "1.5" @@ -67,4 +67,4 @@ testutil = { path = "testutil" } # CI test failures. trybuild = { version = "=1.0.85", features = ["diff"] } # In tests, unlike in production, zerocopy-derive is not optional -zerocopy-derive = { version = "=0.7.12", path = "zerocopy-derive" } +zerocopy-derive = { version = "=0.7.13", path = "zerocopy-derive" } diff --git a/INTERNAL.md b/INTERNAL.md index 4c9ed6a7ea..4b11c913c6 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -18,8 +18,11 @@ have a working Miri, so we need to pin to one that does (see https://rust-lang.github.io/rustup-components-history/). Updating the versions pinned in CI may cause the UI tests to break. In order to -fix UI tests after a version update, set the environment variable -`TRYBUILD=overwrite` while running `cargo test`. +fix UI tests after a version update, run: + +``` +$ TRYBUILD=overwrite ./cargo.sh +all test +``` ## Crate versions @@ -30,4 +33,4 @@ when published on crates.io, both crates effectively constitute a single atomic version. So long as the code in zerocopy is compatible with the code in zerocopy-derive in the same Git commit, then publishing them both is fine. This frees us from the normal task of reasoning about compatibility with a range of -semver-compatible versions of different crates. \ No newline at end of file +semver-compatible versions of different crates. diff --git a/src/lib.rs b/src/lib.rs index 11ff6387d8..507204674f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2069,6 +2069,54 @@ macro_rules! transmute_ref { }} } +/// Includes a file and safely transmutes it to a value of an arbitrary type. +/// +/// The file will be included as a byte array, `[u8; N]`, which will be +/// transmuted to another type, `T`. `T` is inferred from the calling context, +/// and must implement [`FromBytes`]. +/// +/// The file is located relative to the current file (similarly to how modules +/// are found). The provided path is interpreted in a platform-specific way at +/// compile time. So, for instance, an invocation with a Windows path containing +/// backslashes `\` would not compile correctly on Unix. +/// +/// `include_bytes!` is ignorant of byte order. For byte order-aware types, see +/// the [`byteorder`] module. +/// +/// # Examples +/// +/// Assume there are two files in the same directory with the following +/// contents: +/// +/// File 'data' (no trailing newline): +/// +/// ```text +/// abcd +/// ``` +/// +/// File 'main.rs': +/// +/// ```rust +/// use zerocopy::include_value; +/// # macro_rules! include_value { +/// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) }; +/// # } +/// +/// fn main() { +/// let as_u32: u32 = include_value!("data"); +/// assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); +/// let as_i32: i32 = include_value!("data"); +/// assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); +/// } +/// ``` +#[doc(alias("include_bytes", "include_data", "include_type"))] +#[macro_export] +macro_rules! include_value { + ($file:expr $(,)?) => { + $crate::transmute!(*::core::include_bytes!($file)) + }; +} + /// A typed reference derived from a byte slice. /// /// A `Ref` is a reference to a `T` which is stored in a byte slice, `B`. @@ -4250,6 +4298,14 @@ mod tests { assert_eq!(ctr, 1); } + #[test] + fn test_include_value() { + const AS_U32: u32 = include_value!("../testdata/include_value/data"); + assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); + const AS_I32: i32 = include_value!("../testdata/include_value/data"); + assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); + } + #[test] fn test_address() { // Test that the `Deref` and `DerefMut` implementations return a diff --git a/testdata/include_value/data b/testdata/include_value/data new file mode 100644 index 0000000000..85df50785d --- /dev/null +++ b/testdata/include_value/data @@ -0,0 +1 @@ +abcd \ No newline at end of file diff --git a/tests/ui-msrv/include_value_not_from_bytes.rs b/tests/ui-msrv/include_value_not_from_bytes.rs new file mode 120000 index 0000000000..ff7b199d4e --- /dev/null +++ b/tests/ui-msrv/include_value_not_from_bytes.rs @@ -0,0 +1 @@ +../ui-nightly/include_value_not_from_bytes.rs \ No newline at end of file diff --git a/tests/ui-msrv/include_value_not_from_bytes.stderr b/tests/ui-msrv/include_value_not_from_bytes.stderr new file mode 100644 index 0000000000..746a0fa1b8 --- /dev/null +++ b/tests/ui-msrv/include_value_not_from_bytes.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `UnsafeCell: FromBytes` is not satisfied + --> tests/ui-msrv/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `UnsafeCell` + | +note: required by a bound in `NOT_FROM_BYTES::transmute` + --> tests/ui-msrv/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `NOT_FROM_BYTES::transmute` + = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/include_value_wrong_size.rs b/tests/ui-msrv/include_value_wrong_size.rs new file mode 120000 index 0000000000..3752cf747e --- /dev/null +++ b/tests/ui-msrv/include_value_wrong_size.rs @@ -0,0 +1 @@ +../ui-nightly/include_value_wrong_size.rs \ No newline at end of file diff --git a/tests/ui-msrv/include_value_wrong_size.stderr b/tests/ui-msrv/include_value_wrong_size.stderr new file mode 100644 index 0000000000..30045849d7 --- /dev/null +++ b/tests/ui-msrv/include_value_wrong_size.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/include_value_wrong_size.rs:11:25 + | +11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/include_value_not_from_bytes.rs b/tests/ui-nightly/include_value_not_from_bytes.rs new file mode 100644 index 0000000000..45b6138f47 --- /dev/null +++ b/tests/ui-nightly/include_value_not_from_bytes.rs @@ -0,0 +1,12 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because `UnsafeCell: !FromBytes`. +const NOT_FROM_BYTES: core::cell::UnsafeCell = + include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-nightly/include_value_not_from_bytes.stderr b/tests/ui-nightly/include_value_not_from_bytes.stderr new file mode 100644 index 0000000000..ae3a123cec --- /dev/null +++ b/tests/ui-nightly/include_value_not_from_bytes.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `UnsafeCell: FromBytes` is not satisfied + --> tests/ui-nightly/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `UnsafeCell` + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `NOT_FROM_BYTES::transmute` + --> tests/ui-nightly/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/include_value_wrong_size.rs b/tests/ui-nightly/include_value_wrong_size.rs new file mode 100644 index 0000000000..d87b30698b --- /dev/null +++ b/tests/ui-nightly/include_value_wrong_size.rs @@ -0,0 +1,11 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-nightly/include_value_wrong_size.stderr b/tests/ui-nightly/include_value_wrong_size.stderr new file mode 100644 index 0000000000..f592ece1de --- /dev/null +++ b/tests/ui-nightly/include_value_wrong_size.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/include_value_wrong_size.rs:11:25 + | +11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/include_value_not_from_bytes.rs b/tests/ui-stable/include_value_not_from_bytes.rs new file mode 120000 index 0000000000..ff7b199d4e --- /dev/null +++ b/tests/ui-stable/include_value_not_from_bytes.rs @@ -0,0 +1 @@ +../ui-nightly/include_value_not_from_bytes.rs \ No newline at end of file diff --git a/tests/ui-stable/include_value_not_from_bytes.stderr b/tests/ui-stable/include_value_not_from_bytes.stderr new file mode 100644 index 0000000000..3eedf723b7 --- /dev/null +++ b/tests/ui-stable/include_value_not_from_bytes.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `UnsafeCell: FromBytes` is not satisfied + --> tests/ui-stable/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `UnsafeCell` + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `NOT_FROM_BYTES::transmute` + --> tests/ui-stable/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/include_value_wrong_size.rs b/tests/ui-stable/include_value_wrong_size.rs new file mode 120000 index 0000000000..3752cf747e --- /dev/null +++ b/tests/ui-stable/include_value_wrong_size.rs @@ -0,0 +1 @@ +../ui-nightly/include_value_wrong_size.rs \ No newline at end of file diff --git a/tests/ui-stable/include_value_wrong_size.stderr b/tests/ui-stable/include_value_wrong_size.stderr new file mode 100644 index 0000000000..956d74c505 --- /dev/null +++ b/tests/ui-stable/include_value_wrong_size.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/include_value_wrong_size.rs:11:25 + | +11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/Cargo.toml b/zerocopy-derive/Cargo.toml index 5f0e91d028..dade04190a 100644 --- a/zerocopy-derive/Cargo.toml +++ b/zerocopy-derive/Cargo.toml @@ -5,7 +5,7 @@ [package] edition = "2021" name = "zerocopy-derive" -version = "0.7.12" +version = "0.7.13" authors = ["Joshua Liebow-Feeser "] description = "Custom derive for traits from the zerocopy crate" license = "BSD-2-Clause"