Skip to content

Commit

Permalink
Add include_bytes! macro (#35)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
joshlf committed Oct 24, 2023
1 parent 7e80f7d commit db245f1
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 8 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[package]
edition = "2021"
name = "zerocopy"
version = "0.7.12"
version = "0.7.13"
authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
description = "Utilities for zero-copy parsing and serialization"
license = "BSD-2-Clause"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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" }
9 changes: 6 additions & 3 deletions INTERNAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
semver-compatible versions of different crates.
56 changes: 56 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<B, T>` is a reference to a `T` which is stored in a byte slice, `B`.
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions testdata/include_value/data
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abcd
1 change: 1 addition & 0 deletions tests/ui-msrv/include_value_not_from_bytes.rs
12 changes: 12 additions & 0 deletions tests/ui-msrv/include_value_not_from_bytes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0277]: the trait bound `UnsafeCell<u32>: 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<u32>`
|
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)
1 change: 1 addition & 0 deletions tests/ui-msrv/include_value_wrong_size.rs
9 changes: 9 additions & 0 deletions tests/ui-msrv/include_value_wrong_size.stderr
Original file line number Diff line number Diff line change
@@ -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)
12 changes: 12 additions & 0 deletions tests/ui-nightly/include_value_not_from_bytes.rs
Original file line number Diff line number Diff line change
@@ -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<u32>: !FromBytes`.
const NOT_FROM_BYTES: core::cell::UnsafeCell<u32> =
include_value!("../../testdata/include_value/data");
22 changes: 22 additions & 0 deletions tests/ui-nightly/include_value_not_from_bytes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0277]: the trait bound `UnsafeCell<u32>: 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<u32>`
|
= 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)
11 changes: 11 additions & 0 deletions tests/ui-nightly/include_value_wrong_size.rs
Original file line number Diff line number Diff line change
@@ -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");
9 changes: 9 additions & 0 deletions tests/ui-nightly/include_value_wrong_size.stderr
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions tests/ui-stable/include_value_not_from_bytes.rs
22 changes: 22 additions & 0 deletions tests/ui-stable/include_value_not_from_bytes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0277]: the trait bound `UnsafeCell<u32>: 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<u32>`
|
= 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)
1 change: 1 addition & 0 deletions tests/ui-stable/include_value_wrong_size.rs
9 changes: 9 additions & 0 deletions tests/ui-stable/include_value_wrong_size.stderr
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 1 addition & 1 deletion zerocopy-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[package]
edition = "2021"
name = "zerocopy-derive"
version = "0.7.12"
version = "0.7.13"
authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
description = "Custom derive for traits from the zerocopy crate"
license = "BSD-2-Clause"
Expand Down

0 comments on commit db245f1

Please sign in to comment.