1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
//! Macros for safe (and unsafe) access to and initialization of fields of structs wrapped in `MaybeUninit<_>` //! This crate uses the //! [`ptr::addr_of!`](core::ptr::addr_of) //! and [`ptr::addr_of_mut!`](core::ptr::addr_of_mut) //! macros introduced in Rust 1.51 to avoid undefined behavior. //! //! //! ## Examples //! ### Initialize a struct one field at a time //! ``` //! use core::mem::MaybeUninit; //! use project_uninit::partial_init; //! #[derive(PartialEq, Eq, Debug)] //! struct Inner { value1: u8, value2: (i32, bool) } //! #[derive(PartialEq, Eq, Debug)] //! struct MyStruct { name: &'static str, inner: Inner } //! //! let mut target = MaybeUninit::<MyStruct>::uninit(); //! //! let name: &mut &str = partial_init!(target => name = "Foo"); //! assert_eq!(*name, "Foo"); //! *name = "Bar"; //! //! let (value1, value2_0): (&mut u8, &mut i32) = partial_init!(target => { //! inner => value1: 0xff, //! inner => value2 => 0: 1000, //! }); //! assert_eq!(*value1, 0xff); //! assert_eq!(*value2_0, 1000); //! *value2_0 *= 2; //! //! let value2_1: &mut bool = partial_init!(target => inner => value2 => 1 = true); //! assert_eq!(*value2_1, true); //! //! assert_eq!(unsafe { target.assume_init() }, MyStruct { //! name: "Bar", //! inner: Inner { value1: 0xff, value2: (2000, true) }, //! }); //! ``` //! //! ### Obtain references to fields of a `MaybeUninit<_>` struct //! ``` //! # use core::mem::MaybeUninit; //! use project_uninit::project_uninit; //! //! #[derive(PartialEq, Eq, Debug)] //! struct Person { name: &'static str, age: u32 } //! let person = MaybeUninit::new(Person { //! name: "Alice", //! age: 22, //! }); //! let (name, age): (&MaybeUninit<&str>, &MaybeUninit<u32>) = project_uninit!( //! person => { name, age } //! ); //! //! assert_eq!(unsafe { name.assume_init() }, "Alice"); //! assert_eq!(unsafe { age.assume_init() }, 22); //! //! ``` //! //! ### Obtain mutable references to fields of a `MaybeUninit<_>` struct //! ``` //! # use core::mem::MaybeUninit; //! # #[derive(PartialEq, Eq, Debug)] //! # struct Person { name: &'static str, age: u32 } //! use project_uninit::project_uninit_mut; //! //! let mut person = MaybeUninit::new(Person { //! name: "Alice", //! age: 22, //! }); //! //! let (name, age): (&mut MaybeUninit<&str>, &mut MaybeUninit<u32>) = project_uninit_mut!( //! person => { name, age } //! ); //! //! *name = MaybeUninit::new("Alicia"); //! *age = MaybeUninit::new(24); //! //! assert_eq!(unsafe { person.assume_init() }, Person { //! name: "Alicia", //! age: 24, //! }); //! ``` //! ## Safety //! //! It's safe to mutably project multiple fields as long as they are distinct. //! For example, the following snippets do not compile: //! //! ```compile_fail //! # use core::mem::MaybeUninit; //! # #[derive(PartialEq, Eq, Debug)] //! # struct Person { name: &'static str, age: u32 } //! # use project_uninit::partial_init; //! let mut person = MaybeUninit::<Person>::uninit(); //! let (name1, name2) = partial_init!(person => { name: "Bob", name: "Robert" }); //! ``` //! //! ```compile_fail //! # use core::mem::MaybeUninit; //! # #[derive(PartialEq, Eq, Debug)] //! # struct Person { name: &'static str, age: u32 } //! # use project_uninit::project_uninit_mut; //! let mut person = MaybeUninit::<Person>::uninit(); //! let (name1, name2) = project_uninit_mut!(person => { name, name }); //! ``` //! //! ```compile_fail,E0499 //! # use core::mem::MaybeUninit; //! # #[derive(PartialEq, Eq, Debug)] //! # struct Person { name: &'static str, age: u32 } //! # use project_uninit::project_uninit_mut; //! let mut person = MaybeUninit::<Person>::uninit(); //! let name1 = project_uninit_mut!(person => name); //! let name2 = project_uninit_mut!(person => name); //! drop(name1); //! ``` //! //! Additionally, lifetime rules are enforced just like any other borrow. //! The following will not compile: //! ```compile_fail,E0597 //! # use core::mem::MaybeUninit; //! # #[derive(PartialEq, Eq, Debug)] //! # struct Person { name: &'static str, age: u32 } //! # use project_uninit::project_uninit; //! let age: &MaybeUninit<u32>; //! { //! let person = MaybeUninit::<Person>::uninit(); //! age = project_uninit!(person => age); //! } // person is dropped while still borrowed by age //! drop(age); //! ``` //! //! However, this will: //! ``` //! # use core::mem::MaybeUninit; //! # #[derive(PartialEq, Eq, Debug)] //! # struct Person { name: &'static str, age: u32 } //! # use project_uninit::project_uninit; //! fn get_uninit_age<'a>(person: &'a MaybeUninit<Person>) -> &'a MaybeUninit<u32> { //! project_uninit!(person => age) //! } //! ``` #![no_std] mod assert_unique; mod partial_init; mod project; #[doc(hidden)] pub mod utils;