#[cfg(feature = "ds-write")]
mod imp {
use super::ShimPrimaryHandler;
use crate::drop_strategies::WriteDropStrategy;
use crate::handlers::common::handler::CommonHandler;
use crate::handlers::common::shim::UseDefaultOnUninitShim;
use crate::handlers::common::Primary;
use crate::FallibleTryDropStrategy;
use once_cell::sync::Lazy;
use std::io;
pub type DefaultOnUninit = UseDefaultOnUninitShim<Primary>;
impl ShimPrimaryHandler<DefaultOnUninit> {
pub const DEFAULT: Self = Self::USE_DEFAULT_ON_UNINIT;
}
impl ShimPrimaryHandler<UseDefaultOnUninitShim<Primary>> {
#[allow(clippy::declare_interior_mutable_const)]
pub const USE_DEFAULT_ON_UNINIT: Self = Self {
global: CommonHandler::FLAG_ON_UNINIT,
thread_local: CommonHandler::FLAG_ON_UNINIT,
extra_data: Lazy::new(|| {
let mut strategy = WriteDropStrategy::stderr();
strategy.prelude("error: ");
strategy
}),
};
pub const fn use_default_on_uninit() -> Self {
Self::USE_DEFAULT_ON_UNINIT
}
fn cache(&self) -> &WriteDropStrategy<io::Stderr> {
&self.extra_data
}
}
impl FallibleTryDropStrategy for ShimPrimaryHandler<UseDefaultOnUninitShim<Primary>> {
type Error = anyhow::Error;
fn try_handle_error(&self, error: crate::Error) -> Result<(), Self::Error> {
self.on_all_uninit(error, |_, error| {
self.cache()
.try_handle_error(error.into())
.map_err(Into::into)
})
}
}
}
#[cfg(not(feature = "ds-write"))]
mod imp {
use super::ShimPrimaryHandler;
use crate::handlers::on_uninit::PanicOnUninit;
pub type DefaultOnUninit = PanicOnUninit;
impl ShimPrimaryHandler<DefaultOnUninit> {
pub const DEFAULT: Self = Self::PANIC_ON_UNINIT;
}
}
use crate::adapters::ArcError;
use crate::handlers::common::handler::CommonShimHandler;
use crate::handlers::common::shim::OnUninitShim;
use crate::handlers::common::Primary;
use crate::handlers::on_uninit::{DoNothingOnUninit, ErrorOnUninit, FlagOnUninit, PanicOnUninit};
use crate::FallibleTryDropStrategy;
pub use imp::DefaultOnUninit;
pub type ShimPrimaryHandler<OU = DefaultOnUninit> = CommonShimHandler<OU, Primary>;
pub static DEFAULT_SHIM_PRIMARY_HANDLER: ShimPrimaryHandler = ShimPrimaryHandler::DEFAULT;
impl<OU: OnUninitShim> ShimPrimaryHandler<OU> {
fn on_all_uninit(
&self,
error: anyhow::Error,
f: impl FnOnce(anyhow::Error, ArcError) -> anyhow::Result<()>,
) -> anyhow::Result<()> {
let error = ArcError::new(error);
match self
.thread_local
.try_handle_error(ArcError::clone(&error).into())
{
Ok(()) => Ok(()),
Err(_) if self.thread_local.last_drop_failed() => {
match self.global.try_handle_error(ArcError::clone(&error).into()) {
Ok(()) => Ok(()),
Err(uninit_error) if self.global.last_drop_failed() => f(uninit_error, error),
Err(error) => Err(error),
}
}
Err(error) => Err(error),
}
}
}
impl FallibleTryDropStrategy for ShimPrimaryHandler<ErrorOnUninit> {
type Error = anyhow::Error;
fn try_handle_error(&self, error: crate::Error) -> Result<(), Self::Error> {
self.on_all_uninit(error, |uninit_error, _| Err(uninit_error))
}
}
impl FallibleTryDropStrategy for ShimPrimaryHandler<PanicOnUninit> {
type Error = anyhow::Error;
fn try_handle_error(&self, error: crate::Error) -> Result<(), Self::Error> {
self.on_all_uninit(
error,
|_, error| panic!("neither the thread local nor the global primary handlers are initialized (but here's the drop error anyway: {error})")
)
}
}
impl FallibleTryDropStrategy for ShimPrimaryHandler<DoNothingOnUninit> {
type Error = anyhow::Error;
fn try_handle_error(&self, error: crate::Error) -> Result<(), Self::Error> {
self.on_all_uninit(error, |_, _| Ok(()))
}
}
impl FallibleTryDropStrategy for ShimPrimaryHandler<FlagOnUninit> {
type Error = anyhow::Error;
fn try_handle_error(&self, error: crate::Error) -> Result<(), Self::Error> {
let mut last_drop_failed = false;
let result = self.on_all_uninit(error, |uninit_error, _| {
last_drop_failed = true;
Err(uninit_error)
});
self.set_last_drop_failed(last_drop_failed);
result
}
}