Skip to content

Commit 324e6d3

Browse files
committed
Release 0.2.0
1 parent 5cc0210 commit 324e6d3

File tree

10 files changed

+685
-211
lines changed

10 files changed

+685
-211
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "munge"
3-
version = "0.1.1"
3+
version = "0.2.0"
44
authors = ["David Koloski <[email protected]>"]
55
edition = "2021"
66
description = "Macro for easily initializing `MaybeUninit`s"

README.md

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# `munge`
22

3-
`munge` makes it easy to initialize `MaybeUninit`s.
3+
`munge` makes it easy and safe to destructure raw pointers, `MaybeUninit`s, `Cell`s, and `Pin`s.
44

5-
Just use the `munge!` macro to destructure `MaybeUninit`s the same way you'd destructure a value.
6-
Initialize all the fields, then call `assume_init` to unwrap it.
5+
Just use the `munge!` macro to destructure opaque types the same way you'd destructure a value.
76

87
`munge` has no features and is always `#![no_std]`.
98

10-
## Example
9+
## Examples
10+
11+
`munge` makes it easy to initialize `MaybeUninit`s:
1112

1213
```rust
1314
use {
@@ -22,7 +23,7 @@ pub struct Example {
2223

2324
let mut mu = MaybeUninit::<Example>::uninit();
2425

25-
munge!(let Example { a, b: (c, mut f) } = mu);
26+
munge!(let Example { a, b: (c, mut f) } = &mut mu);
2627
assert_eq!(a.write(10), &10);
2728
assert_eq!(c.write('x'), &'x');
2829
assert_eq!(f.write(3.14), &3.14);
@@ -34,3 +35,74 @@ assert_eq!(init.a, 10);
3435
assert_eq!(init.b.0, 'x');
3536
assert_eq!(init.b.1, 3.14);
3637
```
38+
39+
It can also be used to destructure `Cell`s:
40+
41+
```rust
42+
use {
43+
::core::cell::Cell,
44+
::munge::munge,
45+
};
46+
47+
pub struct Example {
48+
a: u32,
49+
b: (char, f32),
50+
}
51+
52+
let value = Example {
53+
a: 10,
54+
b: ('x', 3.14),
55+
};
56+
let cell = Cell::<Example>::new(value);
57+
58+
munge!(let Example { a, b: (c, f) } = &cell);
59+
assert_eq!(a.get(), 10);
60+
a.set(42);
61+
assert_eq!(c.get(), 'x');
62+
c.set('!');
63+
assert_eq!(f.get(), 3.14);
64+
f.set(1.41);
65+
66+
let value = cell.into_inner();
67+
assert_eq!(value.a, 42);
68+
assert_eq!(value.b.0, '!');
69+
assert_eq!(value.b.1, 1.41);
70+
```
71+
72+
And `Pin`s as long as all fields are structurally pinned:
73+
74+
```rust
75+
use {
76+
::core::{marker::PhantomPinned, pin::Pin},
77+
::munge::{munge, StructuralPinning},
78+
};
79+
80+
struct Example {
81+
pub a: u32,
82+
pub b: char,
83+
pub _phantom: PhantomPinned,
84+
}
85+
86+
// SAFETY: `Example` obeys structural pinning.
87+
unsafe impl StructuralPinning for Example {}
88+
89+
let mut value = Example {
90+
a: 0,
91+
b: ' ',
92+
_phantom: PhantomPinned,
93+
};
94+
// SAFETY: `value` will not be moved before being dropped.
95+
let mut pin = unsafe { Pin::new_unchecked(&mut value) };
96+
97+
munge!(let Example { a, b, .. } = pin.as_mut());
98+
*a.get_mut() = 1;
99+
*b.get_mut() = 'a';
100+
101+
assert_eq!(pin.as_mut().into_ref().a, 1);
102+
assert_eq!(pin.as_mut().into_ref().b, 'a');
103+
assert_eq!(value.a, 1);
104+
assert_eq!(value.b, 'a');
105+
```
106+
107+
You can even extend `munge` to work with your own types by implementing its `Destructure` and
108+
`Restructure` traits.

