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;