simple_expressions/types/
value.rs

1use crate::types::error::{Error, Result};
2pub(crate) use crate::types::object::Object;
3use crate::types::primitive::Primitive;
4use crate::types::string_members::get_string_member;
5use std::fmt;
6use std::fmt::{Debug, Display, Formatter};
7use std::rc::Rc;
8
9#[derive(Clone)]
10pub enum Value {
11    Primitive(Primitive),
12    Object(Rc<dyn Object>),
13}
14
15impl Value {
16    pub fn coerce_bool(&self) -> Option<bool> {
17        match self {
18            Value::Primitive(p) => p.coerce_bool(),
19            Value::Object(obj) => obj.as_bool(),
20        }
21    }
22    pub fn to_float_lossy(&self) -> Option<f64> {
23        match self {
24            Value::Primitive(p) => p.to_float_lossy(),
25            Value::Object(obj) => obj.as_float(),
26        }
27    }
28    pub fn as_str_lossy(&self) -> String {
29        match self {
30            Value::Primitive(p) => p.as_str_lossy(),
31            Value::Object(obj) => obj.as_string().unwrap_or_else(|| format!("{}", obj)),
32        }
33    }
34
35    pub fn type_name(&self) -> &'static str {
36        match self {
37            Value::Primitive(Primitive::Str(_)) => "string",
38            Value::Primitive(Primitive::Int(_)) | Value::Primitive(Primitive::Float(_)) => "number",
39            Value::Primitive(Primitive::Bool(_)) => "bool",
40            Value::Object(obj) => obj.type_name(),
41        }
42    }
43
44    pub fn get_member(&self, name: &str) -> Result<Value> {
45        match self {
46            Value::Primitive(Primitive::Str(s)) => get_string_member(s, name),
47            Value::Object(obj) => obj.get_member(name),
48            _ => Err(Error::UnknownMember {
49                type_name: self.type_name().into(),
50                member: name.to_string(),
51            }),
52        }
53    }
54}
55
56impl Display for Primitive {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", self.as_str_lossy())
59    }
60}
61impl Display for Value {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, "{}", self.as_str_lossy())
64    }
65}
66
67impl Debug for Value {
68    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
69        match self {
70            Value::Primitive(p) => write!(f, "{}", p),
71            Value::Object(obj) => write!(f, "{}", obj),
72        }
73    }
74}
75
76impl PartialEq for Value {
77    fn eq(&self, other: &Self) -> bool {
78        match (self, other) {
79            (Value::Primitive(p1), Value::Primitive(p2)) => p1 == p2,
80            (Value::Object(obj1), other) => obj1.equals(other),
81            (other, Value::Object(obj2)) => obj2.equals(other),
82        }
83    }
84}
85
86impl From<Primitive> for Value {
87    fn from(p: Primitive) -> Self {
88        Value::Primitive(p)
89    }
90}
91impl From<i64> for Value {
92    fn from(v: i64) -> Self {
93        Value::Primitive(v.into())
94    }
95}
96impl From<f64> for Value {
97    fn from(v: f64) -> Self {
98        Value::Primitive(v.into())
99    }
100}
101impl From<bool> for Value {
102    fn from(v: bool) -> Self {
103        Value::Primitive(v.into())
104    }
105}
106impl From<String> for Value {
107    fn from(v: String) -> Self {
108        Value::Primitive(v.into())
109    }
110}
111impl From<&str> for Value {
112    fn from(v: &str) -> Self {
113        Value::Primitive(v.into())
114    }
115}
116
117impl TryFrom<Value> for i64 {
118    type Error = Error;
119    fn try_from(v: Value) -> Result<Self> {
120        if let Value::Primitive(p) = v { p.try_into() } else { Err(Error::TypeMismatch("expected int".into())) }
121    }
122}
123impl TryFrom<Value> for f64 {
124    type Error = Error;
125    fn try_from(v: Value) -> Result<Self> {
126        if let Value::Primitive(p) = v { p.try_into() } else { Err(Error::TypeMismatch("expected float".into())) }
127    }
128}
129impl TryFrom<Value> for bool {
130    type Error = Error;
131    fn try_from(v: Value) -> Result<Self> {
132        if let Value::Primitive(p) = v { p.try_into() } else { Err(Error::TypeMismatch("expected bool".into())) }
133    }
134}
135impl TryFrom<Value> for String {
136    type Error = Error;
137    fn try_from(v: Value) -> Result<Self> {
138        if let Value::Primitive(p) = v { p.try_into() } else { Err(Error::TypeMismatch("expected string".into())) }
139    }
140}