pomsky 0.12.0

A new regular expression language
Documentation
use std::ops::{Deref, DerefMut};

pub(crate) struct Deferred<'a, S, F: FnMut(&mut S)> {
    state: &'a mut S,
    mutate: F,
}

impl<'a, S, F: FnMut(&mut S)> Deferred<'a, S, F> {
    pub(crate) fn new(state: &'a mut S, mutate: F) -> Self {
        Deferred { state, mutate }
    }
}

impl<S, F: FnMut(&mut S)> Drop for Deferred<'_, S, F> {
    fn drop(&mut self) {
        let mutator = &mut self.mutate;
        mutator(self.state);
    }
}

impl<S, F: FnMut(&mut S)> Deref for Deferred<'_, S, F> {
    type Target = S;

    fn deref(&self) -> &Self::Target {
        self.state
    }
}

impl<S, F: FnMut(&mut S)> DerefMut for Deferred<'_, S, F> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.state
    }
}

#[doc(hidden)]
pub(crate) trait Mutable {
    fn mutable(&mut self) -> &mut Self;
}

impl<T> Mutable for T {
    fn mutable(&mut self) -> &mut Self {
        self
    }
}

macro_rules! revert_on_drop {
    ($state:ident . $($id:tt).*) => {
        let __prev = $state.$($id).*;
        let mut $state = {
            use $crate::defer::Mutable as _;
            $crate::defer::Deferred::new($state.mutable(), move |$state| {
                $state.$($id).* = __prev;
            })
        };
    };
}