Skip to main content

just_engine/runner/ds/
value.rs

1use std::fmt;
2use std::fmt::{Display, Formatter};
3use std::rc::Rc;
4
5use crate::runner::ds::object::JsObjectType;
6use crate::runner::ds::operations::type_conversion::{TYPE_STR_NULL, TYPE_STR_UNDEFINED};
7use crate::runner::ds::symbol::SymbolData;
8
9/// JavaScript value representation.
10///
11/// Represents all possible JavaScript values including primitives and objects.
12/// This is the primary value type used throughout the engine.
13///
14/// # Examples
15///
16/// ```
17/// use just::runner::ds::value::{JsValue, JsNumberType};
18///
19/// let undefined = JsValue::Undefined;
20/// let null = JsValue::Null;
21/// let boolean = JsValue::Boolean(true);
22/// let string = JsValue::String("hello".to_string());
23/// let number = JsValue::Number(JsNumberType::Integer(42));
24/// ```
25pub enum JsValue {
26    /// The `undefined` value.
27    Undefined,
28    /// The `null` value.
29    Null,
30    /// A boolean value (`true` or `false`).
31    Boolean(bool),
32    /// A string value.
33    String(String),
34    /// A symbol value (ES6 symbols).
35    Symbol(SymbolData),
36    /// A numeric value (integer or float).
37    Number(JsNumberType),
38    /// An object value (including arrays, functions, etc.).
39    Object(JsObjectType),
40}
41impl Clone for JsValue {
42    fn clone(&self) -> Self {
43        match self {
44            JsValue::Undefined => JsValue::Undefined,
45            JsValue::String(d) => JsValue::String(d.to_string()),
46            JsValue::Boolean(d) => JsValue::Boolean(*d),
47            JsValue::Null => JsValue::Null,
48            JsValue::Number(d) => JsValue::Number(d.clone()),
49            JsValue::Object(o) => JsValue::Object(o.clone()),
50            JsValue::Symbol(d) => JsValue::Symbol(d.clone()),
51        }
52    }
53}
54impl Display for JsValue {
55    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
56        write!(
57            f,
58            "{}",
59            match self {
60                JsValue::Undefined => TYPE_STR_UNDEFINED.to_string(),
61                JsValue::Null => TYPE_STR_NULL.to_string(),
62                JsValue::Boolean(b) => format!("bool({})", b),
63                JsValue::String(s) => format!("\"{}\"", s),
64                JsValue::Symbol(s) => s.to_string(),
65                JsValue::Number(n) => n.to_string(),
66                JsValue::Object(o) => (**o).borrow().as_js_object().to_string(),
67            }
68        )
69    }
70}
71
72impl fmt::Debug for JsValue {
73    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
74        match self {
75            JsValue::Undefined => write!(f, "JsValue::Undefined"),
76            JsValue::Null => write!(f, "JsValue::Null"),
77            JsValue::Boolean(b) => write!(f, "JsValue::Boolean({})", b),
78            JsValue::String(s) => write!(f, "JsValue::String({:?})", s),
79            JsValue::Symbol(s) => write!(f, "JsValue::Symbol({})", s),
80            JsValue::Number(n) => write!(f, "JsValue::Number({:?})", n),
81            JsValue::Object(_) => write!(f, "JsValue::Object(...)"),
82        }
83    }
84}
85
86impl PartialEq for JsValue {
87    fn eq(&self, other: &Self) -> bool {
88        match (self, other) {
89            (JsValue::Undefined, JsValue::Undefined) => true,
90            (JsValue::Null, JsValue::Null) => true,
91            (JsValue::Boolean(a), JsValue::Boolean(b)) => a == b,
92            (JsValue::String(a), JsValue::String(b)) => a == b,
93            (JsValue::Number(a), JsValue::Number(b)) => a == b,
94            (JsValue::Object(a), JsValue::Object(b)) => Rc::ptr_eq(a, b),
95            (JsValue::Symbol(a), JsValue::Symbol(b)) => a == b,
96            _ => false,
97        }
98    }
99}
100
101/// JavaScript number type.
102///
103/// JavaScript numbers can be represented as either integers or floats.
104/// The engine uses integers when possible for better performance.
105///
106/// # Examples
107///
108/// ```
109/// use just::runner::ds::value::JsNumberType;
110///
111/// let int = JsNumberType::Integer(42);
112/// let float = JsNumberType::Float(3.14);
113/// let infinity = JsNumberType::Float(f64::INFINITY);
114/// ```
115#[derive(Debug, PartialEq)]
116pub enum JsNumberType {
117    /// An integer value (64-bit signed).
118    Integer(i64),
119    Float(f64),
120    NaN,
121    PositiveInfinity,
122    NegativeInfinity,
123}
124impl Display for JsNumberType {
125    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
126        match self {
127            JsNumberType::Integer(i) => write!(f, "{}", i),
128            JsNumberType::Float(nf) => write!(f, "{}", nf),
129            JsNumberType::NaN => write!(f, "NaN"),
130            JsNumberType::PositiveInfinity => write!(f, "+Infinity"),
131            JsNumberType::NegativeInfinity => write!(f, "-Infinity"),
132        }
133    }
134}
135impl Clone for JsNumberType {
136    fn clone(&self) -> Self {
137        match self {
138            JsNumberType::Integer(i) => JsNumberType::Integer(*i),
139            JsNumberType::Float(nf) => JsNumberType::Float(*nf),
140            JsNumberType::NaN => JsNumberType::NaN,
141            JsNumberType::PositiveInfinity => JsNumberType::PositiveInfinity,
142            JsNumberType::NegativeInfinity => JsNumberType::NegativeInfinity,
143        }
144    }
145}
146
147pub enum JsValueOrSelf<'a> {
148    ValueRef(&'a JsValue),
149    SelfValue,
150}