Giter Site home page Giter Site logo

consume_on_drop's Introduction

consume_on_drop

A zero-cost abstraction that allows Drop::drop to consume self by value

Do you want to call a function that takes self by value in your impl Drop? Do you need the ability to both destructure and drop your struct? Do you want a convenience type to temporarily give your values a new Drop implementation? This crate is for you.

Safe, zero-cost API

ConsumeOnDrop<T> is a #[repr(transparent)] wrapper around T, and all provided operations are zero-cost.

WithConsumer<T, Q> is a thin wrapper around an ordered pair (T, Q), and all its provided operations are zero-cost.

All public functions, methods, and traits in these APIs are completely safe.

Implemented using minimal unsafe code

The implementation of ConsumeOnDrop has exactly 2 lines of unsafe code, both easy checked and tested with Miri.

The implementation of WithConsumer is completely safe (except insofar as it depends on the public API of ConsumeOnDrop).

Consume your type by value on drop

use consume_on_drop::{Consume, ConsumeOnDrop, WithConsumer};

struct T;

fn consume_t(_t: T) {
    println!("We consumed T")
}

impl Consume for T {
    fn consume(self) {
        consume_t(self)
    }
}

fn main () {
    let t = ConsumeOnDrop::new(T);  // A thin wrapper around T which calls T::consume on drop
    drop(t);
    let t = WithConsumer::new(T, consume_t); // Alternately, we can explicitly equip a T with a consumer.
    drop(t);
}

Write a struct that can be destructured and dropped

The following code doesn't compile.

struct MutRef<'a> {
    inner: &'a mut i32,
}

impl<'a> MuRef<'a> {
    pub fn new(val: &'a mut i32) -> Self {
        Self { inner: val }
    }
    
    pub fn into_inner(self) -> &'a mut i32 {
        self.inner
    }
}

impl<'a> Drop for MutRef<'a> {
    fn drop(&mut self) {
        *self.inner += 1;
    }
}

but we can make it work using ConsumeOnDrop:

use consume_on_drop::{Consume, ConsumeOnDrop};

struct RawMut<'a> {
    inner: &'a mut i32,
}

impl<'a> Consume for RawMut<'a> {
    fn consume(self) {
        *self.inner += 1;
    }
}

struct MutRef<'a> {
    inner: ConsumeOnDrop<RawMut<'a>>,
}

impl<'a> MutRef<'a> {
    pub fn new(val: &'a mut i32) -> Self {
        Self { inner: ConsumeOnDrop::new(RawMut { inner: val })}
    }
    
    pub fn into_inner(self) -> &'a mut i32 {
        ConsumeOnDrop::into_inner(self.inner).inner
    }
}

Note that this is a zero-cost abstraction. We could achieve the same effect using Option<RawMut>, but this incurs run-time overhead and prevents us from using the null-pointer optimization on Option<MutRef>.

Temporarily give your type a different drop implementation

Sometimes, you need to temporarily give your type a new drop implementation in case you return early or panic. Often, data may be left in an invalid state if a panic happens at the wrong time. To mark this, you may wish to "poison" your data.

use consume_on_drop::WithConsumer;

struct Data {
    string: Option<String>,
}

impl Data {
    fn new(str: String) -> Self {
        Self { string: Some(str) }
    }
    
    fn extend(&mut self, str: String) {
        self.string.as_mut().unwrap().extend(str.chars())
    }
    
    fn poison(&mut self) {
        self.string = None;
    }
}

fn produce_string() -> String {
    panic!("Oh no, we panicked!");
}

fn extend_produce(data: &mut Data) {
    let mut data = WithConsumer::new(data, Data::poison);
    data.extend(produce_string()); // if produce_string panics, we will drop data here and poison it
    WithConsumer::into_inner(data); // but if there's no panic, we will not poison.
}

License: MIT license

consume_on_drop's People

Contributors

markcsaving avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.