1#![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#[macro_export]
67macro_rules! munge {
68 ($($t:tt)*) => { $crate::munge_with_path!($crate => $($t)*) }
69}
70
71pub unsafe trait Destructure: Sized {
87 type Underlying: ?Sized;
89 type Destructuring: internal::Destructuring;
91
92 fn underlying(&mut self) -> *mut Self::Underlying;
94}
95
96pub unsafe trait Restructure<T: ?Sized>: Destructure {
111 type Restructured;
113
114 unsafe fn restructure(&self, ptr: *mut T) -> Self::Restructured;
121}
122
123pub 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
137pub 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 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 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 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 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 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 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 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 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 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 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}