1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use super::Value;

/// Possible types of values as defined at <https://tc39.es/ecma262/#sec-typeof-operator>.
/// Note that an object which implements call is referred to here as 'Function'.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Type {
    Undefined,
    Null,
    Boolean,
    Number,
    String,
    Symbol,
    BigInt,
    Object,
    Function,
}

impl Type {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Number => "number",
            Self::String => "string",
            Self::Boolean => "boolean",
            Self::Symbol => "symbol",
            Self::Null => "object",
            Self::Undefined => "undefined",
            Self::Function => "function",
            Self::Object => "object",
            Self::BigInt => "bigint",
        }
    }
}

impl Value {
    /// Get the type of the value.
    ///
    /// This is similar to typeof as described at <https://tc39.es/ecma262/#sec-typeof-operator> but instead of
    /// returning a string it returns a Type enum which implements fmt::Display to allow getting the string if
    /// required using to_string().
    pub fn get_type(&self) -> Type {
        match *self {
            Self::Rational(_) | Self::Integer(_) => Type::Number,
            Self::String(_) => Type::String,
            Self::Boolean(_) => Type::Boolean,
            Self::Symbol(_) => Type::Symbol,
            Self::Null => Type::Null,
            Self::Undefined => Type::Undefined,
            Self::BigInt(_) => Type::BigInt,
            Self::Object(ref object) => {
                if object.is_function() {
                    Type::Function
                } else {
                    Type::Object
                }
            }
        }
    }
}