use crate::ptr::rc_box::{
clone_impl, clone_inner, decrement_and_possibly_deallocate, get_count, get_mut_boxed_content,
get_ref_boxed_content, is_exclusive, try_unwrap, unwrap_clone, RcBox,
};
use crate::ptr::Irc;
use std::borrow::{Borrow, BorrowMut};
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ops::DerefMut;
use std::ptr::NonNull;
pub struct Mrc<T> {
ptr: NonNull<RcBox<T>>,
}
impl<T> Mrc<T> {
pub fn new(value: T) -> Self {
let rc_box = RcBox::new(value);
let ptr = rc_box.into_non_null();
Self { ptr }
}
pub fn get_mut(&mut self) -> Option<&mut T> {
if self.is_exclusive() {
Some(get_mut_boxed_content(&mut self.ptr).value.as_mut())
} else {
None
}
}
pub fn try_unwrap(self) -> Result<T, Self> {
try_unwrap(self.ptr).map_err(|ptr| {
Self { ptr } })
}
pub fn get_count(&self) -> usize {
get_count(self.ptr)
}
pub fn is_exclusive(&self) -> bool {
is_exclusive(self.ptr)
}
pub fn irc(&self) -> Irc<T> {
get_ref_boxed_content(&self.ptr).inc_count();
Irc { ptr: self.ptr }
}
pub fn into_irc(self) -> Irc<T> {
get_ref_boxed_content(&self.ptr).inc_count();
Irc { ptr: self.ptr }
}
pub fn ptr_eq(lhs: &Self, rhs: &Self) -> bool {
std::ptr::eq(lhs.ptr.as_ptr(), rhs.ptr.as_ptr())
}
}
impl<T: Clone> Mrc<T> {
pub fn make_mut(&mut self) -> &mut T {
if !self.is_exclusive() {
let rc_box = RcBox::new(self.clone_inner());
let ptr = rc_box.into_non_null();
get_ref_boxed_content(&self.ptr).dec_count();
self.ptr = ptr;
}
get_mut_boxed_content(&mut self.ptr).value.as_mut()
}
pub fn unwrap_clone(self) -> T {
unwrap_clone(self.ptr)
}
pub fn clone_inner(&self) -> T {
clone_inner(self.ptr)
}
}
impl<T> Drop for Mrc<T> {
fn drop(&mut self) {
unsafe { decrement_and_possibly_deallocate(self.ptr) }
}
}
impl<T> Clone for Mrc<T> {
fn clone(&self) -> Self {
Self {
ptr: clone_impl(self.ptr),
}
}
}
impl<T: Default> Default for Mrc<T> {
fn default() -> Self {
Mrc::new(T::default())
}
}
impl<T: Clone> DerefMut for Mrc<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.make_mut()
}
}
impl<T: Clone> AsMut<T> for Mrc<T> {
fn as_mut(&mut self) -> &mut T {
self.make_mut()
}
}
impl<T: Clone> BorrowMut<T> for Mrc<T> {
fn borrow_mut(&mut self) -> &mut T {
self.make_mut()
}
}
impl<T> AsRef<T> for Mrc<T> {
fn as_ref(&self) -> &T {
get_ref_boxed_content(&self.ptr).value.as_ref()
}
}
impl<T> Deref for Mrc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> Borrow<T> for Mrc<T> {
fn borrow(&self) -> &T {
self.as_ref()
}
}
impl<T: PartialEq> PartialEq for Mrc<T> {
fn eq(&self, other: &Self) -> bool {
self.as_ref().eq(other.as_ref())
}
}
impl<T: Eq> Eq for Mrc<T> {}
impl<T: PartialOrd> PartialOrd for Mrc<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}
impl<T: Ord> Ord for Mrc<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.as_ref().cmp(other.as_ref())
}
}
impl<T: Hash> Hash for Mrc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_ref().hash(state)
}
}
impl<T: fmt::Debug> fmt::Debug for Mrc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let rc_box = get_ref_boxed_content(&self.ptr);
f.debug_struct("Irc")
.field("value", rc_box.value.as_ref())
.field("count", &rc_box.get_count())
.finish()
}
}