Macro project_uninit::partial_init[][src]

macro_rules! partial_init {
    ($expr:expr => {$($($props:tt)=>+ : $val:expr),* $(,)?}) => { ... };
    ($expr:expr => $($props:tt)=>+ = $val:expr) => { ... };
}

Partially initialize a struct wrapped in MaybeUninit.

The specified fields will be updated with the given values, and mutable references to those fields will be returned. This statically ensures that the same field is not set mutltiple times in the same macro call, and that multiple references to the same value are not returned.

This must be used in an unsafe block or function when accessing fields of unions.

Syntax

// Initialize a single field:
let age: &mut u32 = partial_init!(bob => age = 35);
assert_eq!(*age, 35);

// Initialize multiple fields:
let (age, id) = partial_init!(bob => {
    age: 36,
    id: (111, 222),
});
assert_eq!(*age, 36);
assert_eq!(*id, (111, 222));

// Initialize fields of fields:
let first: &mut &'static str = partial_init!(bob => name => first = "Bob");
assert_eq!(*first, "Bob");

// Initialize fields of tuples (also works for tuple structs):
let id0: &mut usize = partial_init!(bob => id => 0 = 444);
assert_eq!(*id0, 444);

// Initialize multiple fields, including nested fields:
let (last, age, id1) = partial_init!(bob => {
    name => last: "Jones",
    age: 37,
    id => 1: 888,
});

assert_eq!(*last, "Jones");
assert_eq!(*age, 37);
assert_eq!(*id1, 888);

Example

use core::mem::MaybeUninit;
use project_uninit::partial_init;

#[derive(PartialEq, Eq, Debug)]
struct Person { name: Name, age: u32, id: (usize, usize) }
#[derive(PartialEq, Eq, Debug)]
struct Name { first: &'static str, last: &'static str }

let mut alice = MaybeUninit::<Person>::uninit();

let age = partial_init!(alice => age = 20);
assert_eq!(*age, 20);
*age = 22;

let (first, last, id) = partial_init!(alice => {
    name => first: "Alice",
    name => last: "Smith",
    id: (123, 456),
});
assert_eq!(*first, "Alice");
assert_eq!(*last, "Smith");
assert_eq!(*id, (123, 456));

partial_init!(alice => id => 1 = 789);

assert_eq!(unsafe { alice.assume_init() }, Person {
    name: Name { first: "Alice", last: "Smith" },
    age: 22,
    id: (123, 789),
});