unsafe-fields 0.2.1

Make it unsafe to access or modify fields with safety invariants
Documentation
<!-- 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.