Skip to main content

drop_tracker/
itemtraits.rs

1use crate::DropItem;
2use crate::DroppedError;
3use crate::State;
4use std::borrow::Borrow;
5use std::borrow::BorrowMut;
6use std::cmp::Ordering;
7use std::fmt;
8use std::hash;
9use std::ops::Deref;
10use std::ops::DerefMut;
11
12impl<V> DropItem<V> {
13    fn inner_ref(&self) -> &V {
14        self.try_inner_ref().expect("cannot borrow value")
15    }
16
17    fn try_inner_ref(&self) -> Result<&V, DroppedError> {
18        match self.state {
19            Some(ref state) if state.is_alive() => {
20                // SAFETY: The item is alive. It is possible that another thread may have dropped
21                // the item since we last checked, but in that case it's the caller's
22                // responsibility to ensure safety.
23                Ok(unsafe { self.value.assume_init_ref() })
24            }
25            _ => Err(DroppedError),
26        }
27    }
28
29    fn inner_mut(&mut self) -> &mut V {
30        self.try_inner_mut().expect("cannot borrow mutable value")
31    }
32
33    fn try_inner_mut(&mut self) -> Result<&mut V, DroppedError> {
34        match self.state {
35            Some(ref state) if state.is_alive() => {
36                // SAFETY: The item is alive. It is possible that another thread may have dropped
37                // the item since we last checked, but in that case it's the caller's
38                // responsibility to ensure safety.
39                Ok(unsafe { self.value.assume_init_mut() })
40            }
41            _ => Err(DroppedError),
42        }
43    }
44}
45
46impl<V> Deref for DropItem<V> {
47    type Target = V;
48
49    fn deref(&self) -> &Self::Target {
50        self.inner_ref()
51    }
52}
53
54impl<V> DerefMut for DropItem<V> {
55    fn deref_mut(&mut self) -> &mut Self::Target {
56        self.inner_mut()
57    }
58}
59
60macro_rules! impl_ref_trait {
61    () => {};
62    ( impl <{ $( $params:tt )* }> Borrow < $target:ty > for DropItem < $type_bound:ty > ; $( $rest:tt )* ) => {
63        impl<$($params)*> Borrow<$target> for DropItem<$type_bound> {
64            #[inline(always)]
65            fn borrow(&self) -> &$target {
66                self.inner_ref().borrow()
67            }
68        }
69
70        impl_ref_trait! { $($rest)* }
71    };
72    ( impl <{ $( $params:tt )* }> BorrowMut < $target:ty > for DropItem < $type_bound:ty > ; $( $rest:tt )* ) => {
73        impl<$($params)*> BorrowMut<$target> for DropItem<$type_bound> {
74            #[inline(always)]
75            fn borrow_mut(&mut self) -> &mut $target {
76                self.inner_mut().borrow_mut()
77            }
78        }
79
80        impl_ref_trait! { $($rest)* }
81    };
82    ( impl <{ $( $params:tt )* }> AsRef < $target:ty > for DropItem < $type_bound:ty > ; $( $rest:tt )* ) => {
83        impl<$($params)*> AsRef<$target> for DropItem<$type_bound> {
84            #[inline(always)]
85            fn as_ref(&self) -> &$target {
86                self.inner_ref().as_ref()
87            }
88        }
89
90        impl_ref_trait! { $($rest)* }
91    };
92    ( impl <{ $( $params:tt )* }> AsMut < $target:ty > for DropItem < $type_bound:ty > ; $( $rest:tt )* ) => {
93        impl<$($params)*> AsMut<$target> for DropItem<$type_bound> {
94            #[inline(always)]
95            fn as_mut(&mut self) -> &mut $target {
96                self.inner_mut().as_mut()
97            }
98        }
99
100        impl_ref_trait! { $($rest)* }
101    };
102}
103
104impl_ref_trait! {
105    impl<{V}>                       Borrow<V>       for DropItem<V>;
106    impl<{V: Borrow<str>}>          Borrow<str>     for DropItem<V>;
107    impl<{V: Borrow<[T]>, T}>       Borrow<[T]>     for DropItem<V>;
108
109    impl<{V}>                       BorrowMut<V>    for DropItem<V>;
110    impl<{V: BorrowMut<str>}>       BorrowMut<str>  for DropItem<V>;
111    impl<{V: BorrowMut<[T]>, T}>    BorrowMut<[T]>  for DropItem<V>;
112
113    impl<{V: AsRef<T>, T}>          AsRef<T>        for DropItem<V>;
114    impl<{V: AsMut<T>, T}>          AsMut<T>        for DropItem<V>;
115}
116
117impl<V: Eq> Eq for DropItem<V> {}
118
119impl<V: PartialEq<W>, W> PartialEq<DropItem<W>> for DropItem<V> {
120    fn eq(&self, other: &DropItem<W>) -> bool {
121        self.inner_ref().eq(other.inner_ref())
122    }
123}
124
125impl<V: PartialOrd<W>, W> PartialOrd<DropItem<W>> for DropItem<V> {
126    fn partial_cmp(&self, other: &DropItem<W>) -> Option<Ordering> {
127        self.inner_ref().partial_cmp(other.inner_ref())
128    }
129}
130
131macro_rules! impl_cmp_trait {
132    () => {};
133    (
134        impl < $( $lifetime:lifetime , )? $param:ident $( , $extra_param:ident )? >
135        PartialEq + PartialOrd < $other_type:ty >
136        for DropItem < $item_bound:ty > ; $( $rest:tt )*
137    ) => {
138        impl<$($lifetime,)? $param $(, $extra_param)?> PartialEq<$other_type> for DropItem<$item_bound>
139            where $param: PartialEq<$other_type>
140        {
141            fn eq(&self, other: &$other_type) -> bool {
142                self.inner_ref().eq(other)
143            }
144        }
145
146        impl<$($lifetime,)? $param $(, $extra_param)?> PartialOrd<$other_type> for DropItem<$item_bound>
147            where $param: PartialOrd<$other_type>
148        {
149            fn partial_cmp(&self, other: &$other_type) -> Option<Ordering> {
150                self.inner_ref().partial_cmp(other)
151            }
152        }
153
154        impl_cmp_trait! { $($rest)* }
155    };
156}
157
158impl_cmp_trait! {
159    impl<V>         PartialEq+PartialOrd<i8>        for DropItem<V>;
160    impl<V>         PartialEq+PartialOrd<i16>       for DropItem<V>;
161    impl<V>         PartialEq+PartialOrd<i32>       for DropItem<V>;
162    impl<V>         PartialEq+PartialOrd<i64>       for DropItem<V>;
163    impl<V>         PartialEq+PartialOrd<i128>      for DropItem<V>;
164
165    impl<V>         PartialEq+PartialOrd<u8>        for DropItem<V>;
166    impl<V>         PartialEq+PartialOrd<u16>       for DropItem<V>;
167    impl<V>         PartialEq+PartialOrd<u32>       for DropItem<V>;
168    impl<V>         PartialEq+PartialOrd<u64>       for DropItem<V>;
169    impl<V>         PartialEq+PartialOrd<u128>      for DropItem<V>;
170
171    impl<V>         PartialEq+PartialOrd<f32>       for DropItem<V>;
172    impl<V>         PartialEq+PartialOrd<f64>       for DropItem<V>;
173
174    impl<V>         PartialEq+PartialOrd<char>      for DropItem<V>;
175    impl<V>         PartialEq+PartialOrd<bool>      for DropItem<V>;
176    impl<V>         PartialEq+PartialOrd<()>        for DropItem<V>;
177    impl<V>         PartialEq+PartialOrd<str>       for DropItem<V>;
178    impl<'a, V>     PartialEq+PartialOrd<&'a str>   for DropItem<V>;
179    impl<V, T>      PartialEq+PartialOrd<[T]>       for DropItem<V>;
180    impl<'a, V, T>  PartialEq+PartialOrd<&'a [T]>   for DropItem<V>;
181}
182
183impl<V: hash::Hash> hash::Hash for DropItem<V> {
184    fn hash<H: hash::Hasher>(&self, state: &mut H) {
185        self.inner_ref().hash(state)
186    }
187}
188
189impl<V: fmt::Display> fmt::Display for DropItem<V> {
190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191        self.inner_ref().fmt(f)
192    }
193}
194
195impl<V: fmt::Debug> fmt::Debug for DropItem<V> {
196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197        match self.try_inner_ref() {
198            Ok(value) => f
199                .debug_struct("DropItem")
200                .field("value", value)
201                .field("state", &State::Alive)
202                .finish(),
203            Err(_) => f
204                .debug_struct("DropItem")
205                .field("value", &"<dropped>")
206                .field("state", &State::Dropped)
207                .finish(),
208        }
209    }
210}