//! Types that represent runtime values. use crate::{ error::{Error, Result}, Function, Table, ValueType, VariableMap, }; use json::JsonValue; use serde::{ de::{MapAccess, SeqAccess, Visitor}, ser::SerializeTuple, Deserialize, Serialize, Serializer, }; use std::{ cmp::Ordering, convert::TryFrom, fmt::{self, Display, Formatter}, marker::PhantomData, ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign}, }; pub mod function; pub mod table; pub mod value_type; pub mod variable_map; /// Whale value representation. /// /// Every whale variable has a key and a Value. Variables are represented by /// storing them in a VariableMap. This means the map of variables is itself a /// value that can be treated as any other. #[derive(Debug, Clone, Default)] pub enum Value { List(Vec), Map(VariableMap), Table(Table), Function(Function), String(String), Float(f64), Integer(i64), Boolean(bool), #[default] Empty, } impl Value { pub fn value_type(&self) -> ValueType { ValueType::from(self) } pub fn is_table(&self) -> bool { matches!(self, Value::Table(_)) } pub fn is_string(&self) -> bool { matches!(self, Value::String(_)) } pub fn is_integer(&self) -> bool { matches!(self, Value::Integer(_)) } pub fn is_float(&self) -> bool { matches!(self, Value::Float(_)) } pub fn is_number(&self) -> bool { matches!(self, Value::Integer(_) | Value::Float(_)) } pub fn is_boolean(&self) -> bool { matches!(self, Value::Boolean(_)) } pub fn is_list(&self) -> bool { matches!(self, Value::List(_)) } pub fn is_empty(&self) -> bool { matches!(self, Value::Empty) } pub fn is_map(&self) -> bool { matches!(self, Value::Map(_)) } pub fn is_function(&self) -> bool { matches!(self, Value::Map(_)) } /// Borrows the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::String`. pub fn as_string(&self) -> Result<&String> { match self { Value::String(string) => Ok(string), value => Err(Error::ExpectedString { actual: value.clone(), }), } } /// Copies the value stored in `self` as `i64`, or returns `Err` if `self` is not a `Value::Int`. pub fn as_int(&self) -> Result { match self { Value::Integer(i) => Ok(*i), value => Err(Error::ExpectedInt { actual: value.clone(), }), } } /// Copies the value stored in `self` as `f64`, or returns `Err` if `self` is not a `Primitive::Float`. pub fn as_float(&self) -> Result { match self { Value::Float(f) => Ok(*f), value => Err(Error::ExpectedFloat { actual: value.clone(), }), } } /// Copies the value stored in `self` as `f64`, or returns `Err` if `self` is not a `Primitive::Float` or `Value::Int`. /// Note that this method silently converts `i64` to `f64`, if `self` is a `Value::Int`. pub fn as_number(&self) -> Result { match self { Value::Float(f) => Ok(*f), Value::Integer(i) => Ok(*i as f64), value => Err(Error::ExpectedNumber { actual: value.clone(), }), } } /// Copies the value stored in `self` as `bool`, or returns `Err` if `self` is not a `Primitive::Boolean`. pub fn as_boolean(&self) -> Result { match self { Value::Boolean(boolean) => Ok(*boolean), value => Err(Error::ExpectedBoolean { actual: value.clone(), }), } } /// Borrows the value stored in `self` as `Vec`, or returns `Err` if `self` is not a `Value::List`. pub fn as_list(&self) -> Result<&Vec> { match self { Value::List(list) => Ok(list), value => Err(Error::ExpectedList { actual: value.clone(), }), } } /// Borrows the value stored in `self` as `Vec`, or returns `Err` if `self` is not a `Value::List`. pub fn into_inner_list(self) -> Result> { match self { Value::List(list) => Ok(list), value => Err(Error::ExpectedList { actual: value.clone(), }), } } /// Borrows the value stored in `self` as `Vec`, or returns `Err` if `self` is not a `Value::Map`. pub fn as_map(&self) -> Result<&VariableMap> { match self { Value::Map(map) => Ok(map), value => Err(Error::ExpectedMap { actual: value.clone(), }), } } /// Borrows the value stored in `self` as `Vec`, or returns `Err` if `self` is not a `Value::Table`. pub fn as_table(&self) -> Result<&Table> { match self { Value::Table(table) => Ok(table), value => Err(Error::ExpectedTable { actual: value.clone(), }), } } /// Borrows the value stored in `self` as `Function`, or returns `Err` if /// `self` is not a `Value::Function`. pub fn as_function(&self) -> Result<&Function> { match self { Value::Function(function) => Ok(function), value => Err(Error::ExpectedFunction { actual: value.clone(), }), } } /// Returns `()`, or returns`Err` if `self` is not a `Value::Tuple`. pub fn as_empty(&self) -> Result<()> { match self { Value::Empty => Ok(()), value => Err(Error::ExpectedEmpty { actual: value.clone(), }), } } /// Returns an owned table, either by cloning or converting the inner value.. pub fn to_table(&self) -> Result { match self { Value::Table(table) => Ok(table.clone()), Value::List(list) => Ok(Table::from(list)), Value::Map(map) => Ok(Table::from(map)), value => Err(Error::ExpectedTable { actual: value.clone(), }), } } } impl Add for Value { type Output = Result; fn add(self, other: Self) -> Self::Output { let non_number = match (self, other) { (Value::Integer(left), Value::Integer(right)) => { return Ok(Value::Integer(left + right)) } (Value::Float(left), Value::Float(right)) => return Ok(Value::Float(left + right)), (Value::Integer(left), Value::Float(right)) => { return Ok(Value::Float(left as f64 + right)) } (Value::Float(left), Value::Integer(right)) => { return Ok(Value::Float(left + right as f64)) } (non_number, Value::Integer(_)) | (non_number, Value::Float(_)) => non_number, (non_number, _) => non_number, }; Err(Error::ExpectedNumber { actual: non_number }) } } impl Sub for Value { type Output = Result; fn sub(self, other: Self) -> Self::Output { let non_number = match (self, other) { (Value::Integer(left), Value::Integer(right)) => { return Ok(Value::Integer(left + right)) } (Value::Float(left), Value::Float(right)) => return Ok(Value::Float(left + right)), (Value::Integer(left), Value::Float(right)) => { return Ok(Value::Float(left as f64 + right)) } (Value::Float(left), Value::Integer(right)) => { return Ok(Value::Float(left + right as f64)) } (non_number, Value::Integer(_)) | (non_number, Value::Float(_)) => non_number, (non_number, _) => non_number, }; Err(Error::ExpectedNumber { actual: non_number }) } } impl Mul for Value { type Output = Result; fn mul(self, other: Self) -> Self::Output { if self.is_integer() && other.is_integer() { let left = self.as_int().unwrap(); let right = other.as_int().unwrap(); let value = Value::Integer(left.saturating_mul(right)); Ok(value) } else { let left = self.as_number()?; let right = other.as_number()?; let value = Value::Float(left * right); Ok(value) } } } impl Div for Value { type Output = Result; fn div(self, other: Self) -> Self::Output { let left = self.as_number()?; let right = other.as_number()?; let result = left / right; let value = if result % 2.0 == 0.0 { Value::Integer(result as i64) } else { Value::Float(result) }; Ok(value) } } impl Rem for Value { type Output = Result; fn rem(self, other: Self) -> Self::Output { let left = self.as_int()?; let right = other.as_int()?; let result = left % right; Ok(Value::Integer(result)) } } impl AddAssign for Value { fn add_assign(&mut self, other: Self) { match (self, other) { (Value::Integer(left), Value::Integer(right)) => *left += right, (Value::Float(left), Value::Float(right)) => *left += right, (Value::Float(left), Value::Integer(right)) => *left += right as f64, _ => {} } } } impl SubAssign for Value { fn sub_assign(&mut self, other: Self) { match (self, other) { (Value::Integer(left), Value::Integer(right)) => *left -= right, (Value::Float(left), Value::Float(right)) => *left -= right, (Value::Float(left), Value::Integer(right)) => *left -= right as f64, _ => {} } } } impl Eq for Value {} impl PartialEq for Value { fn eq(&self, other: &Self) -> bool { match (self, other) { (Value::Integer(left), Value::Integer(right)) => left == right, (Value::Float(left), Value::Float(right)) => left == right, (Value::Boolean(left), Value::Boolean(right)) => left == right, (Value::String(left), Value::String(right)) => left == right, (Value::List(left), Value::List(right)) => left == right, (Value::Map(left), Value::Map(right)) => left == right, (Value::Table(left), Value::Table(right)) => left == right, (Value::Function(left), Value::Function(right)) => left == right, (Value::Empty, Value::Empty) => true, _ => false, } } } impl PartialOrd for Value { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for Value { fn cmp(&self, other: &Self) -> Ordering { match (self, other) { (Value::String(left), Value::String(right)) => left.cmp(right), (Value::String(_), _) => Ordering::Greater, (Value::Float(left), Value::Float(right)) => left.total_cmp(right), (Value::Float(_), _) => Ordering::Greater, (Value::Integer(left), Value::Integer(right)) => left.cmp(right), (Value::Integer(_), _) => Ordering::Greater, (Value::Boolean(left), Value::Boolean(right)) => left.cmp(right), (Value::Boolean(_), _) => Ordering::Greater, (Value::List(left), Value::List(right)) => left.cmp(right), (Value::List(_), _) => Ordering::Greater, (Value::Map(left), Value::Map(right)) => left.cmp(right), (Value::Map(_), _) => Ordering::Greater, (Value::Table(left), Value::Table(right)) => left.cmp(right), (Value::Table(_), _) => Ordering::Greater, (Value::Function(left), Value::Function(right)) => left.cmp(right), (Value::Function(_), _) => Ordering::Greater, (Value::Empty, Value::Empty) => Ordering::Equal, (Value::Empty, _) => Ordering::Less, } } } impl Serialize for Value { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { match self { Value::String(inner) => serializer.serialize_str(inner), Value::Float(inner) => serializer.serialize_f64(*inner), Value::Integer(inner) => serializer.serialize_i64(*inner), Value::Boolean(inner) => serializer.serialize_bool(*inner), Value::List(inner) => { let mut tuple = serializer.serialize_tuple(inner.len())?; for value in inner { tuple.serialize_element(value)?; } tuple.end() } Value::Empty => todo!(), Value::Map(inner) => inner.serialize(serializer), Value::Table(inner) => inner.serialize(serializer), Value::Function(inner) => inner.serialize(serializer), } } } impl Display for Value { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Value::String(string) => write!(f, "{string}"), Value::Float(float) => write!(f, "{}", float), Value::Integer(int) => write!(f, "{}", int), Value::Boolean(boolean) => write!(f, "{}", boolean), Value::Empty => write!(f, "()"), Value::List(list) => { write!(f, "[")?; for value in list { write!(f, " {value} ")?; } write!(f, "]") } Value::Map(map) => write!(f, "{map}"), Value::Table(table) => write!(f, "{table}"), Value::Function(function) => write!(f, "{function}"), } } } impl From for Value { fn from(string: String) -> Self { Value::String(string) } } impl From<&str> for Value { fn from(string: &str) -> Self { Value::String(string.to_string()) } } impl From for Value { fn from(float: f64) -> Self { Value::Float(float) } } impl From for Value { fn from(int: i64) -> Self { Value::Integer(int) } } impl From for Value { fn from(boolean: bool) -> Self { Value::Boolean(boolean) } } impl From> for Value { fn from(tuple: Vec) -> Self { Value::List(tuple) } } impl From for Result { fn from(value: Value) -> Self { Ok(value) } } impl From<()> for Value { fn from(_: ()) -> Self { Value::Empty } } impl TryFrom for Value { type Error = Error; fn try_from(json_value: JsonValue) -> Result { use JsonValue::*; match json_value { Null => Ok(Value::Empty), Short(short) => Ok(Value::String(short.to_string())), String(string) => Ok(Value::String(string)), Number(number) => Ok(Value::Float(f64::from(number))), Boolean(boolean) => Ok(Value::Boolean(boolean)), Object(object) => { let mut map = VariableMap::new(); for (key, node_value) in object.iter() { let value = Value::try_from(node_value)?; map.set_value(key.to_string(), value)?; } Ok(Value::Map(map)) } Array(array) => { let mut list = Vec::new(); for json_value in array { let value = Value::try_from(json_value)?; list.push(value); } Ok(Value::List(list)) } } } } impl TryFrom<&JsonValue> for Value { type Error = Error; fn try_from(json_value: &JsonValue) -> Result { use JsonValue::*; match json_value { Null => Ok(Value::Empty), Short(short) => Ok(Value::String(short.to_string())), String(string) => Ok(Value::String(string.clone())), Number(number) => Ok(Value::Float(f64::from(*number))), Boolean(boolean) => Ok(Value::Boolean(*boolean)), Object(object) => { let mut map = VariableMap::new(); for (key, node_value) in object.iter() { let value = Value::try_from(node_value)?; map.set_value(key.to_string(), value)?; } Ok(Value::Map(map)) } Array(array) => { let mut list = Vec::new(); for json_value in array { let value = Value::try_from(json_value)?; list.push(value); } Ok(Value::List(list)) } } } } impl TryFrom for String { type Error = Error; fn try_from(value: Value) -> std::result::Result { if let Value::String(value) = value { Ok(value) } else { Err(Error::ExpectedString { actual: value }) } } } impl TryFrom for f64 { type Error = Error; fn try_from(value: Value) -> std::result::Result { if let Value::Float(value) = value { Ok(value) } else { Err(Error::ExpectedFloat { actual: value }) } } } impl TryFrom for i64 { type Error = Error; fn try_from(value: Value) -> std::result::Result { if let Value::Integer(value) = value { Ok(value) } else { Err(Error::ExpectedInt { actual: value }) } } } impl TryFrom for bool { type Error = Error; fn try_from(value: Value) -> std::result::Result { if let Value::Boolean(value) = value { Ok(value) } else { Err(Error::ExpectedBoolean { actual: value }) } } } struct ValueVisitor { marker: PhantomData Value>, } impl ValueVisitor { fn new() -> Self { ValueVisitor { marker: PhantomData, } } } impl<'de> Visitor<'de> for ValueVisitor { type Value = Value; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("Any valid whale data.") } fn visit_bool(self, v: bool) -> std::result::Result where E: serde::de::Error, { Ok(Value::Boolean(v)) } fn visit_i8(self, v: i8) -> std::result::Result where E: serde::de::Error, { self.visit_i64(v as i64) } fn visit_i16(self, v: i16) -> std::result::Result where E: serde::de::Error, { self.visit_i64(v as i64) } fn visit_i32(self, v: i32) -> std::result::Result where E: serde::de::Error, { self.visit_i64(v as i64) } fn visit_i64(self, v: i64) -> std::result::Result where E: serde::de::Error, { Ok(Value::Integer(v)) } fn visit_i128(self, v: i128) -> std::result::Result where E: serde::de::Error, { if v > i64::MAX as i128 { Ok(Value::Integer(i64::MAX)) } else { Ok(Value::Integer(v as i64)) } } fn visit_u8(self, v: u8) -> std::result::Result where E: serde::de::Error, { self.visit_u64(v as u64) } fn visit_u16(self, v: u16) -> std::result::Result where E: serde::de::Error, { self.visit_u64(v as u64) } fn visit_u32(self, v: u32) -> std::result::Result where E: serde::de::Error, { self.visit_u64(v as u64) } fn visit_u64(self, v: u64) -> std::result::Result where E: serde::de::Error, { self.visit_i64(v as i64) } fn visit_u128(self, v: u128) -> std::result::Result where E: serde::de::Error, { self.visit_i128(v as i128) } fn visit_f32(self, v: f32) -> std::result::Result where E: serde::de::Error, { self.visit_f64(v as f64) } fn visit_f64(self, v: f64) -> std::result::Result where E: serde::de::Error, { Ok(Value::Float(v)) } fn visit_char(self, v: char) -> std::result::Result where E: serde::de::Error, { self.visit_str(&v.to_string()) } fn visit_str(self, v: &str) -> std::result::Result where E: serde::de::Error, { Ok(Value::String(v.to_string())) } fn visit_borrowed_str(self, v: &'de str) -> std::result::Result where E: serde::de::Error, { self.visit_str(v) } fn visit_string(self, v: String) -> std::result::Result where E: serde::de::Error, { Ok(Value::String(v)) } fn visit_bytes(self, v: &[u8]) -> std::result::Result where E: serde::de::Error, { let _ = v; Err(serde::de::Error::invalid_type( serde::de::Unexpected::Bytes(v), &self, )) } fn visit_borrowed_bytes(self, v: &'de [u8]) -> std::result::Result where E: serde::de::Error, { self.visit_bytes(v) } fn visit_byte_buf(self, v: Vec) -> std::result::Result where E: serde::de::Error, { self.visit_bytes(&v) } fn visit_none(self) -> std::result::Result where E: serde::de::Error, { Err(serde::de::Error::invalid_type( serde::de::Unexpected::Option, &self, )) } fn visit_some(self, deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { let _ = deserializer; Err(serde::de::Error::invalid_type( serde::de::Unexpected::Option, &self, )) } fn visit_unit(self) -> std::result::Result where E: serde::de::Error, { Err(serde::de::Error::invalid_type( serde::de::Unexpected::Unit, &self, )) } fn visit_newtype_struct(self, deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { let _ = deserializer; Err(serde::de::Error::invalid_type( serde::de::Unexpected::NewtypeStruct, &self, )) } fn visit_seq(self, mut access: A) -> std::result::Result where A: SeqAccess<'de>, { let mut list = Vec::new(); while let Some(value) = access.next_element()? { list.push(value); } Ok(Value::List(list)) } fn visit_map(self, mut access: M) -> std::result::Result where M: MapAccess<'de>, { let mut map = VariableMap::new(); while let Some((key, value)) = access.next_entry()? { map.set_value(key, value) .expect("Failed to deserialize Value. This is a no-op."); } Ok(Value::Map(map)) } fn visit_enum(self, data: A) -> std::result::Result where A: serde::de::EnumAccess<'de>, { let _ = data; Err(serde::de::Error::invalid_type( serde::de::Unexpected::Enum, &self, )) } fn __private_visit_untagged_option(self, _: D) -> std::result::Result where D: serde::Deserializer<'de>, { Err(()) } } impl<'de> Deserialize<'de> for Value { fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { deserializer.deserialize_any(ValueVisitor::new()) } }