1use serde::{Deserialize, Serialize};
2use std::{fmt, ops, sync::Arc};
3
4#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
11#[repr(transparent)]
12pub struct SharedCow<T: Clone>(Arc<T>);
13
14impl<T: Clone> SharedCow<T> {
15 pub fn new(value: T) -> SharedCow<T> {
17 SharedCow(Arc::new(value))
18 }
19
20 pub fn try_into_owned(self: SharedCow<T>) -> Result<T, SharedCow<T>> {
25 Arc::try_unwrap(self.0).map_err(SharedCow)
26 }
27
28 pub fn into_owned(self: SharedCow<T>) -> T {
30 match self.try_into_owned() {
31 Ok(value) => value,
32 Err(shared) => (*shared.0).clone(),
33 }
34 }
35
36 pub fn to_mut(&mut self) -> &mut T {
39 Arc::make_mut(&mut self.0)
40 }
41
42 pub fn into_arc(value: SharedCow<T>) -> Arc<T> {
44 value.0
45 }
46
47 pub fn ref_count(value: &SharedCow<T>) -> usize {
49 Arc::strong_count(&value.0)
50 }
51}
52
53impl<T> From<T> for SharedCow<T>
54where
55 T: Clone,
56{
57 fn from(value: T) -> Self {
58 SharedCow::new(value)
59 }
60}
61
62impl<T> From<Arc<T>> for SharedCow<T>
63where
64 T: Clone,
65{
66 fn from(value: Arc<T>) -> Self {
67 SharedCow(value)
68 }
69}
70
71impl<T> fmt::Debug for SharedCow<T>
72where
73 T: fmt::Debug + Clone,
74{
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 (*self.0).fmt(f)
78 }
79}
80
81impl<T> fmt::Display for SharedCow<T>
82where
83 T: fmt::Display + Clone,
84{
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 (*self.0).fmt(f)
87 }
88}
89
90impl<T: Clone> Serialize for SharedCow<T>
91where
92 T: Serialize,
93{
94 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
95 where
96 S: serde::Serializer,
97 {
98 self.0.serialize(serializer)
99 }
100}
101
102impl<'de, T: Clone> Deserialize<'de> for SharedCow<T>
103where
104 T: Deserialize<'de>,
105{
106 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
107 where
108 D: serde::Deserializer<'de>,
109 {
110 T::deserialize(deserializer).map(Arc::new).map(SharedCow)
111 }
112}
113
114impl<T: Clone> ops::Deref for SharedCow<T> {
115 type Target = T;
116
117 fn deref(&self) -> &Self::Target {
118 &self.0
119 }
120}
121
122impl<T: Clone> AsRef<[T]> for SharedCow<Vec<T>> {
123 fn as_ref(&self) -> &[T] {
124 self.as_slice()
125 }
126}
127
128impl<T: Clone> IntoIterator for SharedCow<Vec<T>> {
129 type Item = T;
130 type IntoIter = std::vec::IntoIter<T>;
131
132 fn into_iter(self) -> Self::IntoIter {
133 self.into_owned().into_iter()
134 }
135}
136
137impl<'a, T: Clone> IntoIterator for &'a SharedCow<Vec<T>> {
138 type Item = &'a T;
139 type IntoIter = std::slice::Iter<'a, T>;
140
141 fn into_iter(self) -> Self::IntoIter {
142 self.iter()
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn try_into_owned_returns_unique_value() {
152 let value = vec![1, 2, 3];
153 let original_ptr = value.as_ptr();
154 let shared = SharedCow::new(value);
155
156 let Ok(owned) = shared.try_into_owned() else {
157 panic!("value should be uniquely owned");
158 };
159
160 assert_eq!(owned.as_ptr(), original_ptr);
161 }
162
163 #[test]
164 fn try_into_owned_returns_shared_value_without_cloning() {
165 let shared = SharedCow::new(vec![1, 2, 3]);
166 let original_ptr = shared.as_ptr();
167 let clone = shared.clone();
168
169 let Err(still_shared) = clone.try_into_owned() else {
170 panic!("value should still be shared");
171 };
172
173 assert_eq!(still_shared.as_ptr(), original_ptr);
174 assert_eq!(SharedCow::ref_count(&still_shared), 2);
175 }
176}