1use super::Dynamic;
2
3use std::ops::{Neg, Not};
4impl Neg for Dynamic {
5 type Output = Self;
6 fn neg(self) -> Self::Output {
7 use Dynamic::*;
8 match self {
9 I8(i) => I8(i.wrapping_neg()),
10 I16(i) => I16(i.wrapping_neg()),
11 I32(i) => I32(i.wrapping_neg()),
12 I64(i) => I64(i.wrapping_neg()),
13 F32(f) => F32(-f),
14 F64(f) => F64(-f),
15 _ => Null,
16 }
17 }
18}
19
20impl Not for Dynamic {
21 type Output = Self;
22 fn not(self) -> Self::Output {
23 match self {
24 Self::Bool(b) => Self::Bool(!b),
25 Self::I8(i) => Self::I8(!i),
26 Self::I16(i) => Self::I16(!i),
27 Self::I32(i) => Self::I32(!i),
28 Self::I64(i) => Self::I64(!i),
29 Self::U8(i) => Self::U8(!i),
30 Self::U16(i) => Self::U16(!i),
31 Self::U32(i) => Self::U32(!i),
32 Self::U64(i) => Self::U64(!i),
33 _ => Self::Null,
34 }
35 }
36}
37
38use std::ops::{Add, Div, Mul, Rem, Sub};
39
40impl Add for Dynamic {
41 type Output = Self;
42 fn add(self, rhs: Self) -> Self::Output {
43 if self.is_list() {
44 self.clone().append(rhs);
45 return self;
46 } else if rhs.is_list() {
47 rhs.clone().append(self);
48 return rhs;
49 }
50 if let (Self::String(left), Self::String(right)) = (&self, &rhs) {
51 let mut out = String::with_capacity(left.len() + right.len());
52 out.push_str(left.as_str());
53 out.push_str(right.as_str());
54 return Self::String(out.into());
55 } else if let Self::String(left) = &self {
56 let right = rhs.to_string();
57 let mut out = String::with_capacity(left.len() + right.len());
58 out.push_str(left.as_str());
59 out.push_str(&right);
60 return Self::String(out.into());
61 } else if let Self::String(right) = &rhs {
62 let left = self.to_string();
63 let mut out = String::with_capacity(left.len() + right.len());
64 out.push_str(&left);
65 out.push_str(right.as_str());
66 return Self::String(out.into());
67 } else if self.is_f64() || rhs.is_f64() {
68 return Dynamic::F64(self.as_float().unwrap_or(0.0) + rhs.as_float().unwrap_or(0.0));
69 } else if self.is_f32() || rhs.is_f32() {
70 return Dynamic::F32(self.as_float().unwrap_or(0.0) as f32 + rhs.as_float().unwrap_or(0.0) as f32);
71 }
72 if self.is_int() || rhs.is_int() {
73 return Self::I64(self.as_int().unwrap() + rhs.as_int().unwrap());
74 }
75 if self.is_uint() || rhs.is_uint() {
76 return Self::U64(self.as_uint().unwrap() + rhs.as_uint().unwrap());
77 }
78 if self.is_map() && rhs.is_map() {
79 self.append(rhs);
80 }
81 self
82 }
83}
84
85impl Mul for Dynamic {
86 type Output = Self;
87 fn mul(self, rhs: Self) -> Self::Output {
88 if self.is_f64() || rhs.is_f64() {
89 return Dynamic::F64(self.as_float().unwrap_or(0.0) * rhs.as_float().unwrap_or(0.0));
90 } else if self.is_f32() || rhs.is_f32() {
91 return Dynamic::F32(self.as_float().unwrap_or(0.0) as f32 * rhs.as_float().unwrap_or(0.0) as f32);
92 }
93 if self.is_int() || rhs.is_int() {
94 return Self::I64(self.as_int().unwrap_or(0) * rhs.as_int().unwrap_or(0));
95 }
96 if self.is_uint() || rhs.is_uint() {
97 return Self::U64(self.as_uint().unwrap_or(0) * rhs.as_uint().unwrap_or(0));
98 }
99 self
100 }
101}
102
103impl Sub for Dynamic {
104 type Output = Self;
105 fn sub(self, rhs: Self) -> Self::Output {
106 if self.is_f64() || rhs.is_f64() {
107 return Dynamic::F64(self.as_float().unwrap() - rhs.as_float().unwrap());
108 } else if self.is_f32() || rhs.is_f32() {
109 return Dynamic::F32(self.as_float().unwrap() as f32 - rhs.as_float().unwrap() as f32);
110 }
111 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
112 return Self::I64(self.as_int().unwrap() - rhs.as_int().unwrap());
113 }
114 if self.is_list() && rhs.is_list() {
115 if self.len() == rhs.len() {}
116 }
117 self
118 }
119}
120
121impl Div for Dynamic {
122 type Output = Self;
123 fn div(self, rhs: Self) -> Self::Output {
124 if self.is_f64() || rhs.is_f64() {
125 return Dynamic::F64(self.as_float().unwrap() / rhs.as_float().unwrap());
126 } else if self.is_f32() || rhs.is_f32() {
127 return Dynamic::F32(self.as_float().unwrap() as f32 / rhs.as_float().unwrap() as f32);
128 }
129 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
130 return Self::I64(self.as_int().unwrap() / rhs.as_int().unwrap());
131 }
132 self
133 }
134}
135
136impl Rem for Dynamic {
137 type Output = Self;
138 fn rem(self, rhs: Self) -> Self::Output {
139 if self.is_int() || rhs.is_int() || self.is_uint() || rhs.is_uint() {
140 return Self::I64(self.as_int().unwrap() % rhs.as_int().unwrap());
141 }
142 self
143 }
144}
145
146use std::ops::{Shl, Shr};
147
148impl Shl for Dynamic {
149 type Output = Self;
150 fn shl(self, rhs: Self) -> Self::Output {
151 use Dynamic::*;
152 let shift = u64::try_from(rhs).unwrap();
153 match self {
154 I8(i) => I8(i << shift),
155 I16(i) => I16(i << shift),
156 I32(i) => I32(i << shift),
157 I64(i) => I64(i << shift),
158 U8(i) => U8(i << shift),
159 U16(i) => U16(i << shift),
160 U32(i) => U32(i << shift),
161 U64(i) => U64(i << shift),
162 _ => panic!("Cannot shift non-integer types"),
163 }
164 }
165}
166
167impl Shr for Dynamic {
168 type Output = Self;
169 fn shr(self, rhs: Self) -> Self::Output {
170 use Dynamic::*;
171 let shift = u64::try_from(rhs).unwrap();
172 match self {
173 I8(i) => I8(i >> shift),
174 I16(i) => I16(i >> shift),
175 I32(i) => I32(i >> shift),
176 I64(i) => I64(i >> shift),
177 U8(i) => U8(i >> shift),
178 U16(i) => U16(i >> shift),
179 U32(i) => U32(i >> shift),
180 U64(i) => U64(i >> shift),
181 _ => panic!("Cannot shift non-integer types"),
182 }
183 }
184}
185
186use std::ops::{BitAnd, BitOr, BitXor};
187impl BitAnd for Dynamic {
188 type Output = Self;
189 fn bitand(self, rhs: Self) -> Self::Output {
190 let ty = self.get_type() + rhs.get_type();
191 let left = ty.force(self).unwrap();
192 let right = ty.force(rhs).unwrap();
193 match (left, right) {
194 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l & r),
195 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l & r),
196 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l & r),
197 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l & r),
198 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l & r),
199 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l & r),
200 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l & r),
201 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l & r),
202 (_, _) => Dynamic::Null,
203 }
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 #[test]
212 fn negating_signed_min_values_does_not_panic() {
213 assert_eq!(-Dynamic::I8(i8::MIN), Dynamic::I8(i8::MIN));
214 assert_eq!(-Dynamic::I16(i16::MIN), Dynamic::I16(i16::MIN));
215 assert_eq!(-Dynamic::I32(i32::MIN), Dynamic::I32(i32::MIN));
216 assert_eq!(-Dynamic::I64(i64::MIN), Dynamic::I64(i64::MIN));
217 }
218
219 #[test]
220 fn not_is_logical_for_bool_and_bitwise_for_ints() {
221 assert_eq!(!Dynamic::Bool(false), Dynamic::Bool(true));
222 assert_eq!(!Dynamic::I32(0b1010), Dynamic::I32(!0b1010));
223 assert_eq!(!Dynamic::U32(0b1010), Dynamic::U32(!0b1010));
224 }
225}
226
227impl BitOr for Dynamic {
228 type Output = Self;
229 fn bitor(self, rhs: Self) -> Self::Output {
230 let ty = self.get_type() + rhs.get_type();
231 let left = ty.force(self).unwrap();
232 let right = ty.force(rhs).unwrap();
233 match (left, right) {
234 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l | r),
235 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l | r),
236 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l | r),
237 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l | r),
238 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l | r),
239 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l | r),
240 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l | r),
241 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l | r),
242 (_, _) => Dynamic::Null,
243 }
244 }
245}
246
247impl BitXor for Dynamic {
248 type Output = Self;
249 fn bitxor(self, rhs: Self) -> Self::Output {
250 let ty = self.get_type() + rhs.get_type();
251 let left = ty.force(self).unwrap();
252 let right = ty.force(rhs).unwrap();
253 match (left, right) {
254 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l ^ r),
255 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l ^ r),
256 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l ^ r),
257 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l ^ r),
258 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l ^ r),
259 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l ^ r),
260 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l ^ r),
261 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l ^ r),
262 (_, _) => Dynamic::Null,
263 }
264 }
265}