use crate::{FallibleTryDropStrategy, TryDropStrategy};
use anyhow::Error;
use std::cell::RefCell;
#[cfg_attr(
feature = "derives",
derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)
)]
pub struct ThreadUnsafeAdHocMutDropStrategy<F: FnMut(crate::Error)>(pub RefCell<F>);
impl<F: FnMut(crate::Error)> ThreadUnsafeAdHocMutDropStrategy<F> {
pub fn new(f: F) -> Self {
Self(RefCell::new(f))
}
}
impl<F: FnMut(crate::Error)> TryDropStrategy for ThreadUnsafeAdHocMutDropStrategy<F> {
fn handle_error(&self, error: crate::Error) {
self.0.borrow_mut()(error)
}
}
pub trait IntoThreadUnsafeAdHocMutDropStrategy: FnMut(crate::Error) + Sized {
fn into_drop_strategy(self) -> ThreadUnsafeAdHocMutDropStrategy<Self> {
ThreadUnsafeAdHocMutDropStrategy::new(self)
}
}
impl<F: FnMut(crate::Error)> IntoThreadUnsafeAdHocMutDropStrategy for F {}
#[cfg_attr(
feature = "derives",
derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)
)]
pub struct ThreadUnsafeAdHocMutFallibleDropStrategy<F, E>(pub RefCell<F>)
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<crate::Error>;
impl<F, E> ThreadUnsafeAdHocMutFallibleDropStrategy<F, E>
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<crate::Error>,
{
pub fn new(f: F) -> Self {
Self(RefCell::new(f))
}
}
impl<F, E> FallibleTryDropStrategy for ThreadUnsafeAdHocMutFallibleDropStrategy<F, E>
where
F: FnMut(crate::Error) -> Result<(), E>,
E: Into<crate::Error>,
{
type Error = E;
fn try_handle_error(&self, error: Error) -> Result<(), Self::Error> {
self.0.borrow_mut()(error)
}
}
pub trait IntoThreadUnsafeAdHocMutFallibleDropStrategy<E: Into<anyhow::Error>>:
FnMut(crate::Error) -> Result<(), E> + Sized
{
fn into_drop_strategy(self) -> ThreadUnsafeAdHocMutFallibleDropStrategy<Self, E> {
ThreadUnsafeAdHocMutFallibleDropStrategy::new(self)
}
}
impl<T, E> IntoThreadUnsafeAdHocMutFallibleDropStrategy<E> for T
where
T: FnMut(crate::Error) -> Result<(), E>,
E: Into<crate::Error>,
{}
#[cfg(test)]
mod tests {
use std::cell::Cell;
use std::rc::Rc;
use crate::drop_strategies::PanicDropStrategy;
use crate::test_utils::fallible;
use super::*;
#[test]
fn test_thread_unsafe_adhoc_mut_drop_strategy() {
let works = Rc::new(Cell::new(false));
let w = Rc::clone(&works);
let strategy = ThreadUnsafeAdHocMutDropStrategy::new(move |_| w.set(true));
crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.get());
}
#[test]
fn test_into_thread_unsafe_adhoc_mut_drop_strategy() {
let works = Rc::new(Cell::new(false));
let w = Rc::clone(&works);
let strategy = move |_| w.set(true);
let strategy = IntoThreadUnsafeAdHocMutDropStrategy::into_drop_strategy(strategy);
crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.get());
}
#[test]
fn test_thread_unsafe_adhoc_mut_fallible_drop_strategy() {
let works = Rc::new(Cell::new(false));
let w = Rc::clone(&works);
let strategy = ThreadUnsafeAdHocMutFallibleDropStrategy::<_, crate::Error>::new(move |_| {
w.set(true);
Ok(())
});
crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.get());
}
#[test]
fn test_into_thread_unsafe_adhoc_mut_fallible_drop_strategy() {
let works = Rc::new(Cell::new(false));
let w = Rc::clone(&works);
let strategy = move |_| {
w.set(true);
Ok::<_, crate::Error>(())
};
let strategy = IntoThreadUnsafeAdHocMutFallibleDropStrategy::into_drop_strategy(strategy);
crate::install_thread_local_handlers(strategy, PanicDropStrategy::DEFAULT);
drop(fallible());
assert!(works.get());
}
}