1#[cfg(feature = "std")]
4mod arc_error {
5    use std::error::Error;
6    use std::fmt;
7    use std::sync::Arc;
8
9    #[derive(Debug, Clone)]
12    pub struct ArcError(pub Arc<crate::Error>);
13
14    impl ArcError {
15        pub fn new(error: crate::Error) -> Self {
17            ArcError(Arc::new(error))
18        }
19    }
20
21    impl fmt::Display for ArcError {
22        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23            self.0.fmt(f)
24        }
25    }
26
27    impl Error for ArcError {}
28}
29
30#[cfg(feature = "std")]
31pub use arc_error::ArcError;
32
33use crate::{
34    DynFallibleTryDropStrategy, FallibleTryDropStrategy, PureTryDrop, RepeatableTryDrop,
35    TryDropStrategy,
36};
37
38#[allow(unused_imports)] use crate::TryDrop;
40
41use core::marker::PhantomData;
42
43#[cfg_attr(
48    feature = "derives",
49    derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)
50)]
51#[cfg_attr(feature = "shrinkwraprs", derive(Shrinkwrap))]
52pub struct InfallibleToFallibleTryDropStrategyAdapter<T: TryDropStrategy, E: Into<anyhow::Error>> {
53    #[cfg_attr(feature = "shrinkwraprs", shrinkwrap(main_field))]
55    pub inner: T,
56
57    _error: PhantomData<E>,
58}
59
60impl<T: TryDropStrategy, E: Into<anyhow::Error>> InfallibleToFallibleTryDropStrategyAdapter<T, E> {
61    pub fn new(value: T) -> Self {
63        Self {
64            inner: value,
65            _error: PhantomData,
66        }
67    }
68
69    #[cfg(feature = "shrinkwraprs")]
71    pub fn take(this: Self) -> T {
72        this.inner
73    }
74}
75
76impl<T: TryDropStrategy, E: Into<anyhow::Error>> FallibleTryDropStrategy
77    for InfallibleToFallibleTryDropStrategyAdapter<T, E>
78{
79    type Error = E;
80
81    fn try_handle_error(&self, error: anyhow::Error) -> Result<(), Self::Error> {
82        self.inner.handle_error(error);
83        Ok(())
84    }
85}
86
87#[cfg_attr(
90    feature = "derives",
91    derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
92)]
93#[cfg_attr(feature = "shrinkwraprs", derive(Shrinkwrap))]
94#[cfg_attr(feature = "shrinkwraprs", shrinkwrap(mutable))]
95pub struct RepeatableTryDropAdapter<T: PureTryDrop> {
96    #[cfg_attr(feature = "shrinkwraprs", shrinkwrap(main_field))]
98    pub inner: T,
99
100    dropped: bool,
101    panic_on_double_drop: bool,
102}
103
104impl<T: PureTryDrop + Default> Default for RepeatableTryDropAdapter<T> {
105    fn default() -> Self {
106        Self::new(T::default())
107    }
108}
109
110impl<T: PureTryDrop> RepeatableTryDropAdapter<T> {
111    pub fn new(item: T) -> Self {
113        Self {
114            inner: item,
115            dropped: false,
116            panic_on_double_drop: true,
117        }
118    }
119}
120
121#[cfg(not(feature = "shrinkwraprs"))]
122impl<T: PureTryDrop> RepeatableTryDropAdapter<T> {
123    pub fn with_panic_on_double_drop(mut self, panic_on_double_drop: bool) -> Self {
126        self.panic_on_double_drop = panic_on_double_drop;
127        self
128    }
129
130    pub fn dropped(&self) -> bool {
132        self.dropped
133    }
134
135    pub fn panic_on_double_drop(&self) -> bool {
137        self.panic_on_double_drop
138    }
139}
140
141#[cfg(feature = "shrinkwraprs")]
142impl<T: PureTryDrop> RepeatableTryDropAdapter<T> {
143    pub fn with_panic_on_double_drop(mut this: Self, panic_on_double_drop: bool) -> Self {
146        this.panic_on_double_drop = panic_on_double_drop;
147        this
148    }
149
150    pub fn dropped(this: &Self) -> bool {
152        this.dropped
153    }
154
155    pub fn panic_on_double_drop(this: &Self) -> bool {
157        this.panic_on_double_drop
158    }
159
160    pub fn take(this: Self) -> T {
162        this.inner
163    }
164}
165
166impl<T: PureTryDrop> PureTryDrop for RepeatableTryDropAdapter<T> {
167    type Error = T::Error;
168    type FallbackTryDropStrategy = T::FallbackTryDropStrategy;
169    type TryDropStrategy = T::TryDropStrategy;
170
171    fn fallback_try_drop_strategy(&self) -> &Self::FallbackTryDropStrategy {
172        self.inner.fallback_try_drop_strategy()
173    }
174
175    fn try_drop_strategy(&self) -> &Self::TryDropStrategy {
176        self.inner.try_drop_strategy()
177    }
178
179    unsafe fn try_drop(&mut self) -> Result<(), Self::Error> {
180        if self.dropped && self.panic_on_double_drop {
181            panic!("tried to drop object twice, this is an invalid operation")
182        } else {
183            self.inner.try_drop()?;
184            self.dropped = true;
185            Ok(())
186        }
187    }
188}
189
190unsafe impl<T: PureTryDrop> RepeatableTryDrop for RepeatableTryDropAdapter<T> {}
192
193#[cfg_attr(
204    feature = "derives",
205    derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
206)]
207#[cfg_attr(feature = "shrinkwraprs", derive(Shrinkwrap))]
208#[cfg_attr(feature = "shrinkwraprs", shrinkwrap(mutable))]
209pub struct DropAdapter<TD: PureTryDrop>(pub TD);
210
211impl<TD: PureTryDrop> Drop for DropAdapter<TD> {
212    fn drop(&mut self) {
213        let result = unsafe { self.0.try_drop() };
215        if let Err(error) = result {
216            let handler = FallbackTryDropStrategyHandler::new(
217                TryDropStrategyRef(self.0.fallback_try_drop_strategy()),
218                FallibleTryDropStrategyRef(self.0.try_drop_strategy()),
219            );
220
221            handler.handle_error(error.into())
222        }
223    }
224}
225
226impl<RTD: RepeatableTryDrop> PureTryDrop for DropAdapter<RTD> {
227    type Error = RTD::Error;
228    type FallbackTryDropStrategy = RTD::FallbackTryDropStrategy;
229    type TryDropStrategy = RTD::TryDropStrategy;
230
231    fn fallback_try_drop_strategy(&self) -> &Self::FallbackTryDropStrategy {
232        self.0.fallback_try_drop_strategy()
233    }
234
235    fn try_drop_strategy(&self) -> &Self::TryDropStrategy {
236        self.0.try_drop_strategy()
237    }
238
239    unsafe fn try_drop(&mut self) -> Result<(), Self::Error> {
240        self.0.try_drop()
241    }
242}
243
244unsafe impl<RTD: RepeatableTryDrop> RepeatableTryDrop for DropAdapter<RTD> {}
247
248impl<TD: PureTryDrop> From<TD> for DropAdapter<TD> {
249    fn from(t: TD) -> Self {
250        t.adapt()
251    }
252}
253
254#[cfg_attr(
257    feature = "derives",
258    derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
259)]
260#[cfg_attr(feature = "shrinkwraprs", derive(Shrinkwrap))]
261pub struct FallibleTryDropStrategyRef<'a, T: FallibleTryDropStrategy>(pub &'a T);
262
263impl<'a, T: FallibleTryDropStrategy> FallibleTryDropStrategy for FallibleTryDropStrategyRef<'a, T> {
264    type Error = T::Error;
265
266    fn try_handle_error(&self, error: anyhow::Error) -> Result<(), Self::Error> {
267        self.0.try_handle_error(error)
268    }
269}
270
271#[cfg_attr(
274    feature = "derives",
275    derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)
276)]
277#[cfg_attr(feature = "shrinkwraprs", derive(Shrinkwrap))]
278pub struct TryDropStrategyRef<'a, T: TryDropStrategy>(pub &'a T);
279
280impl<'a, T: TryDropStrategy> TryDropStrategy for TryDropStrategyRef<'a, T> {
281    fn handle_error(&self, error: anyhow::Error) {
282        self.0.handle_error(error)
283    }
284}
285
286#[cfg_attr(
292    feature = "derives",
293    derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)
294)]
295pub struct FallbackTryDropStrategyHandler<FDS, FTDS>
296where
297    FDS: TryDropStrategy,
298    FTDS: FallibleTryDropStrategy,
299{
300    pub fallback_try_drop_strategy: FDS,
303
304    pub fallible_try_drop_strategy: FTDS,
306}
307
308impl<FDS, FTDS> FallbackTryDropStrategyHandler<FDS, FTDS>
309where
310    FDS: TryDropStrategy,
311    FTDS: FallibleTryDropStrategy,
312{
313    pub fn new(fallback_try_drop_strategy: FDS, fallible_try_drop_strategy: FTDS) -> Self {
315        Self {
316            fallback_try_drop_strategy,
317            fallible_try_drop_strategy,
318        }
319    }
320}
321
322impl<FDS, FTDS> TryDropStrategy for FallbackTryDropStrategyHandler<FDS, FTDS>
323where
324    FDS: TryDropStrategy,
325    FTDS: FallibleTryDropStrategy,
326{
327    fn handle_error(&self, error: anyhow::Error) {
328        if let Err(error) = self.fallible_try_drop_strategy.dyn_try_handle_error(error) {
329            self.fallback_try_drop_strategy.handle_error(error)
330        }
331    }
332}