use std::sync::Arc; #[derive(PartialEq, Eq)] pub enum ArcCow<'a, T: ?Sized> { Borrowed(&'a T), Owned(Arc), } use std::hash::{Hash, Hasher}; impl<'a, T: ?Sized + Hash> Hash for ArcCow<'a, T> { fn hash(&self, state: &mut H) { match self { Self::Borrowed(borrowed) => Hash::hash(borrowed, state), Self::Owned(owned) => Hash::hash(&**owned, state), } } } impl<'a, T: ?Sized> Clone for ArcCow<'a, T> { fn clone(&self) -> Self { match self { Self::Borrowed(borrowed) => Self::Borrowed(borrowed), Self::Owned(owned) => Self::Owned(owned.clone()), } } } impl<'a, T: ?Sized> From<&'a T> for ArcCow<'a, T> { fn from(s: &'a T) -> Self { Self::Borrowed(s) } } impl From> for ArcCow<'_, T> { fn from(s: Arc) -> Self { Self::Owned(s) } } impl From for ArcCow<'_, str> { fn from(value: String) -> Self { Self::Owned(value.into()) } } impl<'a, T: ?Sized + ToOwned> std::borrow::Borrow for ArcCow<'a, T> { fn borrow(&self) -> &T { match self { ArcCow::Borrowed(borrowed) => borrowed, ArcCow::Owned(owned) => owned.as_ref(), } } } impl std::ops::Deref for ArcCow<'_, T> { type Target = T; fn deref(&self) -> &Self::Target { match self { ArcCow::Borrowed(s) => s, ArcCow::Owned(s) => s.as_ref(), } } } impl AsRef for ArcCow<'_, T> { fn as_ref(&self) -> &T { match self { ArcCow::Borrowed(borrowed) => borrowed, ArcCow::Owned(owned) => owned.as_ref(), } } }