compact_rc/
rc.rs

1use std::borrow;
2use std::borrow::Cow;
3use std::cell::Cell;
4use std::cmp::Ordering;
5use std::ffi::{CStr, CString};
6use std::fmt;
7use std::hash::{Hash, Hasher};
8use std::iter;
9use std::ops::Deref;
10use std::pin::Pin;
11
12use crate::base::RcBase;
13use crate::refcount::RefCount;
14
15/// RcX with u8 counter
16pub type Rc8<T> = RcX<T, u8>;
17/// RcX with u16 counter
18pub type Rc16<T> = RcX<T, u16>;
19/// RcX with u32 counter
20pub type Rc32<T> = RcX<T, u32>;
21/// RcX with u64 counter
22pub type Rc64<T> = RcX<T, u64>;
23/// RcX with usize counter
24pub type Rc<T> = RcX<T, usize>;
25
26/// Low-memory version of [std::rc::Rc].
27///
28/// A type provides almost the same methods as standard `Rc`.
29/// See [the top page](crate) for about differences from the standard `Rc`.
30///
31/// There are aliases for simplicity.
32/// - [Rc]
33/// - [Rc8]
34/// - [Rc16]
35/// - [Rc32]
36/// - [Rc64]
37pub struct RcX<T: ?Sized, C>(RcBase<T, Cell<C>>)
38where
39    Cell<C>: RefCount;
40
41impl<T, C> RcX<T, C>
42where
43    Cell<C>: RefCount,
44{
45    /// See [std::rc::Rc::new].
46    #[inline]
47    pub fn new(value: T) -> RcX<T, C> {
48        RcX(RcBase::new(value))
49    }
50
51    /// See [std::rc::Rc::pin].
52    #[inline]
53    pub fn pin(value: T) -> Pin<RcX<T, C>> {
54        unsafe { Pin::new_unchecked(Self::new(value)) }
55    }
56
57    /// See [std::rc::Rc::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::rc::Rc::from_raw].
64    ///
65    /// # Incompatibility
66    /// Unlike the standard `Rc`, 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::rc::Rc::increment_strong_count].
74    #[inline]
75    pub unsafe fn increment_strong_count(ptr: *const T) {
76        RcBase::<T, Cell<C>>::increment_strong_count(ptr)
77    }
78
79    /// See [std::rc::Rc::decrement_strong_count].
80    #[inline]
81    pub unsafe fn decrement_strong_count(ptr: *const T) {
82        RcBase::<T, Cell<C>>::decrement_strong_count(ptr)
83    }
84
85    /// See [std::rc::Rc::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> RcX<T, C>
93where
94    Cell<C>: RefCount,
95{
96    /// See [std::rc::Rc::as_ptr].
97    #[inline]
98    pub fn as_ptr(this: &Self) -> *const T {
99        RcBase::as_ptr(&this.0)
100    }
101
102    /// See [std::rc::Rc::into_raw].
103    #[inline]
104    pub fn into_raw(this: Self) -> *const T {
105        RcBase::into_raw(this.0)
106    }
107
108    /// See [std::rc::Rc::strong_count].
109    #[inline]
110    pub fn strong_count(this: &Self) -> <Cell<C> as RefCount>::Value {
111        RcBase::strong_count(&this.0)
112    }
113
114    /// See [std::rc::Rc::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::rc::Rc::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> RcX<T, C>
128where
129    Cell<C>: RefCount,
130{
131    /// See [std::rc::Rc::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 RcX<T, C>
139where
140    Cell<C>: RefCount,
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 RcX<T, C>
151where
152    Cell<C>: RefCount,
153{
154    #[inline]
155    fn clone(&self) -> RcX<T, C> {
156        Self(self.0.clone())
157    }
158}
159
160impl<T: Default, C> Default for RcX<T, C>
161where
162    Cell<C>: RefCount,
163{
164    #[inline]
165    fn default() -> RcX<T, C> {
166        RcX::new(Default::default())
167    }
168}
169
170impl<T: ?Sized + PartialEq, C> PartialEq for RcX<T, C>
171where
172    Cell<C>: RefCount,
173{
174    #[inline]
175    fn eq(&self, other: &RcX<T, C>) -> bool {
176        PartialEq::eq(&self.0, &other.0)
177    }
178    #[inline]
179    fn ne(&self, other: &RcX<T, C>) -> bool {
180        PartialEq::ne(&self.0, &other.0)
181    }
182}
183
184impl<T: ?Sized + Eq, C> Eq for RcX<T, C> where Cell<C>: RefCount {}
185
186impl<T: ?Sized + PartialOrd, C> PartialOrd for RcX<T, C>
187where
188    Cell<C>: RefCount,
189{
190    #[inline]
191    fn partial_cmp(&self, other: &RcX<T, C>) -> Option<Ordering> {
192        PartialOrd::partial_cmp(&self.0, &other.0)
193    }
194}
195
196impl<T: ?Sized + Ord, C> Ord for RcX<T, C>
197where
198    Cell<C>: RefCount,
199{
200    #[inline]
201    fn cmp(&self, other: &RcX<T, C>) -> Ordering {
202        Ord::cmp(&self.0, &other.0)
203    }
204}
205
206impl<T: ?Sized + Hash, C> Hash for RcX<T, C>
207where
208    Cell<C>: RefCount,
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 RcX<T, C>
217where
218    Cell<C>: RefCount,
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 RcX<T, C>
227where
228    Cell<C>: RefCount,
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 RcX<T, C>
237where
238    Cell<C>: RefCount,
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 RcX<T, C>
247where
248    Cell<C>: RefCount,
249{
250    #[inline]
251    fn from(t: T) -> Self {
252        Self(RcBase::from(t))
253    }
254}
255
256impl<T: Clone, C> From<&[T]> for RcX<[T], C>
257where
258    Cell<C>: RefCount,
259{
260    #[inline]
261    fn from(v: &[T]) -> RcX<[T], C> {
262        Self(RcBase::from(v))
263    }
264}
265
266impl<C> From<&str> for RcX<str, C>
267where
268    Cell<C>: RefCount,
269{
270    #[inline]
271    fn from(s: &str) -> RcX<str, C> {
272        Self(RcBase::from(s))
273    }
274}
275
276impl<C> From<String> for RcX<str, C>
277where
278    Cell<C>: RefCount,
279{
280    #[inline]
281    fn from(s: String) -> RcX<str, C> {
282        Self(RcBase::from(s))
283    }
284}
285
286impl<C> From<&CStr> for RcX<CStr, C>
287where
288    Cell<C>: RefCount,
289{
290    #[inline]
291    fn from(s: &CStr) -> RcX<CStr, C> {
292        Self(RcBase::from(s))
293    }
294}
295
296impl<C> From<CString> for RcX<CStr, C>
297where
298    Cell<C>: RefCount,
299{
300    #[inline]
301    fn from(s: CString) -> RcX<CStr, C> {
302        Self(RcBase::from(s))
303    }
304}
305
306impl<T, C> From<Box<T>> for RcX<T, C>
307where
308    Cell<C>: RefCount,
309{
310    #[inline]
311    fn from(b: Box<T>) -> RcX<T, C> {
312        Self(RcBase::from(b))
313    }
314}
315
316impl<T, C> From<Vec<T>> for RcX<[T], C>
317where
318    Cell<C>: RefCount,
319{
320    #[inline]
321    fn from(v: Vec<T>) -> RcX<[T], C> {
322        Self(RcBase::from(v))
323    }
324}
325
326impl<'a, B, C> From<Cow<'a, B>> for RcX<B, C>
327where
328    Cell<C>: RefCount,
329    B: ToOwned + ?Sized,
330    RcX<B, C>: From<&'a B> + From<B::Owned>,
331{
332    #[inline]
333    fn from(cow: Cow<'a, B>) -> RcX<B, C> {
334        match cow {
335            Cow::Borrowed(s) => RcX::from(s),
336            Cow::Owned(s) => RcX::from(s),
337        }
338    }
339}
340
341impl<C> From<RcX<str, C>> for RcX<[u8], C>
342where
343    Cell<C>: RefCount,
344{
345    #[inline]
346    fn from(rc: RcX<str, C>) -> Self {
347        Self(RcBase::from(rc.0))
348    }
349}
350
351impl<T, C, const N: usize> TryFrom<RcX<[T], C>> for RcX<[T; N], C>
352where
353    Cell<C>: RefCount,
354{
355    type Error = RcX<[T], C>;
356
357    #[inline]
358    fn try_from(boxed_slice: RcX<[T], C>) -> Result<Self, Self::Error> {
359        RcBase::try_from(boxed_slice.0)
360            .map(Self)
361            .map_err(RcX::<[T], C>)
362    }
363}
364
365impl<T, C> iter::FromIterator<T> for RcX<[T], C>
366where
367    Cell<C>: RefCount,
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 RcX<T, C>
376where
377    Cell<C>: RefCount,
378{
379    #[inline]
380    fn borrow(&self) -> &T {
381        self.0.borrow()
382    }
383}
384
385impl<T: ?Sized, C> AsRef<T> for RcX<T, C>
386where
387    Cell<C>: RefCount,
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 = Rc8::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 = Rc8::<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 = Rc8::<str>::from(borrowed);
423            assert_eq!(&*rc, "Hello");
424        }
425    }
426}