# 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.