use serde::{Deserialize, Serialize}; use std::{fmt, ops, sync::Arc}; /// A container that transparently shares a value when possible, but clones on mutate. /// /// Unlike `Arc`, this is only intended to help save memory usage and reduce the amount of effort /// required to clone unmodified values with easy to use copy-on-write. /// /// This should more or less reflect the API of [`std::borrow::Cow`] as much as is sensible. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[repr(transparent)] pub struct SharedCow(Arc); impl SharedCow { /// Create a new `Shared` value. pub fn new(value: T) -> SharedCow { SharedCow(Arc::new(value)) } /// Take an exclusive clone of the shared value, or move and take ownership if it wasn't shared. pub fn into_owned(self: SharedCow) -> T { // Optimized: if the Arc is not shared, just unwraps the Arc match Arc::try_unwrap(self.0) { Ok(value) => value, Err(arc) => (*arc).clone(), } } /// Get a mutable reference to the value inside the [`SharedCow`]. This will result in a clone /// being created only if the value was shared with multiple references. pub fn to_mut(&mut self) -> &mut T { Arc::make_mut(&mut self.0) } /// Convert the `Shared` value into an `Arc` pub fn into_arc(value: SharedCow) -> Arc { value.0 } /// Return the number of references to the shared value. pub fn ref_count(value: &SharedCow) -> usize { Arc::strong_count(&value.0) } } impl From for SharedCow where T: Clone, { fn from(value: T) -> Self { SharedCow::new(value) } } impl From> for SharedCow where T: Clone, { fn from(value: Arc) -> Self { SharedCow(value) } } impl fmt::Debug for SharedCow where T: fmt::Debug + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Appears transparent (*self.0).fmt(f) } } impl fmt::Display for SharedCow where T: fmt::Display + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (*self.0).fmt(f) } } impl Serialize for SharedCow where T: Serialize, { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { self.0.serialize(serializer) } } impl<'de, T: Clone> Deserialize<'de> for SharedCow where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { T::deserialize(deserializer).map(Arc::new).map(SharedCow) } } impl ops::Deref for SharedCow { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } }