| 
 | 1 | +<!-- Copyright 2024 The Fuchsia Authors  | 
 | 2 | +
  | 
 | 3 | +Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0  | 
 | 4 | +<LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT  | 
 | 5 | +license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.  | 
 | 6 | +This file may not be copied, modified, or distributed except according to  | 
 | 7 | +those terms.  | 
 | 8 | +
  | 
 | 9 | +WARNING: DO NOT EDIT THIS FILE. It is generated automatically. Edits should be  | 
 | 10 | +made in the doc comment on `src/lib.rs` or in `tools/generate-readme`.  | 
 | 11 | +-->  | 
 | 12 | + | 
 | 13 | +# unsafe-fields  | 
 | 14 | + | 
 | 15 | +Support for unsafe fields.  | 
 | 16 | + | 
 | 17 | +This crate provides the `unsafe_fields!` macro, which can be used to mark  | 
 | 18 | +fields as unsafe. Unsafe fields automatically have their types wrapped using  | 
 | 19 | +the `Unsafe` wrapper type. An `Unsafe` is intended to be used to for  | 
 | 20 | +struct, enum, or union fields which carry safety invariants. All accessors  | 
 | 21 | +are `unsafe`, which requires any use of an `Unsafe` field to be inside an  | 
 | 22 | +`unsafe` block. One exception is `Unsafe::as_ref`, which is available when  | 
 | 23 | +the `zerocopy_0_8` feature is enabled. See its docs for more information.  | 
 | 24 | + | 
 | 25 | +An unsafe field has the type `Unsafe<O, F, const NAME_HASH: u128>`. `O` is  | 
 | 26 | +the enclosing type (struct, enum, or union), `F` is the type of the field,  | 
 | 27 | +and `NAME_HASH` is the hash of the field's name. `O` prevents swapping  | 
 | 28 | +unsafe fields of the same `F` type between different enclosing types, and  | 
 | 29 | +`NAME_HASH` prevents swapping different fields of the same `F` type within  | 
 | 30 | +the same enclosing type. Note that swapping the same field between instances  | 
 | 31 | +of the same type [cannot be prevented](crate#limitations).  | 
 | 32 | + | 
 | 33 | +[immutable]: zerocopy_0_8::Immutable  | 
 | 34 | + | 
 | 35 | +## Examples  | 
 | 36 | + | 
 | 37 | +```rust  | 
 | 38 | +use unsafe_fields::{unsafe_fields, Unsafe};  | 
 | 39 | + | 
 | 40 | +unsafe_fields! {  | 
 | 41 | +    /// A `usize` which is guaranteed to be even.  | 
 | 42 | +    pub struct EvenUsize {  | 
 | 43 | +        // INVARIANT: `n` is even.  | 
 | 44 | +        #[unsafe]  | 
 | 45 | +        n: usize,  | 
 | 46 | +    }  | 
 | 47 | +}  | 
 | 48 | + | 
 | 49 | +impl EvenUsize {  | 
 | 50 | +    /// Constructs a new `EvenUsize`.  | 
 | 51 | +    ///  | 
 | 52 | +    /// Returns `None` if `n` is odd.  | 
 | 53 | +    pub fn new(n: usize) -> Option<EvenUsize> {  | 
 | 54 | +        if n % 2 != 0 {  | 
 | 55 | +            return None;  | 
 | 56 | +        }  | 
 | 57 | +        // SAFETY: We just confirmed that `n` is even.  | 
 | 58 | +        let n = unsafe { Unsafe::new(n) };  | 
 | 59 | +        Some(EvenUsize { n })  | 
 | 60 | +    }  | 
 | 61 | +}  | 
 | 62 | +```  | 
 | 63 | + | 
 | 64 | +Attempting to swap unsafe fields of the same type is prevented:  | 
 | 65 | + | 
 | 66 | +```rust,compile_fail,E0308  | 
 | 67 | +use unsafe_fields::{unsafe_fields, Unsafe};  | 
 | 68 | +
  | 
 | 69 | +unsafe_fields! {  | 
 | 70 | +    /// A range.  | 
 | 71 | +    pub struct Range {  | 
 | 72 | +        // INVARIANT: `lo <= hi`.  | 
 | 73 | +        #[unsafe]  | 
 | 74 | +        lo: usize,  | 
 | 75 | +        #[unsafe]  | 
 | 76 | +        hi: usize,  | 
 | 77 | +    }  | 
 | 78 | +}  | 
 | 79 | +
  | 
 | 80 | +impl Range {  | 
 | 81 | +    pub fn swap(&mut self) {  | 
 | 82 | +        // ERROR: Mismatched types  | 
 | 83 | +        core::mem::swap(&mut self.lo, &mut self.hi);  | 
 | 84 | +    }  | 
 | 85 | +}  | 
 | 86 | +```  | 
 | 87 | + | 
 | 88 | +## Limitations  | 
 | 89 | + | 
 | 90 | +Note that we cannot prevent `Unsafe`s from being swapped between the same  | 
 | 91 | +field in instances of the same type:  | 
 | 92 | + | 
 | 93 | +```rust  | 
 | 94 | +use unsafe_fields::{unsafe_fields, Unsafe};  | 
 | 95 | + | 
 | 96 | +unsafe_fields! {  | 
 | 97 | +    /// A `usize` which is guaranteed to be even.  | 
 | 98 | +    pub struct EvenUsize {  | 
 | 99 | +        // INVARIANT: `n` is even.  | 
 | 100 | +        #[unsafe]  | 
 | 101 | +        n: usize,  | 
 | 102 | +    }  | 
 | 103 | +}  | 
 | 104 | + | 
 | 105 | +pub fn swap(a: &mut EvenUsize, b: &mut EvenUsize) {  | 
 | 106 | +    core::mem::swap(&mut a.n, &mut b.n);  | 
 | 107 | +}  | 
 | 108 | +```  | 
 | 109 | + | 
 | 110 | +## Disclaimer  | 
 | 111 | + | 
 | 112 | +Disclaimer: This is not an officially supported Google product.  | 
0 commit comments