use std::{cell::RefCell, mem, ops::Deref, rc::Rc};
use crate::RantValue;
#[derive(Debug)]
pub enum RantVar {
ByVal(RantValue),
ByValConst(RantValue),
ByRef(Rc<RefCell<RantValue>>),
ByRefConst(Rc<RantValue>)
}
impl Default for RantVar {
fn default() -> Self {
Self::ByVal(RantValue::Nothing)
}
}
impl Clone for RantVar {
fn clone(&self) -> Self {
match self {
Self::ByVal(val) => Self::ByVal(val.clone()),
Self::ByRef(val_ref) => Self::ByRef(Rc::clone(val_ref)),
Self::ByValConst(val) => Self::ByValConst(val.clone()),
Self::ByRefConst(val_ref) => Self::ByRefConst(Rc::clone(val_ref)),
}
}
}
impl RantVar {
#[inline]
pub fn is_const(&self) -> bool {
matches!(self, Self::ByValConst(_) | Self::ByRefConst(_))
}
#[inline]
pub fn is_by_val(&self) -> bool {
matches!(self, Self::ByVal(_) | Self::ByValConst(_))
}
#[inline]
pub fn is_by_ref(&self) -> bool {
matches!(self, Self::ByRef(_) | Self::ByRefConst(_))
}
#[inline]
pub fn make_by_ref(&mut self) {
if self.is_by_ref() { return }
match mem::take(self) {
Self::ByVal(val) => *self = Self::ByRef(Rc::new(RefCell::new(val))),
Self::ByValConst(val) => *self = Self::ByRefConst(Rc::new(val)),
_ => unreachable!()
}
}
#[inline]
pub fn write(&mut self, value: RantValue) -> bool {
match self {
Self::ByVal(val) => *val = value,
Self::ByRef(val_ref) => {
val_ref.replace(value);
},
Self::ByRefConst(_) | Self::ByValConst(_) => return false,
}
true
}
#[inline]
pub fn value_ref(&self) -> impl Deref<Target = RantValue> + '_ {
match self {
Self::ByVal(val) | Self::ByValConst(val) => cervine::Cow::Borrowed(val),
Self::ByRef(val_ref) => cervine::Cow::Owned(val_ref.borrow()),
Self::ByRefConst(val_ref) => cervine::Cow::Borrowed(val_ref.as_ref()),
}
}
#[inline]
pub fn value_cloned(&self) -> RantValue {
match self {
RantVar::ByVal(val) | RantVar::ByValConst(val) => val.clone(),
RantVar::ByRef(val_ref) => val_ref.borrow().clone(),
RantVar::ByRefConst(val_ref) => val_ref.as_ref().clone(),
}
}
}