crates-io.md

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
`munge` makes it easy to initialize `MaybeUninit`s.
1+
`munge` makes it easy and safe to destructure raw pointers, `MaybeUninit`s, `Cell`s, and `Pin`s.
22

3-
Just use the `munge!` macro to destructure `MaybeUninit`s the same way you'd destructure a value.
4-
Initialize all the fields, then call `assume_init` to unwrap it.
3+
Just use the `munge!` macro to destructure opaque types the same way you'd destructure a value.
54

65
`munge` has no features and is always `#![no_std]`.
76

8-
## Example
7+
## Examples
8+
9+
`munge` makes it easy to initialize `MaybeUninit`s:
910

1011
```rust
1112
use {
@@ -20,7 +21,7 @@ pub struct Example {
2021

2122
let mut mu = MaybeUninit::<Example>::uninit();
2223

23-
munge!(let Example { a, b: (c, mut f) } = mu);
24+
munge!(let Example { a, b: (c, mut f) } = &mut mu);
2425
assert_eq!(a.write(10), &10);
2526
assert_eq!(c.write('x'), &'x');
2627
assert_eq!(f.write(3.14), &3.14);
@@ -32,3 +33,74 @@ assert_eq!(init.a, 10);
3233
assert_eq!(init.b.0, 'x');
3334
assert_eq!(init.b.1, 3.14);
3435
```
36+
37+
It can also be used to destructure `Cell`s:
38+
39+
```rust
40+
use {
41+
::core::cell::Cell,
42+
::munge::munge,
43+
};
44+
45+
pub struct Example {
46+
a: u32,
47+
b: (char, f32),
48+
}
49+
50+
let value = Example {
51+
a: 10,
52+
b: ('x', 3.14),
53+
};
54+
let cell = Cell::<Example>::new(value);
55+
56+
munge!(let Example { a, b: (c, f) } = &cell);
57+
assert_eq!(a.get(), 10);
58+
a.set(42);
59+
assert_eq!(c.get(), 'x');
60+
c.set('!');
61+
assert_eq!(f.get(), 3.14);
62+
f.set(1.41);
63+
64+
let value = cell.into_inner();
65+
assert_eq!(value.a, 42);
66+
assert_eq!(value.b.0, '!');
67+
assert_eq!(value.b.1, 1.41);
68+
```
69+
70+
And `Pin`s as long as all fields are structurally pinned:
71+
72+
```rust
73+
use {
74+
::core::{marker::PhantomPinned, pin::Pin},
75+
::munge::{munge, StructuralPinning},
76+
};
77+
78+
struct Example {
79+
pub a: u32,
80+
pub b: char,
81+
pub _phantom: PhantomPinned,
82+
}
83+
84+
// SAFETY: `Example` obeys structural pinning.
85+
unsafe impl StructuralPinning for Example {}
86+
87+
let mut value = Example {
88+
a: 0,
89+
b: ' ',
90+
_phantom: PhantomPinned,
91+
};
92+
// SAFETY: `value` will not be moved before being dropped.
93+
let mut pin = unsafe { Pin::new_unchecked(&mut value) };
94+
95+
munge!(let Example { a, b, .. } = pin.as_mut());
96+
*a.get_mut() = 1;
97+
*b.get_mut() = 'a';
98+
99+
assert_eq!(pin.as_mut().into_ref().a, 1);
100+
assert_eq!(pin.as_mut().into_ref().b, 'a');
101+
assert_eq!(value.a, 1);
102+
assert_eq!(value.b, 'a');
103+
```
104+
105+
You can even extend `munge` to work with your own types by implementing its `Destructure` and
106+
`Restructure` traits.

