Skip to main content

yolol_devices/value/
mod.rs

1mod int;
2mod string;
3
4use std::convert::TryFrom;
5use std::convert::TryInto;
6use std::fmt::Display;
7use std::ops::Add;
8use std::ops::Div;
9use std::ops::Mul;
10use std::ops::Rem;
11use std::ops::Sub;
12
13use enum_dispatch::enum_dispatch;
14
15pub use self::int::YololInt;
16pub use self::string::YololString;
17
18#[enum_dispatch]
19pub trait ValueTrait {
20    fn post_inc(&mut self) -> YololValue;
21    fn pre_inc(&mut self) -> YololValue;
22    fn post_dec(&mut self) -> Option<YololValue>;
23    fn pre_dec(&mut self) -> Option<YololValue>;
24    fn fac(&self) -> Option<YololValue>;
25    fn abs(&self) -> Option<YololValue>;
26    fn sqrt(&self) -> Option<YololValue>;
27    fn sin(&self) -> Option<YololValue>;
28    fn asin(&self) -> Option<YololValue>;
29    fn cos(&self) -> Option<YololValue>;
30    fn acos(&self) -> Option<YololValue>;
31    fn tan(&self) -> Option<YololValue>;
32    fn atan(&self) -> Option<YololValue>;
33    fn pow(&self, e: &YololValue) -> Option<YololValue>;
34    fn not(&self) -> YololValue;
35}
36
37#[enum_dispatch(ValueTrait)]
38#[derive(Debug, Clone)]
39pub enum YololValue {
40    String(YololString),
41    Int(YololInt),
42}
43
44impl Default for YololValue {
45    fn default() -> Self {
46        YololValue::Int(YololInt::default())
47    }
48}
49
50impl YololValue {
51    fn is_string(&self) -> bool {
52        match self {
53            YololValue::String(_) => true,
54            YololValue::Int(_) => false,
55        }
56    }
57}
58
59impl From<&YololValue> for bool {
60    fn from(v: &YololValue) -> Self {
61        match v {
62            YololValue::String(v) => v.into(),
63            YololValue::Int(v) => v.into(),
64        }
65    }
66}
67
68impl From<&str> for YololValue {
69    fn from(v: &str) -> Self {
70        Self::String(v.into())
71    }
72}
73
74impl From<i64> for YololValue {
75    fn from(v: i64) -> Self {
76        Self::Int(v.into())
77    }
78}
79
80impl From<f64> for YololValue {
81    fn from(v: f64) -> Self {
82        Self::Int(v.into())
83    }
84}
85
86impl From<bool> for YololValue {
87    fn from(v: bool) -> Self {
88        Self::Int(v.into())
89    }
90}
91
92impl TryFrom<&YololValue> for YololInt {
93    type Error = ();
94
95    fn try_from(value: &YololValue) -> Result<Self, Self::Error> {
96        if let YololValue::Int(v) = value {
97            Ok(*v)
98        } else {
99            Err(())
100        }
101    }
102}
103
104impl TryFrom<&YololValue> for YololString {
105    type Error = ();
106
107    fn try_from(value: &YololValue) -> Result<Self, Self::Error> {
108        if let YololValue::String(v) = value {
109            Ok(v.clone())
110        } else {
111            Err(())
112        }
113    }
114}
115
116impl YololValue {
117    pub fn or(&self, rhs: &Self) -> Self {
118        YololInt::from(self.into() || rhs.into()).into()
119    }
120
121    pub fn and(&self, rhs: &Self) -> Self {
122        YololInt::from(self.into() && rhs.into()).into()
123    }
124}
125
126impl Mul for &YololValue {
127    type Output = Option<YololValue>;
128
129    fn mul(self, rhs: Self) -> Self::Output {
130        if let YololValue::Int(lhs) = self {
131            if let YololValue::Int(rhs) = rhs {
132                return Some((lhs * rhs).into());
133            }
134        }
135        None
136    }
137}
138
139impl Div for &YololValue {
140    type Output = Option<YololValue>;
141
142    fn div(self, rhs: Self) -> Self::Output {
143        if let YololValue::Int(lhs) = self {
144            if let YololValue::Int(rhs) = rhs {
145                return Some((lhs / rhs)?.into());
146            }
147        }
148        None
149    }
150}
151
152impl Rem for &YololValue {
153    type Output = Option<YololValue>;
154
155    fn rem(self, rhs: Self) -> Self::Output {
156        if let YololValue::Int(lhs) = self {
157            if let YololValue::Int(rhs) = rhs {
158                if rhs != &0.into() {
159                    return Some((lhs % rhs)?.into());
160                }
161            }
162        }
163        None
164    }
165}
166
167impl Add for &YololValue {
168    type Output = YololValue;
169
170    fn add(self, rhs: Self) -> Self::Output {
171        if self.is_string() || rhs.is_string() {
172            let a: YololString = {
173                if self.is_string() {
174                    self.try_into().unwrap()
175                } else {
176                    let a: &YololInt = &self.try_into().unwrap();
177                    a.into()
178                }
179            };
180            let b: YololString = {
181                if rhs.is_string() {
182                    rhs.try_into().unwrap()
183                } else {
184                    let b: &YololInt = &rhs.try_into().unwrap();
185                    b.into()
186                }
187            };
188            (a + b).into()
189        } else {
190            let a: YololInt = self.try_into().unwrap();
191            let b: YololInt = rhs.try_into().unwrap();
192            (&a + &b).into()
193        }
194    }
195}
196
197impl Sub for &YololValue {
198    type Output = Option<YololValue>;
199
200    fn sub(self, rhs: Self) -> Self::Output {
201        if self.is_string() || rhs.is_string() {
202            let a: YololString = {
203                if self.is_string() {
204                    self.try_into().unwrap()
205                } else {
206                    let a: &YololInt = &self.try_into().unwrap();
207                    a.into()
208                }
209            };
210            let b: YololString = {
211                if rhs.is_string() {
212                    rhs.try_into().unwrap()
213                } else {
214                    let b: &YololInt = &rhs.try_into().unwrap();
215                    b.into()
216                }
217            };
218            Some((a - b)?.into())
219        } else {
220            let a: YololInt = self.try_into().unwrap();
221            let b: YololInt = rhs.try_into().unwrap();
222            Some((&a - &b).into())
223        }
224    }
225}
226
227impl PartialEq for YololValue {
228    fn eq(&self, rhs: &Self) -> bool {
229        if self.is_string() && rhs.is_string() {
230            let a: YololString = self.clone().try_into().unwrap();
231            let b: YololString = rhs.clone().try_into().unwrap();
232            return a.eq(&b);
233        } else if !self.is_string() && !rhs.is_string() {
234            let a: YololInt = self.clone().try_into().unwrap();
235            let b: YololInt = rhs.clone().try_into().unwrap();
236            return a.eq(&b);
237        }
238        false
239    }
240}
241
242impl PartialOrd for YololValue {
243    fn partial_cmp(&self, rhs: &Self) -> Option<std::cmp::Ordering> {
244        if self.is_string() || rhs.is_string() {
245            let a: YololString = {
246                if self.is_string() {
247                    self.clone().try_into().unwrap()
248                } else {
249                    let a: &YololInt = &self.try_into().unwrap();
250                    a.into()
251                }
252            };
253            let b: YololString = {
254                if rhs.is_string() {
255                    rhs.try_into().unwrap()
256                } else {
257                    let b: &YololInt = &rhs.clone().try_into().unwrap();
258                    b.into()
259                }
260            };
261            a.partial_cmp(&b)
262        } else {
263            let a: YololInt = self.clone().try_into().unwrap();
264            let b: YololInt = rhs.clone().try_into().unwrap();
265            a.partial_cmp(&b)
266        }
267    }
268}
269
270impl Display for YololValue {
271    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272        match self {
273            YololValue::String(v) => write!(f, "{}", v),
274            YololValue::Int(v) => write!(f, "{}", v),
275        }
276    }
277}