Skip to content

Commit

Permalink
Release 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
djkoloski committed Apr 9, 2022
1 parent 5cc0210 commit 324e6d3
Show file tree
Hide file tree
Showing 10 changed files with 685 additions and 211 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "munge"
version = "0.1.1"
version = "0.2.0"
authors = ["David Koloski <[email protected]>"]
edition = "2021"
description = "Macro for easily initializing `MaybeUninit`s"
Expand Down
82 changes: 77 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# `munge`

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

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

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

## Example
## Examples

`munge` makes it easy to initialize `MaybeUninit`s:

```rust
use {
Expand All @@ -22,7 +23,7 @@ pub struct Example {

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

munge!(let Example { a, b: (c, mut f) } = mu);
munge!(let Example { a, b: (c, mut f) } = &mut mu);
assert_eq!(a.write(10), &10);
assert_eq!(c.write('x'), &'x');
assert_eq!(f.write(3.14), &3.14);
Expand All @@ -34,3 +35,74 @@ assert_eq!(init.a, 10);
assert_eq!(init.b.0, 'x');
assert_eq!(init.b.1, 3.14);
```

It can also be used to destructure `Cell`s:

```rust
use {
::core::cell::Cell,
::munge::munge,
};

pub struct Example {
a: u32,
b: (char, f32),
}

let value = Example {
a: 10,
b: ('x', 3.14),
};
let cell = Cell::<Example>::new(value);

munge!(let Example { a, b: (c, f) } = &cell);
assert_eq!(a.get(), 10);
a.set(42);
assert_eq!(c.get(), 'x');
c.set('!');
assert_eq!(f.get(), 3.14);
f.set(1.41);

let value = cell.into_inner();
assert_eq!(value.a, 42);
assert_eq!(value.b.0, '!');
assert_eq!(value.b.1, 1.41);
```

And `Pin`s as long as all fields are structurally pinned:

```rust
use {
::core::{marker::PhantomPinned, pin::Pin},
::munge::{munge, StructuralPinning},
};

struct Example {
pub a: u32,
pub b: char,
pub _phantom: PhantomPinned,
}

// SAFETY: `Example` obeys structural pinning.
unsafe impl StructuralPinning for Example {}

let mut value = Example {
a: 0,
b: ' ',
_phantom: PhantomPinned,
};
// SAFETY: `value` will not be moved before being dropped.
let mut pin = unsafe { Pin::new_unchecked(&mut value) };

munge!(let Example { a, b, .. } = pin.as_mut());
*a.get_mut() = 1;
*b.get_mut() = 'a';

assert_eq!(pin.as_mut().into_ref().a, 1);
assert_eq!(pin.as_mut().into_ref().b, 'a');
assert_eq!(value.a, 1);
assert_eq!(value.b, 'a');
```

You can even extend `munge` to work with your own types by implementing its `Destructure` and
`Restructure` traits.
82 changes: 77 additions & 5 deletions crates-io.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
`munge` makes it easy to initialize `MaybeUninit`s.
`munge` makes it easy and safe to destructure raw pointers, `MaybeUninit`s, `Cell`s, and `Pin`s.

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

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

## Example
## Examples

`munge` makes it easy to initialize `MaybeUninit`s:

```rust
use {
Expand All @@ -20,7 +21,7 @@ pub struct Example {

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

munge!(let Example { a, b: (c, mut f) } = mu);
munge!(let Example { a, b: (c, mut f) } = &mut mu);
assert_eq!(a.write(10), &10);
assert_eq!(c.write('x'), &'x');
assert_eq!(f.write(3.14), &3.14);
Expand All @@ -32,3 +33,74 @@ assert_eq!(init.a, 10);
assert_eq!(init.b.0, 'x');
assert_eq!(init.b.1, 3.14);
```

It can also be used to destructure `Cell`s:

```rust
use {
::core::cell::Cell,
::munge::munge,
};

pub struct Example {
a: u32,
b: (char, f32),
}

let value = Example {
a: 10,
b: ('x', 3.14),
};
let cell = Cell::<Example>::new(value);

munge!(let Example { a, b: (c, f) } = &cell);
assert_eq!(a.get(), 10);
a.set(42);
assert_eq!(c.get(), 'x');
c.set('!');
assert_eq!(f.get(), 3.14);
f.set(1.41);

let value = cell.into_inner();
assert_eq!(value.a, 42);
assert_eq!(value.b.0, '!');
assert_eq!(value.b.1, 1.41);
```

And `Pin`s as long as all fields are structurally pinned:

```rust
use {
::core::{marker::PhantomPinned, pin::Pin},
::munge::{munge, StructuralPinning},
};

struct Example {
pub a: u32,
pub b: char,
pub _phantom: PhantomPinned,
}

// SAFETY: `Example` obeys structural pinning.
unsafe impl StructuralPinning for Example {}

let mut value = Example {
a: 0,
b: ' ',
_phantom: PhantomPinned,
};
// SAFETY: `value` will not be moved before being dropped.
let mut pin = unsafe { Pin::new_unchecked(&mut value) };

munge!(let Example { a, b, .. } = pin.as_mut());
*a.get_mut() = 1;
*b.get_mut() = 'a';

assert_eq!(pin.as_mut().into_ref().a, 1);
assert_eq!(pin.as_mut().into_ref().b, 'a');
assert_eq!(value.a, 1);
assert_eq!(value.b, 'a');
```

You can even extend `munge` to work with your own types by implementing its `Destructure` and
`Restructure` traits.
164 changes: 164 additions & 0 deletions src/impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use {
::core::{cell::{Cell, UnsafeCell}, mem::MaybeUninit, pin::Pin},
crate::{Destructure, Restructure, StructuralPinning},
};

// *const T

impl<T: ?Sized> Destructure for *const T {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
*self as *mut T
}
}

unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*const T> for U {
type Restructured = *const Self;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
ptr as *const Self
}
}

// *mut T

impl<T: ?Sized> Destructure for *mut T {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
*self
}
}

unsafe impl<T: ?Sized, U: ?Sized> Restructure<&*mut T> for U {
type Restructured = *mut Self;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
ptr
}
}

// &MaybeUninit

impl<'a, T> Destructure for &'a MaybeUninit<T> {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
self.as_ptr() as *mut Self::Underlying
}
}

unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a MaybeUninit<T>> for U {
type Restructured = &'b MaybeUninit<U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b &'a MaybeUninit<T>`, so it's safe to dereference for the `'b` lifetime.
unsafe { &*ptr.cast() }
}
}

// &mut MaybeUninit

impl<'a, T> Destructure for &'a mut MaybeUninit<T> {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
MaybeUninit::as_mut_ptr(self)
}
}

unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a mut MaybeUninit<T>> for U {
type Restructured = &'b mut MaybeUninit<U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b &'a mut MaybeUninit<T>`, so it's safe to mutably dereference for the `'b` lifetime.
unsafe { &mut *ptr.cast() }
}
}

// &Cell<T>

impl<'a, T> Destructure for &'a Cell<T> {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
self.as_ptr()
}
}

unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a Cell<T>> for U {
type Restructured = &'b Cell<U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b &'a Cell<T>`, so it's safe to dereference for the `'b` lifetime.
unsafe { &*ptr.cast() }
}
}

// &UnsafeCell<T>

impl<'a, T> Destructure for &'a UnsafeCell<T> {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
self.get()
}
}

unsafe impl<'a: 'b, 'b, T, U: 'b> Restructure<&'b &'a UnsafeCell<T>> for U {
type Restructured = &'b UnsafeCell<U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b &'a UnsafeCell<T>`, so it's safe to dereference for the `'b` lifetime.
unsafe { &*ptr.cast() }
}
}

// Pin<&T> where T: StructuralPinning

impl<'a, T: StructuralPinning> Destructure for Pin<&'a T> {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
unsafe { Pin::into_inner_unchecked(self.as_ref()) as *const T as *mut T }
}
}

unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a T>> for U {
type Restructured = Pin<&'b U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b Pin<&'a T>`, and `T` has structural pinning, so it's safe to derefence as pinned for
// the `'b` lifetime.
unsafe { Pin::new_unchecked(&*ptr) }
}
}

// Pin<&mut T> where T: StructuralPinning

impl<'a, T: StructuralPinning> Destructure for Pin<&'a mut T> {
type Underlying = T;

fn as_mut_ptr(&mut self) -> *mut Self::Underlying {
// SAFETY: The value pointed to by `self` will continue to be treated as pinned.
unsafe { Pin::into_inner_unchecked(self.as_mut()) as *mut T }
}
}

unsafe impl<'a: 'b, 'b, T: StructuralPinning, U: 'b> Restructure<&'b Pin<&'a mut T>> for U {
type Restructured = Pin<&'b mut U>;

unsafe fn restructure(ptr: *mut Self) -> Self::Restructured {
// SAFETY: The caller has guaranteed that `ptr` points to a subfield of some
// `&'b Pin<&'a mut T>`, and `T` has structural pinning, so it's safe to mutably derefence
// as pinned for the `'b` lifetime.
unsafe { Pin::new_unchecked(&mut *ptr) }
}
}
Loading

0 comments on commit 324e6d3

Please sign in to comment.