src/impls.rs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
use {
2+
::core::{cell::{Cell, UnsafeCell}, mem::MaybeUninit, pin::Pin},
3+
crate::{Destructure, Restructure, StructuralPinning},
4+
};
5+
6+
// *const T
7+
8+
impl<T: ?Sized> Destructure for *const T {
9+
type Underlying = T;
10+
11+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
12+
*self as *mut T
13+
}
14+
}
15+
16+
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*const T> for U {
17+
type Restructured = *const Self;
18+
19+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
20+
ptr as *const Self
21+
}
22+
}
23+
24+
// *mut T
25+
26+
impl<T: ?Sized> Destructure for *mut T {
27+
type Underlying = T;
28+
29+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
30+
*self
31+
}
32+
}
33+
34+
unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*mut T> for U {
35+
type Restructured = *mut Self;
36+
37+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
38+
ptr
39+
}
40+
}
41+
42+
// &MaybeUninit
43+
44+
impl<'a, T> Destructure for &'a MaybeUninit<T> {
45+
type Underlying = T;
46+
47+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
48+
self.as_ptr() as *mut Self::Underlying
49+
}
50+
}
51+
52+
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a MaybeUninit<T>> for U {
53+
type Restructured = &'b MaybeUninit<U>;
54+
55+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
56+
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
57+
// `&'b &'a MaybeUninit<T>`, so it's safe to dereference for the `'b` lifetime.
58+
unsafe { &*ptr.cast() }
59+
}
60+
}
61+
62+
// &mut MaybeUninit
63+
64+
impl<'a, T> Destructure for &'a mut MaybeUninit<T> {
65+
type Underlying = T;
66+
67+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
68+
MaybeUninit::as_mut_ptr(self)
69+
}
70+
}
71+
72+
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a mut MaybeUninit<T>> for U {
73+
type Restructured = &'b mut MaybeUninit<U>;
74+
75+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
76+
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
77+
// `&'b &'a mut MaybeUninit<T>`, so it's safe to mutably dereference for the `'b` lifetime.
78+
unsafe { &mut *ptr.cast() }
79+
}
80+
}
81+
82+
// &Cell<T>
83+
84+
impl<'a, T> Destructure for &'a Cell<T> {
85+
type Underlying = T;
86+
87+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
88+
self.as_ptr()
89+
}
90+
}
91+
92+
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a Cell<T>> for U {
93+
type Restructured = &'b Cell<U>;
94+
95+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
96+
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
97+
// `&'b &'a Cell<T>`, so it's safe to dereference for the `'b` lifetime.
98+
unsafe { &*ptr.cast() }
99+
}
100+
}
101+
102+
// &UnsafeCell<T>
103+
104+
impl<'a, T> Destructure for &'a UnsafeCell<T> {
105+
type Underlying = T;
106+
107+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
108+
self.get()
109+
}
110+
}
111+
112+
unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a UnsafeCell<T>> for U {
113+
type Restructured = &'b UnsafeCell<U>;
114+
115+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
116+
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
117+
// `&'b &'a UnsafeCell<T>`, so it's safe to dereference for the `'b` lifetime.
118+
unsafe { &*ptr.cast() }
119+
}
120+
}
121+
122+
// Pin<&T> where T: StructuralPinning
123+
124+
impl<'a, T: StructuralPinning> Destructure for Pin<&'a T> {
125+
type Underlying = T;
126+
127+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
128+
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
129+
unsafe { Pin::into_inner_unchecked(self.as_ref()) as *const T as *mut T }
130+
}
131+
}
132+
133+
unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a T>> for U {
134+
type Restructured = Pin<&'b U>;
135+
136+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
137+
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
138+
// `&'b Pin<&'a T>`, and `T` has structural pinning, so it's safe to derefence as pinned for
139+
// the `'b` lifetime.
140+
unsafe { Pin::new_unchecked(&*ptr) }
141+
}
142+
}
143+
144+
// Pin<&mut T> where T: StructuralPinning
145+
146+
impl<'a, T: StructuralPinning> Destructure for Pin<&'a mut T> {
147+
type Underlying = T;
148+
149+
fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
150+
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
151+
unsafe { Pin::into_inner_unchecked(self.as_mut()) as *mut T }
152+
}
153+
}
154+
155+
unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a mut T>> for U {
156+
type Restructured = Pin<&'b mut U>;
157+
158+
unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
159+
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
160+
// `&'b Pin<&'a mut T>`, and `T` has structural pinning, so it's safe to mutably derefence
161+
// as pinned for the `'b` lifetime.
162+
unsafe { Pin::new_unchecked(&mut *ptr) }
163+
}
164+
}

0 commit comments

Comments
 (0)