Skip to content

Commit

Permalink
[unsafe-fields] Add README.md
Browse files Browse the repository at this point in the history
Makes progress on #1931

gherrit-pr-id: Icc9b6841e66c961989862ff6fb3b4f5140c54513
  • Loading branch information
joshlf committed Oct 22, 2024
1 parent 34f4e6e commit bf8f034
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 2 deletions.
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 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:

```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: Zerocopy is not an officially supported Google product.
5 changes: 5 additions & 0 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 Down

0 comments on commit bf8f034

Please sign in to comment.