use std::fmt::{Debug, Display}; use std::hash::Hash; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use crate::Keyable; use super::{PoisonFlag, PoisonGuard, PoisonRef}; impl<'a, Guard> PoisonRef<'a, Guard> { // This is used so that we don't keep accidentally adding the flag reference pub(super) const fn new(flag: &'a PoisonFlag, guard: Guard) -> Self { Self { guard, #[cfg(panic = "unwind")] flag, _phantom: PhantomData, } } } impl Drop for PoisonRef<'_, Guard> { fn drop(&mut self) { #[cfg(panic = "unwind")] if std::thread::panicking() { self.flag.poison(); } } } impl PartialEq for PoisonRef<'_, Guard> { fn eq(&self, other: &Self) -> bool { self.guard.eq(&other.guard) } } impl PartialOrd for PoisonRef<'_, Guard> { fn partial_cmp(&self, other: &Self) -> Option { self.guard.partial_cmp(&other.guard) } } impl Eq for PoisonRef<'_, Guard> {} impl Ord for PoisonRef<'_, Guard> { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.guard.cmp(&other.guard) } } #[mutants::skip] // hashing involves RNG and is hard to test impl Hash for PoisonRef<'_, Guard> { fn hash(&self, state: &mut H) { self.guard.hash(state) } } #[mutants::skip] impl Debug for PoisonRef<'_, Guard> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) } } impl Display for PoisonRef<'_, Guard> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } } impl Deref for PoisonRef<'_, Guard> { type Target = Guard; fn deref(&self) -> &Self::Target { &self.guard } } impl DerefMut for PoisonRef<'_, Guard> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.guard } } impl AsRef for PoisonRef<'_, Guard> { fn as_ref(&self) -> &Guard { &self.guard } } impl AsMut for PoisonRef<'_, Guard> { fn as_mut(&mut self) -> &mut Guard { &mut self.guard } } #[mutants::skip] // it's hard to get two guards safely impl PartialEq for PoisonGuard<'_, '_, Guard, Key> { fn eq(&self, other: &Self) -> bool { self.guard.eq(&other.guard) } } #[mutants::skip] // it's hard to get two guards safely impl PartialOrd for PoisonGuard<'_, '_, Guard, Key> { fn partial_cmp(&self, other: &Self) -> Option { self.guard.partial_cmp(&other.guard) } } #[mutants::skip] // it's hard to get two guards safely impl Eq for PoisonGuard<'_, '_, Guard, Key> {} #[mutants::skip] // it's hard to get two guards safely impl Ord for PoisonGuard<'_, '_, Guard, Key> { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.guard.cmp(&other.guard) } } #[mutants::skip] // hashing involves RNG and is hard to test impl Hash for PoisonGuard<'_, '_, Guard, Key> { fn hash(&self, state: &mut H) { self.guard.hash(state) } } #[mutants::skip] impl Debug for PoisonGuard<'_, '_, Guard, Key> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&self.guard, f) } } impl Display for PoisonGuard<'_, '_, Guard, Key> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&self.guard, f) } } impl, Key: Keyable> Deref for PoisonGuard<'_, '_, Guard, Key> { type Target = T; fn deref(&self) -> &Self::Target { #[allow(clippy::explicit_auto_deref)] // fixing this results in a compiler error &*self.guard.guard } } impl, Key: Keyable> DerefMut for PoisonGuard<'_, '_, Guard, Key> { fn deref_mut(&mut self) -> &mut Self::Target { #[allow(clippy::explicit_auto_deref)] // fixing this results in a compiler error &mut *self.guard.guard } } impl AsRef for PoisonGuard<'_, '_, Guard, Key> { fn as_ref(&self) -> &Guard { &self.guard.guard } } impl AsMut for PoisonGuard<'_, '_, Guard, Key> { fn as_mut(&mut self) -> &mut Guard { &mut self.guard.guard } }