use std::{fmt, ops::Deref, rc::Rc};
pub struct ByRc<T: ?Sized>(pub Rc<T>);
impl<T> ByRc<T> {
pub fn new(value: Rc<T>) -> Self {
Self(value)
}
}
impl<T: ?Sized> ByRc<T> {
pub fn inner(&self) -> &Rc<T> {
&self.0
}
}
impl<T: ?Sized> Clone for ByRc<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: ?Sized> PartialEq for ByRc<T> {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}
impl<T: ?Sized> Eq for ByRc<T> {}
impl<T: ?Sized> Deref for ByRc<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T: ?Sized> From<Rc<T>> for ByRc<T> {
fn from(value: Rc<T>) -> Self {
Self(value)
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for ByRc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ByRc").field(&&*self.0).finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug)]
struct Handle(u32);
#[test]
fn the_same_allocation_compares_equal() {
let handle = ByRc::new(Rc::new(Handle(1)));
assert_eq!(handle.clone(), handle);
}
#[test]
fn an_equal_value_in_a_different_allocation_does_not() {
let one = ByRc::new(Rc::new(Handle(1)));
let other = ByRc::new(Rc::new(Handle(1)));
assert_ne!(one, other);
}
#[test]
fn deref_reaches_the_wrapped_value() {
let handle = ByRc::new(Rc::new(Handle(7)));
assert_eq!(handle.0.0, 7);
}
#[test]
fn clone_does_not_require_the_payload_to_be_clone() {
let handle = ByRc::new(Rc::new(Handle(1)));
let copy = handle.clone();
assert!(Rc::ptr_eq(handle.inner(), copy.inner()));
}
}