compact_rc/
arc.rs

1use std::borrow;
2use std::borrow::Cow;
3use std::cmp::Ordering;
4use std::ffi::{CStr, CString};
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::iter;
8use std::ops::Deref;
9use std::pin::Pin;
10use std::sync::atomic::{AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize};
11
12use crate::base::RcBase;
13use crate::refcount::RefCount;
14
15/// ArcX with u8 counter
16pub type Arc8<T> = ArcX<T, AtomicU8>;
17/// ArcX with u16 counter
18pub type Arc16<T> = ArcX<T, AtomicU16>;
19/// ArcX with u32 counter
20pub type Arc32<T> = ArcX<T, AtomicU32>;
21/// ArcX with u64 counter
22pub type Arc64<T> = ArcX<T, AtomicU64>;
23/// ArcX with usize counter
24pub type Arc<T> = ArcX<T, AtomicUsize>;
25
26/// Low-memory version of [std::sync::Arc].
27///
28/// This type provides almost the same methods as standard `Arc`.
29/// See [the top page](crate) for about differences from the standard `Arc`.
30///
31/// There are aliases for simplicity.
32/// - [Arc]
33/// - [Arc8]
34/// - [Arc16]
35/// - [Arc32]
36/// - [Arc64]
37pub struct ArcX<T: ?Sized, C>(RcBase<T, C>)
38where
39    C: RefCount + Sync + Send;
40
41impl<T, C> ArcX<T, C>
42where
43    C: RefCount + Sync + Send,
44{
45    /// See [std::sync::Arc::new].
46    #[inline]
47    pub fn new(value: T) -> ArcX<T, C> {
48        ArcX(RcBase::new(value))
49    }
50
51    /// See [std::sync::Arc::pin].
52    #[inline]
53    pub fn pin(value: T) -> Pin<ArcX<T, C>> {
54        unsafe { Pin::new_unchecked(Self::new(value)) }
55    }
56
57    /// See [std::sync::Arc::try_unwrap].
58    #[inline]
59    pub fn try_unwrap(this: Self) -> Result<T, Self> {
60        RcBase::try_unwrap(this.0).map_err(Self)
61    }
62
63    /// See [std::sync::Arc::from_raw].
64    ///
65    /// # Incompatibility
66    /// Unlike the standard `Arc`, this method does not support dynamically sized types (DSTs)
67    /// because some unstabilized features are required to implement this for DSTs.
68    #[inline]
69    pub unsafe fn from_raw(ptr: *const T) -> Self {
70        Self(RcBase::from_raw(ptr))
71    }
72
73    /// See [std::sync::Arc::increment_strong_count].
74    #[inline]
75    pub unsafe fn increment_strong_count(ptr: *const T) {
76        RcBase::<T, C>::increment_strong_count(ptr)
77    }
78
79    /// See [std::sync::Arc::decrement_strong_count].
80    #[inline]
81    pub unsafe fn decrement_strong_count(ptr: *const T) {
82        RcBase::<T, C>::decrement_strong_count(ptr)
83    }
84
85    /// See [std::sync::Arc::into_inner].
86    #[inline]
87    pub fn into_inner(this: Self) -> Option<T> {
88        RcBase::into_inner(this.0)
89    }
90}
91
92impl<T: ?Sized, C> ArcX<T, C>
93where
94    C: RefCount + Sync + Send,
95{
96    /// See [std::sync::Arc::as_ptr].
97    #[inline]
98    pub fn as_ptr(this: &Self) -> *const T {
99        RcBase::as_ptr(&this.0)
100    }
101
102    /// See [std::sync::Arc::into_raw].
103    #[inline]
104    pub fn into_raw(this: Self) -> *const T {
105        RcBase::into_raw(this.0)
106    }
107
108    /// See [std::sync::Arc::strong_count].
109    #[inline]
110    pub fn strong_count(this: &Self) -> <C as RefCount>::Value {
111        RcBase::strong_count(&this.0)
112    }
113
114    /// See [std::sync::Arc::get_mut].
115    #[inline]
116    pub fn get_mut(this: &mut Self) -> Option<&mut T> {
117        RcBase::get_mut(&mut this.0)
118    }
119
120    /// See [std::sync::Arc::ptr_eq].
121    #[inline]
122    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
123        RcBase::ptr_eq(&this.0, &other.0)
124    }
125}
126
127impl<T: Clone, C> ArcX<T, C>
128where
129    C: RefCount + Sync + Send,
130{
131    /// See [std::sync::Arc::make_mut].
132    #[inline]
133    pub fn make_mut(this: &mut Self) -> &mut T {
134        RcBase::make_mut(&mut this.0)
135    }
136}
137
138impl<T: ?Sized, C> Deref for ArcX<T, C>
139where
140    C: RefCount + Sync + Send,
141{
142    type Target = T;
143
144    #[inline(always)]
145    fn deref(&self) -> &T {
146        self.0.deref()
147    }
148}
149
150impl<T: ?Sized, C> Clone for ArcX<T, C>
151where
152    C: RefCount + Sync + Send,
153{
154    #[inline]
155    fn clone(&self) -> ArcX<T, C> {
156        Self(self.0.clone())
157    }
158}
159
160impl<T: Default, C> Default for ArcX<T, C>
161where
162    C: RefCount + Sync + Send,
163{
164    #[inline]
165    fn default() -> ArcX<T, C> {
166        ArcX::new(Default::default())
167    }
168}
169
170impl<T: ?Sized + PartialEq, C> PartialEq for ArcX<T, C>
171where
172    C: RefCount + Sync + Send,
173{
174    #[inline]
175    fn eq(&self, other: &ArcX<T, C>) -> bool {
176        PartialEq::eq(&self.0, &other.0)
177    }
178    #[inline]
179    fn ne(&self, other: &ArcX<T, C>) -> bool {
180        PartialEq::ne(&self.0, &other.0)
181    }
182}
183
184impl<T: ?Sized + Eq, C> Eq for ArcX<T, C> where C: RefCount + Sync + Send {}
185
186impl<T: ?Sized + PartialOrd, C> PartialOrd for ArcX<T, C>
187where
188    C: RefCount + Sync + Send,
189{
190    #[inline]
191    fn partial_cmp(&self, other: &ArcX<T, C>) -> Option<Ordering> {
192        PartialOrd::partial_cmp(&self.0, &other.0)
193    }
194}
195
196impl<T: ?Sized + Ord, C> Ord for ArcX<T, C>
197where
198    C: RefCount + Sync + Send,
199{
200    #[inline]
201    fn cmp(&self, other: &ArcX<T, C>) -> Ordering {
202        Ord::cmp(&self.0, &other.0)
203    }
204}
205
206impl<T: ?Sized + Hash, C> Hash for ArcX<T, C>
207where
208    C: RefCount + Sync + Send,
209{
210    #[inline]
211    fn hash<H: Hasher>(&self, state: &mut H) {
212        Hash::hash(&self.0, state)
213    }
214}
215
216impl<T: ?Sized + fmt::Display, C> fmt::Display for ArcX<T, C>
217where
218    C: RefCount + Sync + Send,
219{
220    #[inline]
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        fmt::Display::fmt(&self.0, f)
223    }
224}
225
226impl<T: ?Sized + fmt::Debug, C> fmt::Debug for ArcX<T, C>
227where
228    C: RefCount + Sync + Send,
229{
230    #[inline]
231    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232        fmt::Debug::fmt(&self.0, f)
233    }
234}
235
236impl<T: ?Sized, C> fmt::Pointer for ArcX<T, C>
237where
238    C: RefCount + Sync + Send,
239{
240    #[inline]
241    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242        fmt::Pointer::fmt(&self.0, f)
243    }
244}
245
246impl<T, C> From<T> for ArcX<T, C>
247where
248    C: RefCount + Sync + Send,
249{
250    #[inline]
251    fn from(t: T) -> Self {
252        Self(RcBase::from(t))
253    }
254}
255
256impl<T: Clone, C> From<&[T]> for ArcX<[T], C>
257where
258    C: RefCount + Sync + Send,
259{
260    #[inline]
261    fn from(v: &[T]) -> ArcX<[T], C> {
262        Self(RcBase::from(v))
263    }
264}
265
266impl<C> From<&str> for ArcX<str, C>
267where
268    C: RefCount + Sync + Send,
269{
270    #[inline]
271    fn from(s: &str) -> ArcX<str, C> {
272        Self(RcBase::from(s))
273    }
274}
275
276impl<C> From<String> for ArcX<str, C>
277where
278    C: RefCount + Sync + Send,
279{
280    #[inline]
281    fn from(s: String) -> ArcX<str, C> {
282        Self(RcBase::from(s))
283    }
284}
285
286impl<C> From<&CStr> for ArcX<CStr, C>
287where
288    C: RefCount + Sync + Send,
289{
290    #[inline]
291    fn from(s: &CStr) -> ArcX<CStr, C> {
292        Self(RcBase::from(s))
293    }
294}
295
296impl<C> From<CString> for ArcX<CStr, C>
297where
298    C: RefCount + Sync + Send,
299{
300    #[inline]
301    fn from(s: CString) -> ArcX<CStr, C> {
302        Self(RcBase::from(s))
303    }
304}
305
306impl<T, C> From<Box<T>> for ArcX<T, C>
307where
308    C: RefCount + Sync + Send,
309{
310    #[inline]
311    fn from(b: Box<T>) -> ArcX<T, C> {
312        Self(RcBase::from(b))
313    }
314}
315
316impl<T, C> From<Vec<T>> for ArcX<[T], C>
317where
318    C: RefCount + Sync + Send,
319{
320    #[inline]
321    fn from(v: Vec<T>) -> ArcX<[T], C> {
322        Self(RcBase::from(v))
323    }
324}
325
326impl<'a, B, C> From<Cow<'a, B>> for ArcX<B, C>
327where
328    C: RefCount + Sync + Send,
329    B: ToOwned + ?Sized,
330    ArcX<B, C>: From<&'a B> + From<B::Owned>,
331{
332    #[inline]
333    fn from(cow: Cow<'a, B>) -> ArcX<B, C> {
334        match cow {
335            Cow::Borrowed(s) => ArcX::from(s),
336            Cow::Owned(s) => ArcX::from(s),
337        }
338    }
339}
340
341impl<C> From<ArcX<str, C>> for ArcX<[u8], C>
342where
343    C: RefCount + Sync + Send,
344{
345    #[inline]
346    fn from(rc: ArcX<str, C>) -> Self {
347        Self(RcBase::from(rc.0))
348    }
349}
350
351impl<T, C, const N: usize> TryFrom<ArcX<[T], C>> for ArcX<[T; N], C>
352where
353    C: RefCount + Sync + Send,
354{
355    type Error = ArcX<[T], C>;
356
357    #[inline]
358    fn try_from(boxed_slice: ArcX<[T], C>) -> Result<Self, Self::Error> {
359        RcBase::try_from(boxed_slice.0)
360            .map(Self)
361            .map_err(ArcX::<[T], C>)
362    }
363}
364
365impl<T, C> iter::FromIterator<T> for ArcX<[T], C>
366where
367    C: RefCount + Sync + Send,
368{
369    #[inline]
370    fn from_iter<I: iter::IntoIterator<Item = T>>(iter: I) -> Self {
371        Self(RcBase::from_iter(iter))
372    }
373}
374
375impl<T: ?Sized, C> borrow::Borrow<T> for ArcX<T, C>
376where
377    C: RefCount + Sync + Send,
378{
379    #[inline]
380    fn borrow(&self) -> &T {
381        self.0.borrow()
382    }
383}
384
385impl<T: ?Sized, C> AsRef<T> for ArcX<T, C>
386where
387    C: RefCount + Sync + Send,
388{
389    #[inline]
390    fn as_ref(&self) -> &T {
391        self.0.as_ref()
392    }
393}
394
395#[cfg(test)]
396mod tests {
397    use super::*;
398
399    #[test]
400    fn pin() {
401        let rc = Arc8::pin(1i32);
402
403        assert_eq!(*rc, 1);
404    }
405
406    #[test]
407    fn from_cow() {
408        // Owned
409        {
410            let v = "Hello".to_string();
411            let owned: Cow<str> = Cow::Owned(v);
412            assert!(matches!(owned, Cow::Owned(_)));
413            let rc = Arc8::<str>::from(owned);
414            assert_eq!(&*rc, "Hello");
415        }
416
417        // Borrowed
418        {
419            let v = "Hello";
420            let borrowed: Cow<str> = Cow::Borrowed(v);
421            assert!(matches!(borrowed, Cow::Borrowed(_)));
422            let rc = Arc8::<str>::from(borrowed);
423            assert_eq!(&*rc, "Hello");
424        }
425    }
426}