yolol_devices/value/
mod.rs1mod 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}