munge/
lib.rs

1//! Munge makes it easy and safe to destructure `MaybeUninit`s, `Cell`s,
2//! `UnsafeCell`s, `ManuallyDrop`s and more.
3//!
4//! Just use the `munge!` macro to destructure opaque types the same way you'd
5//! destructure a value. The `munge!` macro may be used to perform either borrow
6//! destructuring (e.g. `let (a, b) = c` where `c` is a reference) or move
7//! destructuring (e.g. `let (a, b) = c` where `c` is a value) depending on the
8//! type.
9//!
10//! Munge has no features and is always `#![no_std]`.
11//!
12//! ## Examples
13#![doc = include_str!("../example.md")]
14#![no_std]
15#![deny(
16    future_incompatible,
17    missing_docs,
18    nonstandard_style,
19    unsafe_op_in_unsafe_fn,
20    unused,
21    warnings,
22    clippy::all,
23    clippy::missing_safety_doc,
24    clippy::undocumented_unsafe_blocks,
25    rustdoc::broken_intra_doc_links,
26    rustdoc::missing_crate_level_docs
27)]
28#![cfg_attr(all(docsrs, not(doctest)), feature(doc_cfg, doc_auto_cfg))]
29
30#[doc(hidden)]
31pub mod __macro;
32mod impls;
33mod internal;
34
35#[doc(hidden)]
36pub use munge_macro::munge_with_path;
37
38/// Destructures a type into
39///
40/// # Example
41///
42/// ```
43/// # use core::mem::MaybeUninit;
44/// # use munge::munge;
45/// pub struct Example {
46///     a: u32,
47///     b: (char, f32),
48/// }
49///
50/// let mut mu = MaybeUninit::<Example>::uninit();
51///
52/// munge!(let Example { a, b: (c, mut f) } = &mut mu);
53/// assert_eq!(a.write(10), &10);
54/// assert_eq!(c.write('x'), &'x');
55/// assert_eq!(f.write(3.14), &3.14);
56/// // Note that `mut` bindings can be reassigned like you'd expect:
57/// let mut new_f = MaybeUninit::uninit();
58/// f = &mut new_f;
59///
60/// // SAFETY: `mu` is completely initialized.
61/// let init = unsafe { mu.assume_init() };
62/// assert_eq!(init.a, 10);
63/// assert_eq!(init.b.0, 'x');
64/// assert_eq!(init.b.1, 3.14);
65/// ```
66#[macro_export]
67macro_rules! munge {
68    ($($t:tt)*) => { $crate::munge_with_path!($crate => $($t)*) }
69}
70
71/// A type that can be destructured into its constituent parts.
72///
73/// See the [crate docs](index.html#examples) for an example of implementing
74/// `Destructure` and `Restructure`.
75///
76/// # Safety
77///
78/// - [`Destructuring`](Destructure::Destructuring) must reflect the type of
79///   destructuring allowed for the type:
80///   - [`Borrow`] if the type is restructured by creating disjoint borrows of
81///     the fields of `Underlying`.
82///   - [`Move`] if the type may be restructured by moving the fields out of the
83///     destructured `Underlying`.
84/// - [`underlying`](Destructure::underlying) must return a pointer that is
85///   non-null, properly aligned, and valid for reads.
86pub unsafe trait Destructure: Sized {
87    /// The underlying type that is destructured.
88    type Underlying: ?Sized;
89    /// The type of destructuring to perform.
90    type Destructuring: internal::Destructuring;
91
92    /// Returns a mutable pointer to the underlying type.
93    fn underlying(&mut self) -> *mut Self::Underlying;
94}
95
96/// A type that can be "restructured" as a field of some containing type.
97///
98/// See the [crate docs](index.html#examples) for an example of implementing
99/// `Destructure` and `Restructure`.
100///
101/// # Safety
102///
103/// [`restructure`](Restructure::restructure) must return a valid
104/// [`Restructured`](Restructure::Restructured) that upholds the invariants for
105/// its [`Destructuring`](Destructure::Destructuring):
106/// - If the type is destructured [by borrow](Borrow), then the `Restructured`
107///   value must behave as a disjoint borrow of a field of the underlying type.
108/// - If the type is destructured [by move](Move), then the `Restructured` value
109///   must move the fields out of the underlying type.
110pub unsafe trait Restructure<T: ?Sized>: Destructure {
111    /// The restructured version of this type.
112    type Restructured;
113
114    /// Restructures a pointer to this type into the target type.
115    ///
116    /// # Safety
117    ///
118    /// `ptr` must be a properly aligned pointer to a subfield of the pointer
119    /// [`underlying`](Destructure::underlying) `self`.
120    unsafe fn restructure(&self, ptr: *mut T) -> Self::Restructured;
121}
122
123/// Destructuring by borrow, e.g. `let (a, b) = c` where `c` is a reference.
124///
125/// Borrow destructuring leaves the original value intact, only borrowing from
126/// the destructured value. Borrow destructuring may use rest patterns (`..`)
127/// because the original value is not moved and so it is safe to restructure
128/// only some of the fields of the destructured value.
129pub struct Borrow;
130
131impl internal::Destructuring for Borrow {}
132
133impl<T: Destructure> internal::DestructuringFor<T> for Borrow {
134    type Destructurer = internal::Borrow<T>;
135}
136
137/// Destructuring by move, e.g. `let (a, b) = c` where `c` is a value.
138///
139/// Move destructuring forgets the original value and moves each destructured
140/// field during restructuring. Move destructuring may not use rest patterns
141/// (`..`) because every field of the original value must be restructured, else
142/// they will be forgotten.
143pub struct Move;
144
145impl internal::Destructuring for Move {}
146
147impl<T: Destructure> internal::DestructuringFor<T> for Move {
148    type Destructurer = internal::Move<T>;
149}
150
151#[cfg(test)]
152mod tests {
153    use core::mem::MaybeUninit;
154
155    #[test]
156    fn project_tuple() {
157        let mut mu = MaybeUninit::<(u32, char)>::uninit();
158
159        munge!(let (a, b) = &mut mu);
160        assert_eq!(a.write(1), &1);
161        assert_eq!(b.write('a'), &'a');
162        munge!(let (a, b,) = &mut mu);
163        assert_eq!(a.write(2), &2);
164        assert_eq!(b.write('b'), &'b');
165
166        munge!(let (a, _) = &mut mu);
167        assert_eq!(a.write(3), &3);
168        munge!(let (_, b) = &mut mu);
169        assert_eq!(b.write('c'), &'c');
170        munge!(let (a, _,) = &mut mu);
171        assert_eq!(a.write(3), &3);
172        munge!(let (_, b,) = &mut mu);
173        assert_eq!(b.write('c'), &'c');
174
175        munge!(let (mut a, mut b) = &mut mu);
176        assert_eq!(a.write(4), &4);
177        assert_eq!(b.write('d'), &'d');
178        let mut new_a = MaybeUninit::uninit();
179        a = &mut new_a;
180        let mut new_b = MaybeUninit::uninit();
181        b = &mut new_b;
182        let _ = a;
183        let _ = b;
184
185        munge!(let (a, ..) = &mut mu);
186        assert_eq!(a.write(5), &5);
187
188        // SAFETY: `mu` is completely initialized.
189        let init = unsafe { mu.assume_init() };
190        assert_eq!(init.0, 5);
191        assert_eq!(init.1, 'd');
192    }
193
194    #[test]
195    fn project_array() {
196        let mut mu = MaybeUninit::<[u32; 2]>::uninit();
197
198        munge!(let [a, b] = &mut mu);
199        assert_eq!(a.write(1), &1);
200        assert_eq!(b.write(1), &1);
201        munge!(let [a, b,] = &mut mu);
202        assert_eq!(a.write(2), &2);
203        assert_eq!(b.write(2), &2);
204
205        munge!(let [a, _] = &mut mu);
206        assert_eq!(a.write(3), &3);
207        munge!(let [_, b] = &mut mu);
208        assert_eq!(b.write(3), &3);
209        munge!(let [a, _,] = &mut mu);
210        assert_eq!(a.write(4), &4);
211        munge!(let [_, b,] = &mut mu);
212        assert_eq!(b.write(4), &4);
213
214        munge!(let [mut a, mut b] = &mut mu);
215        assert_eq!(a.write(5), &5);
216        assert_eq!(b.write(5), &5);
217        let mut new_a = MaybeUninit::uninit();
218        a = &mut new_a;
219        let mut new_b = MaybeUninit::uninit();
220        b = &mut new_b;
221        let _ = a;
222        let _ = b;
223
224        munge!(let [a, ..] = &mut mu);
225        assert_eq!(a.write(6), &6);
226
227        // SAFETY: `mu` is completely initialized.
228        let init = unsafe { mu.assume_init() };
229        assert_eq!(init[0], 6);
230        assert_eq!(init[1], 5);
231    }
232
233    #[test]
234    fn project_struct() {
235        pub struct Example {
236            pub a: u32,
237            pub b: char,
238        }
239
240        let mut mu = MaybeUninit::<Example>::uninit();
241
242        munge!(let Example { a, b } = &mut mu);
243        assert_eq!(a.write(1), &1);
244        assert_eq!(b.write('a'), &'a');
245        munge!(let Example { a, b, } = &mut mu);
246        assert_eq!(a.write(2), &2);
247        assert_eq!(b.write('b'), &'b');
248
249        munge!(let Example { a, b: x } = &mut mu);
250        assert_eq!(a.write(3), &3);
251        assert_eq!(x.write('c'), &'c');
252        munge!(let Example { a, b: x, } = &mut mu);
253        assert_eq!(a.write(4), &4);
254        assert_eq!(x.write('d'), &'d');
255
256        munge!(let Example { a: x, b } = &mut mu);
257        assert_eq!(x.write(3), &3);
258        assert_eq!(b.write('c'), &'c');
259        munge!(let Example { a: x, b, } = &mut mu);
260        assert_eq!(x.write(4), &4);
261        assert_eq!(b.write('d'), &'d');
262
263        munge!(let Example { a, b: _ } = &mut mu);
264        assert_eq!(a.write(5), &5);
265        munge!(let Example { a, b: _, } = &mut mu);
266        assert_eq!(a.write(6), &6);
267
268        munge!(let Example { mut a, mut b } = &mut mu);
269        assert_eq!(a.write(7), &7);
270        assert_eq!(b.write('e'), &'e');
271        let mut new_a = MaybeUninit::uninit();
272        a = &mut new_a;
273        let mut new_b = MaybeUninit::uninit();
274        b = &mut new_b;
275        let _ = a;
276        let _ = b;
277
278        munge!(let Example { a: mut x, b: mut y } = &mut mu);
279        assert_eq!(x.write(8), &8);
280        assert_eq!(y.write('f'), &'f');
281        let mut new_x = MaybeUninit::uninit();
282        x = &mut new_x;
283        let mut new_y = MaybeUninit::uninit();
284        y = &mut new_y;
285        let _ = x;
286        let _ = y;
287
288        munge!(let Example { b, .. } = &mut mu);
289        assert_eq!(b.write('g'), &'g');
290
291        // SAFETY: `mu` is completely initialized.
292        let init = unsafe { mu.assume_init() };
293        assert_eq!(init.a, 8);
294        assert_eq!(init.b, 'g');
295    }
296
297    #[test]
298    fn project_tuple_struct() {
299        struct Example(u32, char);
300
301        let mut mu = MaybeUninit::<Example>::uninit();
302
303        munge!(let Example(a, b) = &mut mu);
304        assert_eq!(a.write(1), &1);
305        assert_eq!(b.write('a'), &'a');
306        munge!(let Example(a, b,) = &mut mu);
307        assert_eq!(a.write(2), &2);
308        assert_eq!(b.write('b'), &'b');
309
310        munge!(let Example(a, _) = &mut mu);
311        assert_eq!(a.write(3), &3);
312        munge!(let Example(_, b) = &mut mu);
313        assert_eq!(b.write('c'), &'c');
314        munge!(let Example(a, _,) = &mut mu);
315        assert_eq!(a.write(3), &3);
316        munge!(let Example(_, b,) = &mut mu);
317        assert_eq!(b.write('d'), &'d');
318
319        munge!(let Example(mut a, mut b) = &mut mu);
320        assert_eq!(a.write(4), &4);
321        assert_eq!(b.write('e'), &'e');
322        let mut new_a = MaybeUninit::uninit();
323        a = &mut new_a;
324        let mut new_b = MaybeUninit::uninit();
325        b = &mut new_b;
326        let _ = a;
327        let _ = b;
328
329        munge!(let Example(a, ..) = &mut mu);
330        assert_eq!(a.write(5), &5);
331
332        // SAFETY: `mu` is completely initialized.
333        let init = unsafe { mu.assume_init() };
334        assert_eq!(init.0, 5);
335        assert_eq!(init.1, 'e');
336    }
337
338    #[test]
339    fn project_generic() {
340        struct Example<T>(u32, T);
341
342        let mut mu = MaybeUninit::<Example<char>>::uninit();
343
344        munge!(let Example(a, b) = &mut mu);
345        assert_eq!(a.write(1), &1);
346        assert_eq!(b.write('a'), &'a');
347        munge!(let Example(a, b,) = &mut mu);
348        assert_eq!(a.write(2), &2);
349        assert_eq!(b.write('b'), &'b');
350
351        munge!(let Example(a, _) = &mut mu);
352        assert_eq!(a.write(3), &3);
353        munge!(let Example(_, b) = &mut mu);
354        assert_eq!(b.write('c'), &'c');
355        munge!(let Example(a, _,) = &mut mu);
356        assert_eq!(a.write(3), &3);
357        munge!(let Example(_, b,) = &mut mu);
358        assert_eq!(b.write('c'), &'c');
359
360        munge!(let Example(a, ..) = &mut mu);
361        assert_eq!(a.write(4), &4);
362
363        // SAFETY: `mu` is completely initialized.
364        let init = unsafe { mu.assume_init() };
365        assert_eq!(init.0, 4);
366        assert_eq!(init.1, 'c');
367
368        let mut mu = MaybeUninit::<Example<Example<char>>>::uninit();
369
370        munge!(
371            let Example::<Example<char>>(a, Example::<char>(b, c)) = &mut mu;
372        );
373        assert_eq!(a.write(1), &1);
374        assert_eq!(b.write(2), &2);
375        assert_eq!(c.write('a'), &'a');
376
377        // SAFETY: `mu` is completely initialized.
378        let init = unsafe { mu.assume_init() };
379        assert_eq!(init.0, 1);
380        assert_eq!(init.1 .0, 2);
381        assert_eq!(init.1 .1, 'a');
382    }
383
384    #[test]
385    fn project_nested_struct() {
386        struct Inner {
387            a: u32,
388            b: char,
389        }
390        struct Outer {
391            inner: Inner,
392            c: i32,
393        }
394
395        let mut mu = MaybeUninit::<Outer>::uninit();
396
397        munge!(let Outer { inner: Inner { a, b }, c } = &mut mu);
398        assert_eq!(a.write(1), &1);
399        assert_eq!(b.write('a'), &'a');
400        assert_eq!(c.write(2), &2);
401
402        // SAFETY: `mu` is completely initialized.
403        let init = unsafe { mu.assume_init() };
404        assert_eq!(init.inner.a, 1);
405        assert_eq!(init.inner.b, 'a');
406        assert_eq!(init.c, 2);
407    }
408
409    #[test]
410    fn project_nested_tuple() {
411        let mut mu = MaybeUninit::<(u32, (char, u32))>::uninit();
412
413        munge!(let (a, (b, c)) = &mut mu);
414        assert_eq!(a.write(1), &1);
415        assert_eq!(b.write('a'), &'a');
416        assert_eq!(c.write(2), &2);
417
418        // SAFETY: `mu` is completely initialized.
419        let init = unsafe { mu.assume_init() };
420        assert_eq!(init, (1, ('a', 2)));
421    }
422
423    #[test]
424    fn project_nested_array() {
425        let mut mu = MaybeUninit::<[[u32; 2]; 2]>::uninit();
426
427        munge!(let [a, [b, c]] = &mut mu);
428        assert_eq!(a.write([1, 2]), &[1, 2]);
429        assert_eq!(b.write(3), &3);
430        assert_eq!(c.write(4), &4);
431
432        // SAFETY: `mu` is completely initialized.
433        let init = unsafe { mu.assume_init() };
434        assert_eq!(init, [[1, 2], [3, 4]]);
435    }
436
437    #[test]
438    fn generics() {
439        struct Inner<T> {
440            a: u32,
441            b: T,
442        }
443        struct Outer<T> {
444            inner: Inner<T>,
445            c: i32,
446        }
447
448        let mut mu = MaybeUninit::<Outer<char>>::uninit();
449
450        munge!(let Outer { inner: Inner { a, b }, c } = &mut mu);
451        assert_eq!(a.write(1), &1);
452        assert_eq!(b.write('a'), &'a');
453        assert_eq!(c.write(2), &2);
454
455        // SAFETY: `mu` is completely initialized.
456        let init = unsafe { mu.assume_init() };
457        assert_eq!(init.inner.a, 1);
458        assert_eq!(init.inner.b, 'a');
459        assert_eq!(init.c, 2);
460    }
461
462    #[test]
463    fn cell() {
464        use core::cell::Cell;
465
466        pub struct Example {
467            a: u32,
468            b: (char, f32),
469        }
470
471        let value = Example {
472            a: 10,
473            b: ('x', core::f32::consts::PI),
474        };
475        let cell = Cell::<Example>::new(value);
476
477        munge!(let Example { a, b: (c, f) } = &cell);
478        assert_eq!(a.get(), 10);
479        a.set(42);
480        assert_eq!(c.get(), 'x');
481        c.set('!');
482        assert_eq!(f.get(), core::f32::consts::PI);
483        f.set(1.41);
484
485        let value = cell.into_inner();
486        assert_eq!(value.a, 42);
487        assert_eq!(value.b.0, '!');
488        assert_eq!(value.b.1, 1.41);
489    }
490
491    #[test]
492    fn maybe_uninit_value() {
493        let mu = MaybeUninit::<(u32, char)>::new((10_000, 'x'));
494
495        munge!(let (a, b) = mu);
496        assert_eq!(unsafe { a.assume_init() }, 10_000);
497        assert_eq!(unsafe { b.assume_init() }, 'x');
498    }
499
500    #[test]
501    fn cell_value() {
502        use core::cell::Cell;
503
504        let cell = Cell::<(u32, char)>::new((10_000, 'x'));
505
506        munge!(let (a, b) = cell);
507        assert_eq!(a.get(), 10_000);
508        assert_eq!(b.get(), 'x');
509    }
510
511    #[test]
512    fn unsafe_cell_value() {
513        use core::cell::UnsafeCell;
514
515        let uc = UnsafeCell::<(u32, char)>::new((10_000, 'x'));
516
517        munge!(let (mut a, mut b) = uc);
518        assert_eq!(*a.get_mut(), 10_000);
519        assert_eq!(*b.get_mut(), 'x');
520    }
521
522    #[test]
523    fn manually_drop_value() {
524        use core::mem::ManuallyDrop;
525
526        let md = ManuallyDrop::new((10_000, 'x'));
527
528        munge!(let (a, b) = md);
529        assert_eq!(*a, 10_000);
530        assert_eq!(*b, 'x');
531    }
532
533    #[test]
534    fn struct_borrow_partial_destructuring() {
535        use core::cell::Cell;
536
537        struct Example {
538            a: u32,
539            b: u32,
540        }
541
542        let mut value = Cell::new(Example { a: 0, b: 1 });
543
544        munge!(let Example { a, .. } = &mut value);
545        assert_eq!(a.get(), 0);
546        a.set(2);
547        assert_eq!(a.get(), 2);
548
549        munge!(let Example { a: c, b: _ } = &value);
550        assert_eq!(c.get(), 2);
551        c.set(3);
552        assert_eq!(c.get(), 3);
553    }
554
555    #[test]
556    fn tuple_borrow_partial_destructuring() {
557        use core::cell::Cell;
558
559        struct Example(u32, u32);
560
561        let mut value = Cell::new(Example(0, 1));
562
563        munge!(let Example(a, ..) = &mut value);
564        assert_eq!(a.get(), 0);
565        a.set(2);
566        assert_eq!(a.get(), 2);
567
568        munge!(let Example(c, _) = &value);
569        assert_eq!(c.get(), 2);
570        c.set(3);
571        assert_eq!(c.get(), 3);
572    }
573}