9 unstable releases
0.5.2 | Nov 21, 2024 |
---|---|
0.5.1 | Nov 21, 2024 |
0.5.0 | Jul 31, 2023 |
0.4.0 | Nov 12, 2021 |
0.1.0 | Jun 20, 2020 |
#228 in Rust patterns
20,097 downloads per month
Used in 6 crates
(5 directly)
19KB
214 lines
dispose
- Linear wrappers for Rust
This is a small crate I made when working with gfx-hal
to simplify working with linear resources
that must be consumed at the end of their life, rather than borrowed as Drop
does. For more
information, see the docs.
lib.rs
:
A small crate for handling resources that must be consumed at the end of their lifetime.
Since Rust's type system is affine rather than linear, Drop::drop
mutably
borrows self
, rather than consuming it. For the most part, this is fine,
but for some cases (such as working with the crate gfx_hal
) resources must
be consumed on drop. This crate and the dispose_derive
crate serve to
cover the typical boilerplate for such cases by managing the ManuallyDrop
wrapper for you. (See the Dispose
derive macro for more info on that)
As a bonus, this crate makes it easy to defer the execution of an FnOnce
closure to the end of a scope, which can be done using the defer
function.
NOTE: The Dispose
trait does not provide a Drop
impl by itself.
For that, a value implementing Dispose
must be wrapped in a Disposable
struct.
Examples
use dispose::{Dispose, Disposable};
struct MyStruct;
impl Dispose for MyStruct {
fn dispose(self) { println!("Goodbye, world!"); }
}
{
let _my_struct = Disposable::new(MyStruct);
} // prints "Goodbye, world!"
As a design consideration, values implementing Dispose
should always be
returned wrapped in Disposable
or any other wrapper properly implementing
Drop
. Disposable
is recommended as it contains an unsafe leak
function to retrieve the inner value, if necessary.
use dispose::{Dispose, Disposable};
mod secrets {
pub struct Secrets {
launch_codes: u32,
}
impl Secrets {
pub fn new(launch_codes: u32) -> Disposable<Self> {
Self { launch_codes }.into()
}
}
impl Dispose for Secrets {
fn dispose(mut self) { self.launch_codes = 0x0; } // Nice try, hackers!
}
}
fn main() {
let secret = secrets::Secrets::new(0xDEADBEEF);
} // secret is properly disposed at the end of the scope
fn BAD() {
let secret = secrets::Secrets::new(0o1337);
let mwahaha = unsafe { Disposable::leak(secret) };
} // .dispose() was not called - data has been leaked!
(My lawyers have advised me to note that the above example is not cryptographically secure. Please do not clean up secure memory by simply setting it to zero.)
Dependencies
~225–670KB
~16K SLoC