1use std::{
2 borrow::Cow,
3 cmp::Ordering,
4 fmt::{self, Debug},
5 hash::{Hash, Hasher},
6 sync::Arc,
7};
8
9pub enum ArcCow<'a, T: ?Sized> {
10 Borrowed(&'a T),
11 Owned(Arc<T>),
12}
13
14impl<T: ?Sized + PartialEq> PartialEq for ArcCow<'_, T> {
15 fn eq(&self, other: &Self) -> bool {
16 let a = self.as_ref();
17 let b = other.as_ref();
18 a == b
19 }
20}
21
22impl<T: ?Sized + PartialOrd> PartialOrd for ArcCow<'_, T> {
23 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
24 self.as_ref().partial_cmp(other.as_ref())
25 }
26}
27
28impl<T: ?Sized + Ord> Ord for ArcCow<'_, T> {
29 fn cmp(&self, other: &Self) -> Ordering {
30 self.as_ref().cmp(other.as_ref())
31 }
32}
33
34impl<T: ?Sized + Eq> Eq for ArcCow<'_, T> {}
35
36impl<T: ?Sized + Hash> Hash for ArcCow<'_, T> {
37 fn hash<H: Hasher>(&self, state: &mut H) {
38 match self {
39 Self::Borrowed(borrowed) => Hash::hash(borrowed, state),
40 Self::Owned(owned) => Hash::hash(&**owned, state),
41 }
42 }
43}
44
45impl<T: ?Sized> Clone for ArcCow<'_, T> {
46 fn clone(&self) -> Self {
47 match self {
48 Self::Borrowed(borrowed) => Self::Borrowed(borrowed),
49 Self::Owned(owned) => Self::Owned(owned.clone()),
50 }
51 }
52}
53
54impl<'a, T: ?Sized> From<&'a T> for ArcCow<'a, T> {
55 fn from(s: &'a T) -> Self {
56 Self::Borrowed(s)
57 }
58}
59
60impl<T: ?Sized> From<Arc<T>> for ArcCow<'_, T> {
61 fn from(s: Arc<T>) -> Self {
62 Self::Owned(s)
63 }
64}
65
66impl<T: ?Sized> From<&'_ Arc<T>> for ArcCow<'_, T> {
67 fn from(s: &'_ Arc<T>) -> Self {
68 Self::Owned(s.clone())
69 }
70}
71
72impl From<String> for ArcCow<'_, str> {
73 fn from(value: String) -> Self {
74 Self::Owned(value.into())
75 }
76}
77
78impl From<&String> for ArcCow<'_, str> {
79 fn from(value: &String) -> Self {
80 Self::Owned(value.clone().into())
81 }
82}
83
84impl<'a> From<Cow<'a, str>> for ArcCow<'a, str> {
85 fn from(value: Cow<'a, str>) -> Self {
86 match value {
87 Cow::Borrowed(borrowed) => Self::Borrowed(borrowed),
88 Cow::Owned(owned) => Self::Owned(owned.into()),
89 }
90 }
91}
92
93impl<T> From<Vec<T>> for ArcCow<'_, [T]> {
94 fn from(vec: Vec<T>) -> Self {
95 ArcCow::Owned(Arc::from(vec))
96 }
97}
98
99impl<'a> From<&'a str> for ArcCow<'a, [u8]> {
100 fn from(s: &'a str) -> Self {
101 ArcCow::Borrowed(s.as_bytes())
102 }
103}
104
105impl<T: ?Sized + ToOwned> std::borrow::Borrow<T> for ArcCow<'_, T> {
106 fn borrow(&self) -> &T {
107 match self {
108 ArcCow::Borrowed(borrowed) => borrowed,
109 ArcCow::Owned(owned) => owned.as_ref(),
110 }
111 }
112}
113
114impl<T: ?Sized> std::ops::Deref for ArcCow<'_, T> {
115 type Target = T;
116
117 fn deref(&self) -> &Self::Target {
118 match self {
119 ArcCow::Borrowed(s) => s,
120 ArcCow::Owned(s) => s.as_ref(),
121 }
122 }
123}
124
125impl<T: ?Sized> AsRef<T> for ArcCow<'_, T> {
126 fn as_ref(&self) -> &T {
127 match self {
128 ArcCow::Borrowed(borrowed) => borrowed,
129 ArcCow::Owned(owned) => owned.as_ref(),
130 }
131 }
132}
133
134impl<T: ?Sized + Debug> Debug for ArcCow<'_, T> {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 match self {
137 ArcCow::Borrowed(borrowed) => Debug::fmt(borrowed, f),
138 ArcCow::Owned(owned) => Debug::fmt(&**owned, f),
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146 use std::{borrow::Cow, collections::hash_map::DefaultHasher, collections::HashMap, hash::Hasher};
147
148 #[test]
149 fn test_creation_from_reference() {
150 let value = 42;
151 let arc_cow = ArcCow::from(&value);
152 assert!(matches!(arc_cow, ArcCow::Borrowed(_)));
153 assert_eq!(*arc_cow, 42);
154 }
155
156 #[test]
157 fn test_creation_from_arc() {
158 let value = Arc::new("Hello".to_string());
159 let arc_cow = ArcCow::from(value.clone());
160 assert!(matches!(arc_cow, ArcCow::Owned(_)));
161 assert_eq!(arc_cow.as_ref(), "Hello");
162 }
163
164 #[test]
165 fn test_clone_borrowed() {
166 let value = "borrowed";
167 let arc_cow1 :ArcCow<'static, str>= ArcCow::from(value);
168 let arc_cow2 = arc_cow1.clone();
169
170 assert!(matches!(arc_cow1, ArcCow::Borrowed(_)));
172 assert!(matches!(arc_cow2, ArcCow::Borrowed(_)));
173 assert_eq!(arc_cow1, arc_cow2);
174 }
175
176 #[test]
177 fn test_clone_owned() {
178 let arc_cow1 = ArcCow::from(Arc::new(100));
179 let arc_cow2 = arc_cow1.clone();
180
181 assert!(matches!(arc_cow1, ArcCow::Owned(_)));
183 assert!(matches!(arc_cow2, ArcCow::Owned(_)));
184 assert_eq!(arc_cow1, arc_cow2);
185
186 if let ArcCow::Owned(arc) = &arc_cow1 {
188 let arc_mut = Arc::as_ptr(arc) as *mut i32;
190 unsafe { *arc_mut = 200; } }
192 assert_eq!(arc_cow1, arc_cow2);
193 }
194
195 #[test]
196 fn test_comparison() {
197 let borrowed1 = ArcCow::from("abc");
198 let borrowed2 = ArcCow::from("abc");
199 let owned1 = ArcCow::from("abc".to_string());
200 let different = ArcCow::from("def");
201
202 assert_eq!(borrowed1, borrowed2);
204 assert_eq!(borrowed1, owned1);
205
206 assert_ne!(borrowed1, different);
208
209 assert!(borrowed1 < different);
211 assert!(borrowed1 <= owned1);
212 assert!(different > owned1);
213 }
214
215 #[test]
216 fn test_hashing() {
217 fn calculate_hash<T: Hash>(value: &T) -> u64 {
218 let mut hasher = DefaultHasher::new();
219 value.hash(&mut hasher);
220 hasher.finish()
221 }
222
223 let borrowed_str :ArcCow<'static, str>= ArcCow::from("test");
224 let owned_str = ArcCow::from("test".to_string());
225 let different :ArcCow<'static, str>= ArcCow::from("different");
226
227 assert_eq!(calculate_hash(&borrowed_str), calculate_hash(&owned_str));
229
230 assert_ne!(calculate_hash(&borrowed_str), calculate_hash(&different));
232 }
233
234 #[test]
235 fn test_cow_conversion() {
236 let borrowed_cow = Cow::Borrowed("borrowed");
237 let owned_cow :Cow<'static, str>= Cow::Owned("owned".to_string());
238
239 let borrowed_arc_cow: ArcCow<'_, str> = borrowed_cow.into();
240 let owned_arc_cow: ArcCow<'_, str> = owned_cow.into();
241
242 assert!(matches!(borrowed_arc_cow, ArcCow::Borrowed(_)));
243 assert!(matches!(owned_arc_cow, ArcCow::Owned(_)));
244 assert_eq!(borrowed_arc_cow.as_ref(), "borrowed");
245 assert_eq!(owned_arc_cow.as_ref(), "owned");
246 }
247
248 #[test]
249 fn test_collection_handling() {
250 let mut map = HashMap::new();
251
252 map.insert(ArcCow::from("key1"), 1);
253 map.insert(ArcCow::from("key2".to_string()), 2);
254 assert_eq!(map.get(&ArcCow::from("key1")), Some(&1));
258 assert_eq!(map.get(&ArcCow::from("key2")), Some(&2));
259 assert_eq!(map.get(&ArcCow::from("key4")), None);
263 }
264
265 #[test]
266 fn test_slice_conversions() {
267 let vec = vec![1, 2, 3];
269 let slice: ArcCow<'_, [i32]> = vec.into();
270 assert_eq!(&*slice, &[1, 2, 3]);
271
272 let bytes: ArcCow<'_, [u8]> = "text".into();
274 assert_eq!(&*bytes, b"text");
275 }
276
277 #[test]
278 fn test_debug_output() {
279 let borrowed: ArcCow<'_, str> = "debug".into();
280 let owned: ArcCow<'_, str> = "output".to_string().into();
281
282 assert_eq!(format!("{:?}", borrowed), "\"debug\"");
283 assert_eq!(format!("{:?}", owned), "\"output\"");
284 }
285
286 #[test]
287 fn test_deref_and_as_ref() {
288 let borrowed :ArcCow<'static, i32>= ArcCow::from(&42);
289 let owned = ArcCow::from(Arc::new(100));
290
291 assert_eq!(*borrowed, 42);
293 assert_eq!(*owned, 100);
294
295 let ref_borrowed: &i32 = borrowed.as_ref();
297 let ref_owned: &i32 = owned.as_ref();
298 assert_eq!(*ref_borrowed, 42);
299 assert_eq!(*ref_owned, 100);
300 }
301
302
303
304 #[test]
305 fn test_send_sync() {
306 fn assert_send<T: Send>() {}
307 fn assert_sync<T: Sync>() {}
308
309 assert_send::<ArcCow<'static, str>>();
310 assert_sync::<ArcCow<'static, str>>();
311 }
312
313 #[test]
314 fn test_thread_safety() {
315 let shared = ArcCow::from(Arc::new(100));
316
317 let handle = std::thread::spawn(move || {
318 assert_eq!(*shared, 100);
319 });
320
321 handle.join().unwrap();
322 }
323}
324
325
326
327#[cfg(test)]
329mod tests2 {
330 use super::*;
331 use std::collections::HashSet;
332
333 #[test]
334 fn test_deref_and_as_ref() {
335 let borrowed_str = "hello";
336 let arc_cow_borrowed = ArcCow::Borrowed(borrowed_str);
337 assert_eq!(arc_cow_borrowed.as_ref(), "hello");
338 assert_eq!(arc_cow_borrowed.as_ref(), "hello");
339
340 let owned_string: Arc<str> = Arc::from("world");
341 let arc_cow_owned = ArcCow::Owned(owned_string);
342 assert_eq!(arc_cow_owned.as_ref(), "world");
343 assert_eq!(arc_cow_owned.as_ref(), "world");
344 }
345
346 #[test]
347 fn test_equality() {
348 let s1 = "test";
349 let s2: Arc<str> = Arc::from("test");
350 let s3: Arc<str> = Arc::from("different");
351
352 let borrowed = ArcCow::Borrowed(s1);
353 let owned1 = ArcCow::Owned(s2.clone());
354 let owned2 = ArcCow::Owned(s3.clone());
355
356 assert_eq!(borrowed, owned1);
357 assert_ne!(borrowed, owned2);
358 assert_eq!(ArcCow::from(&s2), owned1);
359 }
360
361 #[test]
362 fn test_ordering() {
363 let s1 = "apple";
364 let s2: Arc<str> = Arc::from("banana");
365 let s3 = "cherry";
366
367 let borrowed1 = ArcCow::Borrowed(s1);
368 let owned = ArcCow::Owned(s2);
369 let borrowed2 = ArcCow::Borrowed(s3);
370
371 assert_eq!(borrowed1.cmp(&owned), Ordering::Less);
372 assert_eq!(owned.cmp(&borrowed1), Ordering::Greater);
373 assert_eq!(borrowed2.cmp(&owned), Ordering::Greater);
374 assert_eq!(borrowed1.cmp(&borrowed1), Ordering::Equal);
375 }
376
377 #[test]
378 fn test_hash() {
379 let mut set = HashSet::new();
380 let s1 = "hashable";
381 let s2: Arc<str> = Arc::from("hashable");
382
383 let borrowed = ArcCow::Borrowed(s1);
384 let owned = ArcCow::Owned(s2);
385
386 set.insert(borrowed);
387 assert!(set.contains(&owned));
388 assert_eq!(set.len(), 1);
389 }
390
391 #[test]
392 fn test_clone() {
393 let borrowed_str = "borrowed";
395 let arc_cow_borrowed = ArcCow::Borrowed(borrowed_str);
396 let cloned_borrowed = arc_cow_borrowed.clone();
397 if let ArcCow::Borrowed(inner) = cloned_borrowed {
398 assert_eq!(inner, "borrowed");
399 } else {
400 panic!("Cloned Borrowed should be Borrowed");
401 }
402 assert_eq!(arc_cow_borrowed.as_ref(), "borrowed");
404
405 let owned_arc: Arc<str> = Arc::from("owned");
407 let arc_cow_owned = ArcCow::Owned(owned_arc);
408 }
411
412 #[test]
413 fn test_from_implementations() {
414 let s_ref = "hello";
416 let cow_from_ref :ArcCow<'static, str>= ArcCow::from(s_ref);
417 assert_eq!(&*cow_from_ref, "hello");
418 assert!(matches!(cow_from_ref, ArcCow::Borrowed(_)));
419
420 let s_arc: Arc<str> = Arc::from("world");
422 let cow_from_arc = ArcCow::from(s_arc.clone());
423 assert_eq!(&*cow_from_arc, "world");
424 assert!(matches!(cow_from_arc, ArcCow::Owned(_)));
425 assert_eq!(Arc::strong_count(&s_arc), 2);
426
427 let string = String::from("string");
429 let cow_from_string = ArcCow::from(string);
430 assert_eq!(&*cow_from_string, "string");
431 assert!(matches!(cow_from_string, ArcCow::Owned(_)));
432
433 let borrowed_cow: Cow<str> = Cow::Borrowed("cow_borrowed");
435 let arc_cow_from_borrowed_cow = ArcCow::from(borrowed_cow);
436 assert_eq!(&*arc_cow_from_borrowed_cow, "cow_borrowed");
437 assert!(matches!(arc_cow_from_borrowed_cow, ArcCow::Borrowed(_)));
438
439 let owned_cow: Cow<str> = Cow::Owned(String::from("cow_owned"));
440 let arc_cow_from_owned_cow = ArcCow::from(owned_cow);
441 assert_eq!(&*arc_cow_from_owned_cow, "cow_owned");
442 assert!(matches!(arc_cow_from_owned_cow, ArcCow::Owned(_)));
443
444 let vec = vec![1, 2, 3];
446 let cow_from_vec = ArcCow::from(vec);
447 assert_eq!(&*cow_from_vec, &[1, 2, 3]);
448 assert!(matches!(cow_from_vec, ArcCow::Owned(_)));
449 }
450
451 #[test]
452 fn test_debug_format() {
453 let borrowed = ArcCow::Borrowed("debug");
454 assert_eq!(format!("{:?}", borrowed), "\"debug\"");
455
456 let owned: ArcCow<str> = ArcCow::Owned(Arc::from("debug"));
457 assert_eq!(format!("{:?}", owned), "\"debug\"");
458 }
459
460 trait ArcCowExt<T: ?Sized> {
462 fn into_arc(self) -> Arc<T>;
463 }
464
465 impl<T: ?Sized + Clone> ArcCowExt<T> for ArcCow<'_, T>
466 where
467 T: ToOwned<Owned = T>,
468 {
469 fn into_arc(self) -> Arc<T> {
470 match self {
471 ArcCow::Borrowed(b) => Arc::new(b.to_owned()),
472 ArcCow::Owned(o) => o,
473 }
474 }
475 }
476}