mod tests;
use std::cell::{Ref, RefCell, RefMut};
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
#[derive(Debug)]
pub enum Data<T: Clone> {
Value(Option<T>),
Ref(Rc<RefCell<T>>),
Cow(Option<Rc<Option<T>>>),
}
impl<T: Clone> Data<T> {
pub fn by_val(&self) -> Self {
match self {
Data::Value(v) => {
Data::Value(v.clone())
}
Data::Ref(r) => {
let t = r.as_ref().borrow().clone();
Data::Value(Some(t))
}
Data::Cow(c) => {
let c = c.as_ref().unwrap();
let t = c.as_ref().clone();
Data::Value(t)
}
}
}
pub fn by_ref(&mut self) -> Self {
match self {
Data::Ref(r) => {
Data::Ref(Rc::clone(r))
}
Data::Value(opt) => {
let t = opt.take().expect("Value was already taken");
let rc = Rc::new(RefCell::new(t));
*self = Data::Ref(Rc::clone(&rc));
Data::Ref(rc)
}
Data::Cow(c) => {
let mut c = c.take().expect("Value was already taken");
let rc = if let Some(inner) = Rc::get_mut(&mut c) {
let t = inner.take().expect("Inner option was empty");
Rc::new(RefCell::new(t))
} else {
let t = c.as_ref().clone().expect("Inner option was empty");
Rc::new(RefCell::new(t))
};
*self = Data::Ref(Rc::clone(&rc));
Data::Ref(rc)
}
}
}
pub fn by_cow(&mut self) -> Self {
match self {
Data::Value(v) => {
let rc = Rc::new(v.take());
*self = Data::Cow(Some(Rc::clone(&rc)));
Data::Cow(Some(rc))
}
Data::Ref(r) => {
let copy = r.borrow().clone();
Data::Cow(Some(Rc::new(Some(copy))))
}
Data::Cow(c) => {
let rc = c.take().expect("Value was already taken");
*self = Data::Cow(Some(Rc::clone(&rc)));
Data::Cow(Some(rc))
}
}
}
}
impl<T: Clone> Data<T> {
pub fn borrow(&self) -> ValRef<'_, T> {
match self {
Data::Value(Some(v)) => ValRef::Raw(v),
Data::Ref(r) => ValRef::Ref(r.as_ref().borrow()),
Data::Cow(Some(v)) => {
let t = v.as_ref().as_ref().unwrap();
ValRef::Raw(t)
}
_ => unreachable!("Value was already taken"),
}
}
pub fn borrow_mut(&mut self) -> ValRefMut<'_, T> {
match self {
Data::Value(Some(v)) => ValRefMut::Raw(v),
Data::Ref(r) => ValRefMut::Ref(r.borrow_mut()),
Data::Cow(Some(v)) => {
if let Some(own) = Rc::get_mut(v) {
let t = own.take();
*self = Data::Value(t);
self.borrow_mut()
} else {
let tc = v.as_ref().clone();
*self = Data::Value(tc);
self.borrow_mut()
}
}
_ => unreachable!("Value was already taken"),
}
}
}
impl<T: Clone> Data<T> {
#[inline]
pub fn value(data: T) -> Self {
Self::Value(Some(data))
}
#[inline]
pub fn reference(data: T) -> Self {
Self::Ref(Rc::new(RefCell::new(data)))
}
#[inline]
pub fn cow(data: T) -> Self {
Self::Cow(Some(Rc::new(Some(data))))
}
}
impl<T: Clone> Data<T> {
pub fn is_ref(&self) -> bool {
matches!(self, Data::Ref(_))
}
pub fn is_val(&self) -> bool {
matches!(self, Data::Value(_))
}
pub fn is_cow(&self) -> bool {
matches!(self, Data::Cow(_))
}
}
pub enum ValRef<'a, T: ?Sized + 'a> {
Raw(&'a T),
Ref(Ref<'a, T>),
}
impl<T: ?Sized> Deref for ValRef<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Self::Raw(v) => *v,
Self::Ref(v) => v.deref(),
}
}
}
pub enum ValRefMut<'a, T: ?Sized + 'a> {
Raw(&'a mut T),
Ref(RefMut<'a, T>),
}
impl<T: ?Sized> Deref for ValRefMut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Self::Raw(v) => v,
Self::Ref(v) => v.deref(),
}
}
}
impl<T: ?Sized> DerefMut for ValRefMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::Raw(v) => v,
Self::Ref(v) => v.deref_mut(),
}
}
}