Crates.io | owned-pin |
lib.rs | owned-pin |
version | 1.3.3 |
source | src |
created_at | 2023-11-30 05:05:17.19236 |
updated_at | 2023-12-02 08:28:43.323706 |
description | A wrapper that both owns and pins data in memory |
homepage | |
repository | https://github.com/js2xxx/owned-pin |
max_upload_size | |
id | 1053869 |
size | 65,423 |
This crate deals with data that is owned by some entity but (maybe) immovable in memory. It is inspired by R-value references in C++.
See the documentation for more information.
With Pin<P>
only, we cannot guarantee the move semantics of the value.
use core::pin::{Pin, pin};
use core::marker::PhantomPinned;
fn try_to_take_the_ownership_of<T>(pinned: Pin<&mut T>) {}
let mut value = pin!(PhantomPinned);
// The caller can reborrow the value...
try_to_take_the_ownership_of(value.as_mut());
// ... so the same pinned data can be used twice,
// thus unable to guarantee the move semantics.
try_to_take_the_ownership_of(value.as_mut());
In practice, this is because there is no such smart pointer that owns data by holding a unique reference to some other location on the stack.
Thus, we introduce the OnStack<T>
smart pointer and an alias of OPin<T>
= Pin<OnStack<T>>
, which both "own" and "pin" the data on the stack, enabling the example above to work as desired:
use owned_pin::{OPin, opin};
use core::marker::PhantomPinned;
fn take_the_ownership_of<T>(owned_and_pinned: OPin<T>) {}
let value = opin!(PhantomPinned);
// The `as_mut` method of `OPin` actually
// returns a `Pin<&mut T>`...
take_the_ownership_of(value);
// ... so the value itself cannot be used again.
// The line below causes rustc to emit `E0382`.
// take_the_ownership_of(value);
With data that implements Unpin
, we can even move it out from the wrapper safe and sound:
use owned_pin::{opin, unpin};
// Pins the value onto the stack.
let pinned = opin!(String::from("Hello!"));
// Retrieves back the data because `String` is `Unpin`.
let string: String = unpin(pinned);
MIT OR Apache-2.0