simple_expressions/types/
primitive.rs

1use crate::types::error::{Error, Result};
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum Primitive {
5    Int(i64),
6    Float(f64),
7    Str(String),
8    Bool(bool),
9}
10
11impl Primitive {
12    pub fn as_bool(&self) -> Option<bool> {
13        self.coerce_bool()
14    }
15    pub fn as_int(&self) -> Option<i64> {
16        if let Primitive::Int(i) = self { Some(*i) } else { None }
17    }
18    pub fn as_float(&self) -> Option<f64> {
19        if let Primitive::Float(f) = self { Some(*f) } else { None }
20    }
21    pub fn as_str(&self) -> String {
22        self.as_str_lossy()
23    }
24
25    // Newer, explicit coercions
26    pub fn coerce_bool(&self) -> Option<bool> {
27        match self {
28            Primitive::Int(i) => Some(*i != 0),
29            Primitive::Float(f) => Some(*f != 0.0),
30            Primitive::Str(s) if s == "true" || s == "false" => Some(s == "true"),
31            Primitive::Bool(b) => Some(*b),
32            _ => None,
33        }
34    }
35    pub fn to_float_lossy(&self) -> Option<f64> {
36        match self {
37            Primitive::Float(f) => Some(*f),
38            Primitive::Int(i) => Some(*i as f64),
39            _ => None,
40        }
41    }
42    pub fn as_str_lossy(&self) -> String {
43        match self {
44            Primitive::Str(s) => s.clone(),
45            Primitive::Int(i) => i.to_string(),
46            Primitive::Float(f) => f.to_string(),
47            Primitive::Bool(b) => b.to_string(),
48        }
49    }
50}
51
52impl From<i64> for Primitive {
53    fn from(v: i64) -> Self {
54        Primitive::Int(v)
55    }
56}
57impl From<f64> for Primitive {
58    fn from(v: f64) -> Self {
59        Primitive::Float(v)
60    }
61}
62impl From<bool> for Primitive {
63    fn from(v: bool) -> Self {
64        Primitive::Bool(v)
65    }
66}
67impl From<String> for Primitive {
68    fn from(v: String) -> Self {
69        Primitive::Str(v)
70    }
71}
72impl From<&str> for Primitive {
73    fn from(v: &str) -> Self {
74        Primitive::Str(v.to_string())
75    }
76}
77
78impl TryFrom<Primitive> for i64 {
79    type Error = Error;
80    fn try_from(p: Primitive) -> Result<Self> {
81        if let Primitive::Int(i) = p { Ok(i) } else { Err(Error::TypeMismatch("expected int".into())) }
82    }
83}
84impl TryFrom<Primitive> for f64 {
85    type Error = Error;
86    fn try_from(p: Primitive) -> Result<Self> {
87        if let Primitive::Float(f) = p { Ok(f) } else { Err(Error::TypeMismatch("expected float".into())) }
88    }
89}
90impl TryFrom<Primitive> for bool {
91    type Error = Error;
92    fn try_from(p: Primitive) -> Result<Self> {
93        if let Primitive::Bool(b) = p { Ok(b) } else { Err(Error::TypeMismatch("expected bool".into())) }
94    }
95}
96impl TryFrom<Primitive> for String {
97    type Error = Error;
98    fn try_from(p: Primitive) -> Result<Self> {
99        if let Primitive::Str(s) = p { Ok(s) } else { Err(Error::TypeMismatch("expected string".into())) }
100    }
101}