1use crate::vm::handle::{ArrayHandle, FunctionHandle, ObjectHandle};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6pub enum Value {
7 Number(f64),
8 String(String),
9 Boolean(bool),
10 Object(ObjectHandle),
11 Array(ArrayHandle),
12 Function(FunctionHandle),
13 Null,
14 Undefined,
15}
16
17impl Value {
18 pub fn is_primitive(&self) -> bool {
19 matches!(
20 self,
21 Value::Number(_)
22 | Value::String(_)
23 | Value::Boolean(_)
24 | Value::Null
25 | Value::Undefined
26 )
27 }
28
29 pub fn as_number(&self) -> Option<f64> {
30 if let Value::Number(n) = self {
31 Some(*n)
32 } else {
33 None
34 }
35 }
36
37 pub fn as_bool(&self) -> Option<bool> {
38 if let Value::Boolean(b) = self {
39 Some(*b)
40 } else {
41 None
42 }
43 }
44
45 pub fn as_string(&self) -> Option<&str> {
46 if let Value::String(s) = self {
47 Some(s)
48 } else {
49 None
50 }
51 }
52
53 pub fn to_number(&self) -> f64 {
54 match self {
55 Value::Number(n) => *n,
56 Value::Boolean(b) => {
57 if *b {
58 1.0
59 } else {
60 0.0
61 }
62 }
63 Value::String(s) => s.parse::<f64>().unwrap_or(f64::NAN),
64 Value::Null => 0.0,
65 Value::Undefined => f64::NAN,
66 _ => f64::NAN,
67 }
68 }
69
70 pub fn to_string_value(&self) -> String {
71 match self {
72 Value::Number(n) => n.to_string(),
73 Value::Boolean(b) => b.to_string(),
74 Value::String(s) => s.clone(),
75 Value::Null => "null".to_string(),
76 Value::Undefined => "undefined".to_string(),
77 Value::Object(_) => "[object Object]".to_string(),
78 Value::Array(_) => "[object Array]".to_string(),
79 Value::Function(_) => "[function]".to_string(),
80 }
81 }
82
83 pub fn to_boolean(&self) -> bool {
84 match self {
85 Value::Boolean(b) => *b,
86 Value::Number(n) => *n != 0.0 && !n.is_nan(),
87 Value::String(s) => !s.is_empty(),
88 Value::Null | Value::Undefined => false,
89 _ => true,
90 }
91 }
92
93 pub fn is_truthy(&self) -> bool {
94 self.to_boolean()
95 }
96
97 pub fn is_falsy(&self) -> bool {
98 !self.to_boolean()
99 }
100}
101
102impl fmt::Display for Value {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(f, "{}", self.to_string_value())
105 }
106}
107
108impl From<f64> for Value {
109 fn from(n: f64) -> Self {
110 Value::Number(n)
111 }
112}
113
114impl From<String> for Value {
115 fn from(s: String) -> Self {
116 Value::String(s)
117 }
118}
119
120impl From<bool> for Value {
121 fn from(b: bool) -> Self {
122 Value::Boolean(b)
123 }
124}