use std::convert::TryInto;
use thiserror::Error;
use crate::{
list::list_view::ListView, map::map_view::MapView, ops::ObjID, text::text_view::TextView,
};
use super::ObjView;
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub enum Value {
Plain(litl::Val),
ReadView(ObjView),
WriteView(ObjView),
}
impl Value {
pub fn str(value: &str) -> Value {
Value::Plain(litl::Val::str(value))
}
pub fn plain(value: litl::Val) -> Value {
Value::Plain(value)
}
pub(super) fn read_view(view: ObjView) -> Value {
Value::ReadView(view)
}
pub(super) fn write_view(view: ObjView) -> Value {
Value::WriteView(view)
}
}
impl Value {
pub fn if_obj(&self) -> Result<&ObjView, ValueError> {
self.try_into()
}
pub fn if_map(&self) -> Result<&MapView, ValueError> {
let obj: &ObjView = self.try_into()?;
obj.try_into()
}
pub fn if_list(&self) -> Result<&ListView, ValueError> {
let obj: &ObjView = self.try_into()?;
obj.try_into()
}
pub fn if_text(&self) -> Result<&TextView, ValueError> {
let obj: &ObjView = self.try_into()?;
obj.try_into()
}
pub fn if_mut_obj(&mut self) -> Result<&mut ObjView, ValueError> {
self.try_into()
}
pub fn if_map_mut(&mut self) -> Result<&mut MapView, ValueError> {
let obj: &mut ObjView = self.try_into()?;
obj.try_into()
}
pub fn if_list_mut(&mut self) -> Result<&mut ListView, ValueError> {
let obj: &mut ObjView = self.try_into()?;
obj.try_into()
}
pub fn if_text_mut(&mut self) -> Result<&mut TextView, ValueError> {
let obj: &mut ObjView = self.try_into()?;
obj.try_into()
}
pub fn if_plain(&self) -> Result<&litl::Val, ValueError> {
match &self {
Value::Plain(plain) => Ok(plain),
Value::ReadView(view) | Value::WriteView(view) => {
Err(ValueError::ExpectedPlainButGotCollaborative(view.clone()))
}
}
}
pub fn to_litl(&self) -> litl::Val {
match &self {
Value::Plain(value) => value.clone(),
Value::ReadView(view) | Value::WriteView(view) => view.to_litl(),
}
}
pub fn obj_id(&self) -> Option<ObjID> {
match &self {
Value::Plain(_) => None,
Value::ReadView(view) | Value::WriteView(view) => Some(view.get_obj_id()),
}
}
}
impl TryInto<ObjView> for Value {
type Error = ValueError;
fn try_into(self) -> Result<ObjView, Self::Error> {
match self {
Value::ReadView(view) | Value::WriteView(view) => Ok(view),
Value::Plain(val) => Err(ValueError::ExpectedCollaborativeButGotPlain(val)),
}
}
}
impl<'a> TryInto<&'a ObjView> for &'a Value {
type Error = ValueError;
fn try_into(self) -> Result<&'a ObjView, Self::Error> {
match &self {
Value::ReadView(view) | Value::WriteView(view) => Ok(view),
Value::Plain(val) => Err(ValueError::ExpectedCollaborativeButGotPlain(val.clone())),
}
}
}
impl<'a> TryInto<&'a mut ObjView> for &'a mut Value {
type Error = ValueError;
fn try_into(self) -> Result<&'a mut ObjView, Self::Error> {
match self {
Value::ReadView(_) => Err(ValueError::ExpectedMutableCollaborativeObj),
Value::WriteView(view) => Ok(view),
Value::Plain(val) => Err(ValueError::ExpectedCollaborativeButGotPlain(val.clone())),
}
}
}
#[derive(Error, Debug, PartialEq, Eq)]
#[allow(clippy::enum_variant_names)]
pub enum ValueError {
#[error("Expected plain value but got collaborative object {0:?}")]
ExpectedPlainButGotCollaborative(ObjView),
#[error("Expected collaborative object but got plain value {0:?}")]
ExpectedCollaborativeButGotPlain(litl::Val),
#[error("Expected collaborative map but got {0:?}")]
ExpectedMap(ObjView),
#[error("Expected collaborative list but got {0:?}")]
ExpectedList(ObjView),
#[error("Expected collaborative text but got {0:?}")]
ExpectedText(ObjView),
#[error("Expected mutable collaborative object")]
ExpectedMutableCollaborativeObj,
}