tarc/
lib.rs

1//! # tarc
2//!
3//! ## Transposable, type-erasable, and FFI-compatible Arc.
4//!
5//! `tarc` is a fork of `std::sync::Arc` with several additions easing its use in type-erased
6//! scenarios.
7
8#![cfg_attr(not(feature = "std"), no_std)]
9
10#[cfg(not(feature = "std"))]
11extern crate alloc;
12
13#[cfg(not(feature = "std"))]
14use alloc::alloc::{alloc, dealloc};
15use core::alloc::Layout;
16use core::marker::Unpin;
17use core::pin::Pin;
18#[cfg(not(feature = "std"))]
19use core::prelude::rust_2018::*;
20use core::ptr::NonNull;
21use core::sync::atomic::{fence, AtomicUsize, Ordering};
22#[cfg(feature = "std")]
23use std::alloc::{alloc, dealloc};
24
25/// An opaque handle.
26#[repr(transparent)]
27pub struct Handle(BaseArc<()>);
28
29impl<T: ?Sized> From<Arc<T>> for Handle {
30    fn from(arc: Arc<T>) -> Self {
31        Self(unsafe { arc.untranspose::<()>() })
32    }
33}
34
35impl<T: ?Sized> From<BaseArc<T>> for Handle {
36    fn from(arc: BaseArc<T>) -> Self {
37        let data = arc.into_raw();
38        Self(unsafe { BaseArc::from_raw(data as *const ()) })
39    }
40}
41
42#[repr(C)]
43struct ArcHeader {
44    count: AtomicUsize,
45    drop: unsafe extern "C" fn(*mut ()),
46}
47
48pub type DropInPlace = Option<unsafe extern "C" fn(*mut ())>;
49
50#[repr(C)]
51struct DynArcHeader {
52    size: usize,
53    alignment: usize,
54    drop_in_place: DropInPlace,
55    hdr: ArcHeader,
56}
57
58unsafe extern "C" fn do_drop<T>(data: *mut ()) {
59    core::ptr::drop_in_place(data as *mut T);
60    let (header, layout) = layout::<T>();
61    dealloc((data as *mut u8).sub(header), layout);
62}
63
64unsafe extern "C" fn do_drop_in_place<T>(data: *mut ()) {
65    core::ptr::drop_in_place(data as *mut T);
66}
67
68unsafe extern "C" fn do_dyn_drop(data: *mut ()) {
69    let header = (data as *mut DynArcHeader).sub(1);
70    let layout = Layout::from_size_align_unchecked((*header).size, (*header).alignment);
71
72    if let Some(drop_fn) = (*header).drop_in_place {
73        drop_fn(data);
74    }
75
76    dealloc(header as *mut u8, layout);
77}
78
79fn layout<T>() -> (usize, Layout) {
80    header_layout::<DynArcHeader>(unsafe {
81        Layout::from_size_align_unchecked(core::mem::size_of::<T>(), core::mem::align_of::<T>())
82    })
83}
84
85fn header_layout<H>(inp: Layout) -> (usize, Layout) {
86    let alignment = core::cmp::max(inp.align(), core::mem::align_of::<H>());
87    let header_size = core::mem::size_of::<H>();
88
89    // Alignment is always a power of two, thus bitwise ops are valid
90    let align_up = |val| (val + (alignment - 1)) & !(alignment - 1);
91
92    let header_aligned = align_up(header_size);
93    let size = header_aligned + align_up(inp.size());
94
95    // SAFETY: left half and right half of the size calculation are multiple of alignment
96    let layout = unsafe { Layout::from_size_align_unchecked(size, alignment) };
97
98    (header_aligned, layout)
99}
100
101unsafe fn allocate<T>() -> NonNull<T> {
102    let (header, layout) = layout::<T>();
103    let data = alloc(layout).add(header);
104
105    assert!(!data.is_null());
106
107    NonNull::new_unchecked(data as *mut T)
108}
109
110unsafe fn initialize<T>(data: NonNull<T>, val: T) {
111    let header = (data.as_ptr() as *mut ArcHeader).sub(1);
112    header.write(ArcHeader {
113        count: AtomicUsize::new(1),
114        drop: do_drop::<T>,
115    });
116    data.as_ptr().write(val);
117}
118
119/// Arc that is safe to transpose and type-erase.
120///
121/// Standard `BaseArc<T>` allocates space for a header and places the header contents at the start
122/// of that space, which means the offset between data and header depends on the type alignment.
123/// This Arc puts the header right next to the data, making header accesses not rely on the
124/// underlying type. This allows to safely transmute `Arc<T>` into `Arc<()>`, or any type that `T`
125/// is safe to transmute into.
126///
127/// In addition, you may convert `BaseArc<T>` to `Arc<O>` if `O` is stored within `T` and there is
128/// a `AsRef<O>` implementation on `T`.
129///
130/// Semantically, this arc differs from the standard library in its absence of weak references.
131/// This is so that the header fits within 2 pointers.
132#[repr(transparent)]
133pub struct BaseArc<T: ?Sized> {
134    data: NonNull<T>,
135}
136
137impl BaseArc<()> {
138    /// Create a custom Arc.
139    ///
140    /// This function allows to create a custom dynamically sized arc with custom cleanup routine.
141    ///
142    /// Note that the contents of the created arc are uninitialized.
143    ///
144    /// # Arguments
145    ///
146    /// - `layout` - size and alignment of the object being created.
147    /// - `drop_in_place` - optional cleanup routine to be invoked on upon releasing the arc.
148    ///
149    /// # Panics
150    ///
151    /// This function panics if it fails to allocate enough data for the arc.
152    ///
153    /// # Safety
154    ///
155    /// Technically only correct `drop_in_place` implementation needs to be provided. That means,
156    /// the caller must ensure that `drop_in_place` releases the contents of the initialized arc
157    /// (after it has been returned from this function to the caller), correctly. If `None` is
158    /// passed as the cleanup routine, this function should be safe.
159    pub unsafe fn custom(layout: Layout, drop_in_place: DropInPlace) -> Self {
160        let (header, layout) = header_layout::<DynArcHeader>(layout);
161        let data = alloc(layout);
162
163        assert!(!data.is_null());
164
165        let hdr = data as *mut DynArcHeader;
166
167        hdr.write(DynArcHeader {
168            size: layout.size(),
169            alignment: layout.align(),
170            drop_in_place,
171            hdr: ArcHeader {
172                count: AtomicUsize::new(1),
173                drop: do_dyn_drop,
174            },
175        });
176
177        let data = NonNull::new_unchecked(data.add(header) as *mut _);
178
179        Self { data }
180    }
181}
182
183impl<T> BaseArc<T> {
184    pub fn new(val: T) -> Self {
185        let data = unsafe { allocate::<T>() };
186        unsafe {
187            initialize::<T>(data, val);
188        }
189
190        Self { data }
191    }
192
193    pub fn pin(data: T) -> Pin<Self> {
194        unsafe { Pin::new_unchecked(Self::new(data)) }
195    }
196
197    pub fn transpose<O>(self) -> Arc<O>
198    where
199        T: AsRef<O>,
200    {
201        // Make sure the type can at least be within T
202        assert!(core::mem::size_of::<O>() <= core::mem::size_of::<T>());
203
204        let transposed = (*self).as_ref() as *const _ as *const u8;
205        let raw = self.into_raw() as *const u8;
206
207        unsafe {
208            let off = (transposed as usize).checked_sub(raw as usize).unwrap();
209
210            // Make sure the pointer is within T
211            assert!(off <= (core::mem::size_of::<T>() - core::mem::size_of::<O>()));
212
213            Arc::from_raw(raw.add(off) as *const O, off)
214        }
215    }
216}
217
218impl<T: ?Sized> BaseArc<T> {
219    fn header(&self) -> &ArcHeader {
220        unsafe { &*((self.data.as_ptr() as *mut u8) as *mut ArcHeader).sub(1) }
221    }
222
223    /// Convert a pointer to managed `BaseArc`.
224    ///
225    /// # Safety
226    ///
227    /// `data` must be originally created through `BaseArc::new`.
228    pub unsafe fn from_raw(data: *const T) -> Self {
229        Self {
230            data: NonNull::new_unchecked(data as *mut _),
231        }
232    }
233
234    pub fn into_raw(self) -> *const T {
235        let ret = self.data.as_ptr() as *const _;
236        core::mem::forget(self);
237        ret
238    }
239
240    /// Increment the strong reference count
241    ///
242    /// This function takes a pointer to `BaseArc`-allocated data and increments its reference
243    /// count.
244    ///
245    /// # Safety
246    ///
247    /// `ptr` must be originally created by `BaseArc::new`.
248    pub unsafe fn increment_strong_count(ptr: *const T) {
249        // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
250        let arc = core::mem::ManuallyDrop::new(Self::from_raw(ptr));
251        // Now increase refcount, but don't drop new refcount either
252        let _arc_clone: core::mem::ManuallyDrop<_> = arc.clone();
253    }
254
255    /// Decrement the strong reference count
256    ///
257    /// This function takes a pointer to `BaseArc`-allocated data and decrements its reference
258    /// count. If the count reaches 0, destructor is called.
259    ///
260    /// # Safety
261    ///
262    /// `ptr` must be originally created by `BaseArc::new`.
263    pub unsafe fn decrement_strong_count(ptr: *const T) {
264        core::mem::drop(BaseArc::from_raw(ptr));
265    }
266
267    // Needed for macro drop impl
268    unsafe fn as_original_ptr<O: Sized>(&self) -> *const O {
269        (self.data.as_ptr() as *const u8) as *const O
270    }
271}
272
273/// Arc that is safe to transpose and type-erase.
274///
275/// Standard `Arc<T>` allocates space for a header and places the header contents at the start of
276/// that space, which means the offset between data and header depends on the type alignment. This
277/// Arc puts the header right next to the data, making header accesses not rely on the underlying
278/// type. This allows to safely transmute `Arc<T>` into `Arc<()>`, or any type that `T` is safe to
279/// transmute into.
280///
281/// In addition, you may convert `Arc<T>` to `Arc<O>` if `O` is stored within `T` and there is a
282/// `AsRef<O>` implementation on `T`.
283///
284/// Semantically, this arc also differs from the standard library in its absence of weak references.
285/// This is so that the header fits within 2 pointers.
286#[repr(C)]
287pub struct Arc<T: ?Sized> {
288    data: NonNull<T>,
289    offset: usize,
290}
291
292impl<T> Arc<T> {
293    pub fn new(val: T) -> Self {
294        let data = unsafe { allocate::<T>() };
295        unsafe {
296            initialize::<T>(data, val);
297        }
298
299        Self { data, offset: 0 }
300    }
301
302    pub fn pin(data: T) -> Pin<Self> {
303        unsafe { Pin::new_unchecked(Self::new(data)) }
304    }
305
306    pub fn transpose<O>(self) -> Arc<O>
307    where
308        T: AsRef<O>,
309    {
310        // Make sure the type can at least be within T
311        assert!(core::mem::size_of::<O>() <= core::mem::size_of::<T>());
312
313        let transposed = (*self).as_ref() as *const _ as *const u8;
314        let (raw, offset) = self.into_raw();
315        let raw = raw as *const u8;
316
317        unsafe {
318            let off = (transposed as usize).checked_sub(raw as usize).unwrap();
319
320            // Make sure the pointer is within T
321            assert!(off <= (core::mem::size_of::<T>() - core::mem::size_of::<O>()));
322
323            Arc::from_raw(raw.add(off) as *const O, offset + off)
324        }
325    }
326}
327
328impl<T: ?Sized> Arc<T> {
329    fn header(&self) -> &ArcHeader {
330        unsafe { &*((self.data.as_ptr() as *mut u8).sub(self.offset) as *mut ArcHeader).sub(1) }
331    }
332
333    /// Convert raw pointer to a managed `Arc`.
334    ///
335    /// # Safety
336    ///
337    /// `ptr` and `offset` needs to be a pair acquired from `Arc::into_raw` function call. More
338    /// specifically, `ptr as *const u8 - offset` must point to start of the data of original
339    /// `BaseArc`.
340    pub unsafe fn from_raw(data: *const T, offset: usize) -> Self {
341        Self {
342            data: NonNull::new_unchecked(data as *mut _),
343            offset,
344        }
345    }
346
347    pub fn into_raw(self) -> (*const T, usize) {
348        let ret = self.data.as_ptr() as *const _;
349        let offset = self.offset;
350        core::mem::forget(self);
351        (ret, offset)
352    }
353
354    /// Increment the strong reference count.
355    ///
356    /// Takes pointer to Arc's data and byte offset of the data and increments the strong reference
357    /// count.
358    ///
359    /// # Safety
360    ///
361    /// `ptr` and `offset` needs to be a pair acquired from `Arc::into_raw` function call. More
362    /// specifically, `ptr as *const u8 - offset` must point to start of the data of original
363    /// `BaseArc`.
364    pub unsafe fn increment_strong_count(ptr: *const T, offset: usize) {
365        // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
366        let arc = core::mem::ManuallyDrop::new(Self::from_raw(ptr, offset));
367        // Now increase refcount, but don't drop new refcount either
368        let _arc_clone: core::mem::ManuallyDrop<_> = arc.clone();
369    }
370
371    /// Decrement the strong reference count.
372    ///
373    /// Takes pointer to Arc's data and byte offset of the data and decrements the strong reference
374    /// count.
375    ///
376    /// If the reference count reaches 0, destructor is called.
377    ///
378    /// # Safety
379    ///
380    /// `ptr` and `offset` needs to be a pair acquired from `Arc::into_raw` function call. More
381    /// specifically, `ptr as *const u8 - offset` must point to start of the data of original
382    /// `BaseArc`.
383    pub unsafe fn decrement_strong_count(ptr: *const T, offset: usize) {
384        core::mem::drop(Arc::from_raw(ptr, offset));
385    }
386
387    /// Get `BaseArc<O>` out of this `Arc`
388    ///
389    /// # Safety
390    ///
391    /// The base arc must be of type `O`.
392    pub unsafe fn untranspose<O>(self) -> BaseArc<O> {
393        let (raw, offset) = self.into_raw();
394        let raw = (raw as *const u8).sub(offset) as *const O;
395        BaseArc::from_raw(raw)
396    }
397
398    /// Get the pointer to data of `BaseArc<O>`.
399    ///
400    /// # Safety
401    ///
402    /// The base arc must be of type `O`.
403    pub unsafe fn as_original_ptr<O>(&self) -> *const O {
404        (self.data.as_ptr() as *const u8).sub(self.offset) as *const O
405    }
406
407    pub fn is_original(&self) -> bool {
408        self.offset == 0
409    }
410
411    pub fn into_base(self) -> Result<BaseArc<T>, Self> {
412        if self.offset == 0 {
413            let (raw, _) = self.into_raw();
414            Ok(unsafe { BaseArc::from_raw(raw) })
415        } else {
416            Err(self)
417        }
418    }
419}
420
421/// Expand all function-like macros in docs before docs themselves are interpreted.
422///
423/// This is a workaround for rustc < 1.54, where doc attributes cannot have functional macros in
424/// them.
425macro_rules! doc {
426    ( $(#[doc = $expr1:expr])* ### #[doc = $expr2:expr] $($tt:tt)* ) => {
427        doc! {
428            $(#[doc = $expr1])*
429            #[doc = $expr2]
430            ###
431            $($tt)*
432        }
433    };
434    ( $(#[doc = $exprs:expr])* ### $($tt:tt)* ) => {
435        $(#[doc = $exprs])*
436        $($tt)*
437    };
438    ( $($tt:tt)* ) => {
439        doc! {
440            ###
441            $($tt)*
442        }
443    }
444}
445
446macro_rules! arc_traits {
447    ($mname:ident, $ty:ident) => {
448
449        impl<T> $ty<T> {
450            pub fn strong_count(&self) -> usize {
451                self.header().count.load(Ordering::Acquire)
452            }
453
454            pub fn as_ptr(&self) -> *const T {
455                self.data.as_ptr() as *const _
456            }
457
458            pub fn exclusive_ptr(&self) -> Option<NonNull<T>> {
459                if self.strong_count() == 1 {
460                    Some(self.data)
461                } else {
462                    None
463                }
464            }
465
466            pub fn get_mut(&mut self) -> Option<&mut T> {
467                self.exclusive_ptr().map(|v| unsafe { &mut *v.as_ptr() })
468            }
469        }
470
471        mod $mname {
472            use super::*;
473            impl<T: Default> Default for $ty<T> {
474                doc! {
475                    #[doc = concat!("Creates a new `", stringify!($ty), "<T>`, with the `Default` value for `T`.")]
476                    ///
477                    /// # Examples
478                    ///
479                    /// ```
480                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
481                    ///
482                    #[doc = concat!("let x: ", stringify!($ty), "<i32> = Default::default();")]
483                    /// assert_eq!(*x, 0);
484                    /// ```
485                    fn default() -> Self {
486                        Self::new(T::default())
487                    }
488                }
489            }
490
491            impl<T: ?Sized> core::ops::Deref for $ty<T> {
492                type Target = T;
493
494                fn deref(&self) -> &Self::Target {
495                    unsafe { self.data.as_ref() }
496                }
497            }
498
499            impl<T: ?Sized + core::hash::Hash> core::hash::Hash for $ty<T> {
500                fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
501                    (**self).hash(state)
502                }
503            }
504
505            impl<T: ?Sized> Unpin for $ty<T> {}
506
507            unsafe impl<T: ?Sized + Sync + Send> Send for $ty<T> {}
508            unsafe impl<T: ?Sized + Sync + Send> Sync for $ty<T> {}
509
510            doc! {
511                #[doc = concat!("Converts a `T` into an `", stringify!($ty), "<T>`")]
512                ///
513                /// The conversion moves the value into a
514                #[doc = concat!("newly allocated `", stringify!($ty), "`. It is equivalent to")]
515                #[doc = concat!(" calling `", stringify!($ty), "::new(t)`")]
516                ///
517                /// # Example
518                /// ```rust
519                #[doc = concat!("# use tarc:: ", stringify!($ty), ";")]
520                /// let x = 5;
521                #[doc = concat!("let arc = ", stringify!($ty), "::new(5);")]
522                ///
523                #[doc = concat!("assert_eq!(", stringify!($ty), "::from(x), arc);")]
524                /// ```
525                impl<T> From<T> for $ty<T> {
526                    fn from(t: T) -> Self {
527                        Self::new(t)
528                    }
529                }
530            }
531
532            impl<T: ?Sized> Clone for $ty<T> {
533                doc! {
534                    #[doc = concat!("Makes a clone of the `", stringify!($ty), "` pointer.")]
535                    ///
536                    /// This creates another pointer to the same allocation, increasing the
537                    /// strong reference count.
538                    ///
539                    /// # Examples
540                    ///
541                    /// ```
542                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
543                    ///
544                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
545                    ///
546                    #[doc = concat!("let _ = ", stringify!($ty), "::clone(&five);")]
547                    /// ```
548                    fn clone(&self) -> Self {
549                        if self.header().count.fetch_add(1, Ordering::Relaxed) > core::isize::MAX as usize {
550                            panic!()
551                        }
552
553                        Self { ..*self }
554                    }
555                }
556            }
557
558            impl<T: ?Sized> Drop for $ty<T> {
559                doc! {
560                    #[doc = concat!("Drops the `", stringify!($ty), "`.")]
561                    ///
562                    /// This will decrement the reference count. If the strong reference
563                    /// count reaches zero then the no more references, so we `drop` the inner value.
564                    ///
565                    /// # Examples
566                    ///
567                    /// ```
568                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
569                    ///
570                    /// struct Foo;
571                    ///
572                    /// impl Drop for Foo {
573                    ///     fn drop(&mut self) {
574                    ///         println!("dropped!");
575                    ///     }
576                    /// }
577                    ///
578                    #[doc = concat!("let foo  = ", stringify!($ty), "::new(Foo);")]
579                    #[doc = concat!("let foo2 = ", stringify!($ty), "::clone(&foo);")]
580                    ///
581                    /// drop(foo);    // Doesn't print anything
582                    /// drop(foo2);   // Prints "dropped!"
583                    /// ```
584                    fn drop(&mut self) {
585                        let header = self.header();
586
587                        if header.count.fetch_sub(1, Ordering::Release) != 1 {
588                            return;
589                        }
590
591                        fence(Ordering::SeqCst);
592
593                        unsafe { (header.drop)(self.as_original_ptr::<()>() as *mut ()) }
594                    }
595                }
596            }
597
598            impl<T: ?Sized + PartialEq> PartialEq for $ty<T> {
599                doc! {
600                    #[doc = concat!("Equality for two `", stringify!($ty), "`s.")]
601                    ///
602                    #[doc = concat!("Two `", stringify!($ty), "`s are equal if their inner values are equal, even if they are")]
603                    /// stored in different allocation.
604                    ///
605                    /// If `T` also implements `Eq` (implying reflexivity of equality),
606                    #[doc = concat!("two `", stringify!($ty), "`s that point to the same allocation are always equal.")]
607                    ///
608                    /// # Examples
609                    ///
610                    /// ```
611                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
612                    ///
613                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
614                    ///
615                    #[doc = concat!("assert!(five == ", stringify!($ty), "::new(5));")]
616                    /// ```
617                    #[inline]
618                    fn eq(&self, other: &$ty<T>) -> bool {
619                        // TODO: implement this optimization with specialization
620                        /*self.as_ptr() == other.as_ptr() ||*/ (**self == **other)
621                    }
622                }
623
624                doc! {
625                    #[doc = concat!("Inequality for two `", stringify!($ty), "`s.")]
626                    ///
627                    #[doc = concat!("Two `", stringify!($ty), "`s are unequal if their inner values are unequal.")]
628                    ///
629                    /// If `T` also implements `Eq` (implying reflexivity of equality),
630                    #[doc = concat!("two `", stringify!($ty), "`s that point to the same value are never unequal.")]
631                    ///
632                    /// # Examples
633                    ///
634                    /// ```
635                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
636                    ///
637                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
638                    ///
639                    #[doc = concat!("assert!(five != ", stringify!($ty), "::new(6));")]
640                    /// ```
641                    #[inline]
642                    #[allow(clippy::partialeq_ne_impl)]
643                    fn ne(&self, other: &$ty<T>) -> bool {
644                        // TODO: implement this optimization with specialization
645                        /*self.as_ptr() != other.as_ptr() &&*/ (**self != **other)
646                    }
647                }
648            }
649
650            use core::cmp::{Ord, Ordering as CmpOrdering};
651
652            impl<T: ?Sized + PartialOrd> PartialOrd for $ty<T> {
653                doc! {
654                    #[doc = concat!("Partial comparison for two `", stringify!($ty), "`s.")]
655                    ///
656                    /// The two are compared by calling `partial_cmp()` on their inner values.
657                    ///
658                    /// # Examples
659                    ///
660                    /// ```
661                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
662                    /// use std::cmp::Ordering;
663                    ///
664                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
665                    ///
666                    #[doc = concat!("assert_eq!(Some(Ordering::Less), five.partial_cmp(&", stringify!($ty), "::new(6)));")]
667                    /// ```
668                    fn partial_cmp(&self, other: &$ty<T>) -> Option<CmpOrdering> {
669                        (**self).partial_cmp(&**other)
670                    }
671                }
672
673                doc! {
674                    #[doc = concat!("Less-than comparison for two `", stringify!($ty), "`s.")]
675                    ///
676                    /// The two are compared by calling `<` on their inner values.
677                    ///
678                    /// # Examples
679                    ///
680                    /// ```
681                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
682                    ///
683                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
684                    ///
685                    #[doc = concat!("assert!(five < ", stringify!($ty), "::new(6));")]
686                    /// ```
687                    fn lt(&self, other: &$ty<T>) -> bool {
688                        *(*self) < *(*other)
689                    }
690                }
691
692                doc! {
693                    #[doc = concat!("'Less than or equal to' comparison for two `", stringify!($ty), "`s.")]
694                    ///
695                    /// The two are compared by calling `<=` on their inner values.
696                    ///
697                    /// # Examples
698                    ///
699                    /// ```
700                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
701                    ///
702                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
703                    ///
704                    #[doc = concat!("assert!(five <= ", stringify!($ty), "::new(5));")]
705                    /// ```
706                    fn le(&self, other: &$ty<T>) -> bool {
707                        *(*self) <= *(*other)
708                    }
709                }
710
711                doc! {
712                    #[doc = concat!("Greater-than comparison for two `", stringify!($ty), "`s.")]
713                    ///
714                    /// The two are compared by calling `>` on their inner values.
715                    ///
716                    /// # Examples
717                    ///
718                    /// ```
719                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
720                    ///
721                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
722                    ///
723                    #[doc = concat!("assert!(five > ", stringify!($ty), "::new(4));")]
724                    /// ```
725                    fn gt(&self, other: &$ty<T>) -> bool {
726                        *(*self) > *(*other)
727                    }
728                }
729
730                doc! {
731                    #[doc = concat!("'Greater than or equal to' comparison for two `", stringify!($ty), "`s.")]
732                    ///
733                    /// The two are compared by calling `>=` on their inner values.
734                    ///
735                    /// # Examples
736                    ///
737                    /// ```
738                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
739                    ///
740                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
741                    ///
742                    #[doc = concat!("assert!(five >= ", stringify!($ty), "::new(5));")]
743                    /// ```
744                    fn ge(&self, other: &$ty<T>) -> bool {
745                        *(*self) >= *(*other)
746                    }
747                }
748            }
749
750            impl<T: ?Sized + Eq> Eq for $ty<T> {}
751
752            impl<T: ?Sized + Ord> Ord for $ty<T> {
753                doc! {
754                    #[doc = concat!("Comparison for two `", stringify!($ty), "`s.")]
755                    ///
756                    /// The two are compared by calling `cmp()` on their inner values.
757                    ///
758                    /// # Examples
759                    ///
760                    /// ```
761                    #[doc = concat!("use tarc::", stringify!($ty), ";")]
762                    /// use std::cmp::Ordering;
763                    ///
764                    #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
765                    ///
766                    #[doc = concat!("assert_eq!(Ordering::Less, five.cmp(& ", stringify!($ty), "::new(6)));")]
767                    /// ```
768                    fn cmp(&self, other: &$ty<T>) -> CmpOrdering {
769                        (**self).cmp(&**other)
770                    }
771                }
772            }
773
774            use core::fmt;
775
776            impl<T: ?Sized + fmt::Display> fmt::Display for $ty<T> {
777                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778                    fmt::Display::fmt(&**self, f)
779                }
780            }
781
782            impl<T: ?Sized + fmt::Debug> fmt::Debug for $ty<T> {
783                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
784                    fmt::Debug::fmt(&**self, f)
785                }
786            }
787
788            impl<T: ?Sized> fmt::Pointer for $ty<T> {
789                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790                    fmt::Pointer::fmt(&(&**self as *const T), f)
791                }
792            }
793
794            impl<T: ?Sized> core::borrow::Borrow<T> for $ty<T> {
795                fn borrow(&self) -> &T {
796                    &**self
797                }
798            }
799
800            impl<T: ?Sized> AsRef<T> for $ty<T> {
801                fn as_ref(&self) -> &T {
802                    &**self
803                }
804            }
805
806            #[cfg(feature = "std")]
807            mod std_impl {
808                use super::*;
809                use std::error::Error;
810
811                impl<T: Error + ?Sized> Error for $ty<T> {
812                    #[allow(deprecated, deprecated_in_future)]
813                    fn description(&self) -> &str {
814                        Error::description(&**self)
815                    }
816
817                    #[allow(deprecated)]
818                    fn cause(&self) -> Option<&dyn Error> {
819                        Error::cause(&**self)
820                    }
821
822                    fn source(&self) -> Option<&(dyn Error + 'static)> {
823                        Error::source(&**self)
824                    }
825                }
826            }
827        }
828    };
829}
830
831arc_traits!(base_arc, BaseArc);
832arc_traits!(arc, Arc);