Skip to content

[unsafe-fields] Add README.md #1961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,4 @@ Zerocopy uses [GitHub Releases].

## Disclaimer

Disclaimer: Zerocopy is not an officially supported Google product.
Disclaimer: This is not an officially supported Google product.
4 changes: 3 additions & 1 deletion ci/check_readme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ set -eo pipefail
cargo install -q cargo-readme --version 3.2.0

diff <(cargo -q run --manifest-path tools/Cargo.toml -p generate-readme) README.md >&2
exit $?

cd unsafe-fields
diff <(cargo -q run --manifest-path ../tools/Cargo.toml -p generate-readme) README.md >&2
2 changes: 1 addition & 1 deletion tools/generate-readme/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ made in the doc comment on `src/lib.rs` or in `tools/generate-readme`.
const DISCLAIMER_FOOTER: &str = "\
## Disclaimer

Disclaimer: Zerocopy is not an officially supported Google product.\
Disclaimer: This is not an officially supported Google product.\
";

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion unsafe-fields/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

[package]
name = "unsafe-fields"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
description = "Make it unsafe to access or modify fields with safety invariants"
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
Expand Down
112 changes: 112 additions & 0 deletions unsafe-fields/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!-- Copyright 2024 The Fuchsia Authors

Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
This file may not be copied, modified, or distributed except according to
those terms.

WARNING: DO NOT EDIT THIS FILE. It is generated automatically. Edits should be
made in the doc comment on `src/lib.rs` or in `tools/generate-readme`.
-->

# unsafe-fields

Support for unsafe fields.

This crate provides the `unsafe_fields!` macro, which can be used to mark
fields as unsafe. Unsafe fields automatically have their types wrapped using
the `Unsafe` wrapper type. An `Unsafe` is intended to be used to for
struct, enum, or union fields which carry safety invariants. All accessors
are `unsafe`, which requires any use of an `Unsafe` field to be inside an
`unsafe` block. One exception is `Unsafe::as_ref`, which is available when
the `zerocopy_0_8` feature is enabled. See its docs for more information.

An unsafe field has the type `Unsafe<O, F, const NAME_HASH: u128>`. `O` is
the enclosing type (struct, enum, or union), `F` is the type of the field,
and `NAME_HASH` is the hash of the field's name. `O` prevents swapping
unsafe fields of the same `F` type between different enclosing types, and
`NAME_HASH` prevents swapping different fields of the same `F` type within
the same enclosing type. Note that swapping the same field between instances
of the same type [cannot be prevented](crate#limitations).

[immutable]: zerocopy_0_8::Immutable

## Examples

```rust
use unsafe_fields::{unsafe_fields, Unsafe};

unsafe_fields! {
/// A `usize` which is guaranteed to be even.
pub struct EvenUsize {
// INVARIANT: `n` is even.
#[unsafe]
n: usize,
}
}

impl EvenUsize {
/// Constructs a new `EvenUsize`.
///
/// Returns `None` if `n` is odd.
pub fn new(n: usize) -> Option<EvenUsize> {
if n % 2 != 0 {
return None;
}
// SAFETY: We just confirmed that `n` is even.
let n = unsafe { Unsafe::new(n) };
Some(EvenUsize { n })
}
}
```

Attempting to swap unsafe fields of the same type is prevented:

```rust,compile_fail,E0308
use unsafe_fields::{unsafe_fields, Unsafe};

unsafe_fields! {
/// A range.
pub struct Range {
// INVARIANT: `lo <= hi`.
#[unsafe]
lo: usize,
#[unsafe]
hi: usize,
}
}

impl Range {
pub fn swap(&mut self) {
// ERROR: Mismatched types
core::mem::swap(&mut self.lo, &mut self.hi);
}
}
```

## Limitations

Note that we cannot prevent `Unsafe`s from being swapped between the same
field in instances of the same type:

```rust
use unsafe_fields::{unsafe_fields, Unsafe};

unsafe_fields! {
/// A `usize` which is guaranteed to be even.
pub struct EvenUsize {
// INVARIANT: `n` is even.
#[unsafe]
n: usize,
}
}

pub fn swap(a: &mut EvenUsize, b: &mut EvenUsize) {
core::mem::swap(&mut a.n, &mut b.n);
}
```

## Disclaimer

Disclaimer: This is not an officially supported Google product.
11 changes: 8 additions & 3 deletions unsafe-fields/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
// This file may not be copied, modified, or distributed except according to
// those terms.

// After updating the following doc comment, make sure to run the following
// command to update `README.md` based on its contents:
//
// cargo -q run --manifest-path ../tools/Cargo.toml -p generate-readme > README.md

//! Support for unsafe fields.
//!
//! This crate provides the [`unsafe_fields!`] macro, which can be used to mark
Expand All @@ -28,7 +33,7 @@
//!
//! # Examples
//!
//! ```
//! ```rust
//! use unsafe_fields::{unsafe_fields, Unsafe};
//!
//! unsafe_fields! {
Expand Down Expand Up @@ -57,7 +62,7 @@
//!
//! Attempting to swap unsafe fields of the same type is prevented:
//!
//! ```compile_fail,E0308
//! ```rust,compile_fail,E0308
//! use unsafe_fields::{unsafe_fields, Unsafe};
//!
//! unsafe_fields! {
Expand All @@ -84,7 +89,7 @@
//! Note that we cannot prevent `Unsafe`s from being swapped between the same
//! field in instances of the same type:
//!
//! ```
//! ```rust
//! use unsafe_fields::{unsafe_fields, Unsafe};
//!
//! unsafe_fields! {
Expand Down