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
usizes 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.