Skip to main content

arc_cow/
lib.rs

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        // 克隆后仍为 Borrowed
171        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        // 克隆后仍为 Owned
182        assert!(matches!(arc_cow1, ArcCow::Owned(_)));
183        assert!(matches!(arc_cow2, ArcCow::Owned(_)));
184        assert_eq!(arc_cow1, arc_cow2);
185        
186        // 修改原始值影响副本
187        if let ArcCow::Owned(arc) = &arc_cow1 {
188            // 类型是 Arc<T>,但我们需要可变引用来修改,所以需要强转
189            let arc_mut = Arc::as_ptr(arc) as *mut i32;
190            unsafe { *arc_mut = 200; } // 不安全操作,仅用于测试
191        }
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        // 同值比较
203        assert_eq!(borrowed1, borrowed2);
204        assert_eq!(borrowed1, owned1);
205        
206        // 异值比较
207        assert_ne!(borrowed1, different);
208        
209        // 排序
210        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        // 相同内容不同变体应该具有相同哈希
228        assert_eq!(calculate_hash(&borrowed_str), calculate_hash(&owned_str));
229        
230        // 不同内容应该不同哈希
231        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        // map.insert(ArcCow::from(Arc::new("key3")), 3);
255        
256        // 混合类型键查询
257        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("key3")), Some(&3));
260        
261        // 值查询
262        assert_eq!(map.get(&ArcCow::from("key4")), None);
263    }
264
265    #[test]
266    fn test_slice_conversions() {
267        // Vec 转切片
268        let vec = vec![1, 2, 3];
269        let slice: ArcCow<'_, [i32]> = vec.into();
270        assert_eq!(&*slice, &[1, 2, 3]);
271        
272        // &str 转 [u8]
273        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        // 解引用
292        assert_eq!(*borrowed, 42);
293        assert_eq!(*owned, 100);
294        
295        // as_ref
296        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// ...existing code...
328#[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        // Clone Borrowed
394        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        // Ensure original is not moved
403        assert_eq!(arc_cow_borrowed.as_ref(), "borrowed");
404
405        // Clone Owned
406        let owned_arc: Arc<str> = Arc::from("owned");
407        let arc_cow_owned = ArcCow::Owned(owned_arc);
408        // assert_eq!(Arc::strong_count(arc_cow_owned.clone().into_arc()), 2);
409        // assert_eq!(Arc::strong_count(&arc_cow_owned.into_arc()), 1);
410    }
411
412    #[test]
413    fn test_from_implementations() {
414        // From<&'a T>
415        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        // From<Arc<T>>
421        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        // From<String> for ArcCow<'_, str>
428        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        // From<Cow<'a, str>>
434        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        // From<Vec<T>> for ArcCow<'_, [T]>
445        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    // Helper extension trait for tests
461    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}