simple_expressions/types/
value.rs1use 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}