Crate mappable_rc
source ·Expand description
Provides mappable Rc
and Arc
implementations.
This crate provides two types: Marc
and Mrc
, corresponding to std
’s Arc
and Rc
types. For the most part, these types are near drop in replacements; they also provide shared
ownership via reference countings, many of the same methods, and almost all of the same trait
impls. The key difference is the existence of the map
method on both types. For example, you
can use Mrc::map
to subslice an Mrc<[u32]>
:
use mappable_rc::Mrc;
let m: Mrc<[u32]> = vec![1, 2, 3, 4].into();
assert_eq!(m.as_ref(), &[1, 2, 3, 4]);
let m: Mrc<[u32]> = Mrc::map(m, |slice| &slice[1..=2]);
assert_eq!(m.as_ref(), &[2, 3]);
The map
functions do not require preserving types. For example:
use mappable_rc::Mrc;
struct S(u32);
let m: Mrc<S> = Mrc::new(S(5));
let inner: Mrc<u32> = Mrc::map(m, |s| &s.0);
assert_eq!(inner.as_ref(), &5);
You can use the types provided by this crate even if other code hands you an Rc
or an Arc
.
See the Mrc::from_rc
and Marc::from_arc
methods, and the corresponding From
impls.
Performance
The performance characteristics of the types in this crate are very similar to the corresponding
std
types. The data pointer is stored directly in the struct, and so the referenced data is
only one indirection away. The Marc
implementation internally reuses the Arc
from std
, and
so the atomic operations are expected to be no more or less efficient.
A number of the trait implementations in this crate are more efficient than the corresponding
std
implementsions. Mrc<[T]>: From<Vec<T>>
is implemented like this:
use mappable_rc::Mrc;
let v = vec![1; 1000];
let m: Mrc<Vec<i32>> = Mrc::new(v);
let m: Mrc<[i32]> = Mrc::map(m, |v| &v[..]);
This means that the data in the Vec
is never copied and only a small allocation is performed.
The same implementation for Arc<[T]>
will perform a copy of the Vec
’s data, to ensure that
the memory format complies with the more stringent requirements of Arc
.
The main performance downside of these types is that the size of Mrc
and Marc
is two
usize
s greater than the size of the corresponding std
type.
#![no_std]
This crate is #![no_std]
by default, but of course depends on alloc
. There is a non-default
std
feature that provides implementations of std::error::Error
, From<OsString>
and
From<PathBuf>
. Activating this feature introduces an std
dependency.
This crate has no other dependencies.