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
40fn int_fault(reason: &'static str) -> Dynamic {
41 crate::set_fault(reason);
42 Dynamic::Null
43}
44
45fn checked_i64(left: &Dynamic, right: &Dynamic, reason: &'static str) -> Option<(i64, i64)> {
46 match (left.as_int(), right.as_int()) {
47 (Some(left), Some(right)) => Some((left, right)),
48 _ => {
49 crate::set_fault(reason);
50 None
51 }
52 }
53}
54
55impl Add for Dynamic {
56 type Output = Self;
57 fn add(self, rhs: Self) -> Self::Output {
58 if self.is_list() {
59 self.clone().append(rhs);
60 return self;
61 } else if rhs.is_list() {
62 rhs.clone().append(self);
63 return rhs;
64 }
65 match (self, rhs) {
66 (Self::StringBuf(mut left), Self::StringBuf(right)) => {
67 left.push_str(&right);
68 return Self::StringBuf(left);
69 }
70 (Self::StringBuf(mut left), Self::String(right)) => {
71 left.push_str(right.as_str());
72 return Self::StringBuf(left);
73 }
74 (Self::StringBuf(mut left), right) => {
75 left.push_str(&right.to_string());
76 return Self::StringBuf(left);
77 }
78 (Self::String(left), Self::StringBuf(right)) => {
79 let mut out = String::with_capacity(left.len() + right.len());
80 out.push_str(left.as_str());
81 out.push_str(&right);
82 return Self::StringBuf(out);
83 }
84 (Self::String(left), Self::String(right)) => {
85 let mut out = String::with_capacity(left.len() + right.len());
86 out.push_str(left.as_str());
87 out.push_str(right.as_str());
88 return Self::StringBuf(out);
89 }
90 (Self::String(left), right) => {
91 let right = right.to_string();
92 let mut out = String::with_capacity(left.len() + right.len());
93 out.push_str(left.as_str());
94 out.push_str(&right);
95 return Self::StringBuf(out);
96 }
97 (left, Self::StringBuf(right)) => {
98 let left = left.to_string();
99 let mut out = String::with_capacity(left.len() + right.len());
100 out.push_str(&left);
101 out.push_str(&right);
102 return Self::StringBuf(out);
103 }
104 (left, Self::String(right)) => {
105 let left = left.to_string();
106 let mut out = String::with_capacity(left.len() + right.len());
107 out.push_str(&left);
108 out.push_str(right.as_str());
109 return Self::StringBuf(out);
110 }
111 (left, right) => {
112 if left.is_f64() || right.is_f64() {
113 return Dynamic::F64(left.as_float().unwrap_or(0.0) + right.as_float().unwrap_or(0.0));
114 } else if left.is_f32() || right.is_f32() {
115 return Dynamic::F32(left.as_float().unwrap_or(0.0) as f32 + right.as_float().unwrap_or(0.0) as f32);
116 }
117 if left.is_int() || right.is_int() {
118 let Some((left, right)) = checked_i64(&left, &right, "整数加法类型或范围错误") else {
119 return Dynamic::Null;
120 };
121 return left.checked_add(right).map(Self::I64).unwrap_or_else(|| int_fault("整数加法溢出"));
122 }
123 if left.is_uint() || right.is_uint() {
124 let (Some(left), Some(right)) = (left.as_uint(), right.as_uint()) else {
125 return int_fault("无符号整数加法类型错误");
126 };
127 return left.checked_add(right).map(Self::U64).unwrap_or_else(|| int_fault("无符号整数加法溢出"));
128 }
129 if left.is_map() && right.is_map() {
130 left.append(right);
131 }
132 left
133 }
134 }
135 }
136}
137
138impl Mul for Dynamic {
139 type Output = Self;
140 fn mul(self, rhs: Self) -> Self::Output {
141 if self.is_f64() || rhs.is_f64() {
142 return Dynamic::F64(self.as_float().unwrap_or(0.0) * rhs.as_float().unwrap_or(0.0));
143 } else if self.is_f32() || rhs.is_f32() {
144 return Dynamic::F32(self.as_float().unwrap_or(0.0) as f32 * rhs.as_float().unwrap_or(0.0) as f32);
145 }
146 if self.is_int() || rhs.is_int() {
147 let Some((left, right)) = checked_i64(&self, &rhs, "整数乘法类型或范围错误") else {
148 return Dynamic::Null;
149 };
150 return left.checked_mul(right).map(Self::I64).unwrap_or_else(|| int_fault("整数乘法溢出"));
151 }
152 if self.is_uint() || rhs.is_uint() {
153 let (Some(left), Some(right)) = (self.as_uint(), rhs.as_uint()) else {
154 return int_fault("无符号整数乘法类型错误");
155 };
156 return left.checked_mul(right).map(Self::U64).unwrap_or_else(|| int_fault("无符号整数乘法溢出"));
157 }
158 self
159 }
160}
161
162impl Sub for Dynamic {
163 type Output = Self;
164 fn sub(self, rhs: Self) -> Self::Output {
165 if self.is_float() && rhs.is_float() {
166 if self.is_f64() || rhs.is_f64() {
167 return Dynamic::F64(self.as_float().unwrap() - rhs.as_float().unwrap());
168 } else if self.is_f32() || rhs.is_f32() {
169 return Dynamic::F32(self.as_float().unwrap() as f32 - rhs.as_float().unwrap() as f32);
170 }
171 }
172 if self.is_int() || rhs.is_int() {
173 let Some((left, right)) = checked_i64(&self, &rhs, "整数减法类型或范围错误") else {
174 return Dynamic::Null;
175 };
176 return left.checked_sub(right).map(Self::I64).unwrap_or_else(|| int_fault("整数减法溢出"));
177 }
178 if self.is_uint() || rhs.is_uint() {
179 let (Some(left), Some(right)) = (self.as_uint(), rhs.as_uint()) else {
180 return int_fault("无符号整数减法类型错误");
181 };
182 return left.checked_sub(right).map(Self::U64).unwrap_or_else(|| int_fault("无符号整数减法溢出"));
183 }
184 self
185 }
186}
187
188impl Div for Dynamic {
189 type Output = Self;
190 fn div(self, rhs: Self) -> Self::Output {
191 if self.is_float() && rhs.is_float() {
192 if self.is_f64() || rhs.is_f64() {
193 return Dynamic::F64(self.as_float().unwrap() / rhs.as_float().unwrap());
194 } else if self.is_f32() || rhs.is_f32() {
195 return Dynamic::F32(self.as_float().unwrap() as f32 / rhs.as_float().unwrap() as f32);
196 }
197 }
198 if self.is_int() || rhs.is_int() {
199 let Some((left, right)) = checked_i64(&self, &rhs, "整数除法类型或范围错误") else {
200 return Dynamic::Null;
201 };
202 return match left.checked_div(right) {
203 Some(value) => Self::I64(value),
204 None => {
205 crate::set_fault("整数除零");
206 Self::Null
207 }
208 };
209 }
210 if self.is_uint() || rhs.is_uint() {
211 let (Some(left), Some(right)) = (self.as_uint(), rhs.as_uint()) else {
212 return int_fault("无符号整数除法类型错误");
213 };
214 return match left.checked_div(right) {
215 Some(value) => Self::U64(value),
216 None => {
217 crate::set_fault("无符号整数除零");
218 Self::Null
219 }
220 };
221 }
222 self
223 }
224}
225
226impl Rem for Dynamic {
227 type Output = Self;
228 fn rem(self, rhs: Self) -> Self::Output {
229 if self.is_int() || rhs.is_int() {
230 let Some((left, right)) = checked_i64(&self, &rhs, "整数取余类型或范围错误") else {
231 return Dynamic::Null;
232 };
233 return match left.checked_rem(right) {
234 Some(value) => Self::I64(value),
235 None => {
236 crate::set_fault("整数取余除零");
237 Self::Null
238 }
239 };
240 }
241 if self.is_uint() || rhs.is_uint() {
242 let (Some(left), Some(right)) = (self.as_uint(), rhs.as_uint()) else {
243 return int_fault("无符号整数取余类型错误");
244 };
245 return match left.checked_rem(right) {
246 Some(value) => Self::U64(value),
247 None => {
248 crate::set_fault("无符号整数取余除零");
249 Self::Null
250 }
251 };
252 }
253 self
254 }
255}
256
257use std::ops::{Shl, Shr};
258
259impl Shl for Dynamic {
260 type Output = Self;
261 fn shl(self, rhs: Self) -> Self::Output {
262 use Dynamic::*;
263 let Some(shift) = rhs.as_int().and_then(|value| u32::try_from(value).ok()).or_else(|| rhs.as_uint().and_then(|value| u32::try_from(value).ok())) else {
264 return int_fault("位移数量类型或范围错误");
265 };
266 match self {
267 I8(i) => i.checked_shl(shift).map(I8).unwrap_or_else(|| int_fault("左移溢出")),
268 I16(i) => i.checked_shl(shift).map(I16).unwrap_or_else(|| int_fault("左移溢出")),
269 I32(i) => i.checked_shl(shift).map(I32).unwrap_or_else(|| int_fault("左移溢出")),
270 I64(i) => i.checked_shl(shift).map(I64).unwrap_or_else(|| int_fault("左移溢出")),
271 U8(i) => i.checked_shl(shift).map(U8).unwrap_or_else(|| int_fault("左移溢出")),
272 U16(i) => i.checked_shl(shift).map(U16).unwrap_or_else(|| int_fault("左移溢出")),
273 U32(i) => i.checked_shl(shift).map(U32).unwrap_or_else(|| int_fault("左移溢出")),
274 U64(i) => i.checked_shl(shift).map(U64).unwrap_or_else(|| int_fault("左移溢出")),
275 _ => Dynamic::I64(0),
276 }
277 }
278}
279
280impl Shr for Dynamic {
281 type Output = Self;
282 fn shr(self, rhs: Self) -> Self::Output {
283 use Dynamic::*;
284 let Some(shift) = rhs.as_int().and_then(|value| u32::try_from(value).ok()).or_else(|| rhs.as_uint().and_then(|value| u32::try_from(value).ok())) else {
285 return int_fault("位移数量类型或范围错误");
286 };
287 match self {
288 I8(i) => i.checked_shr(shift).map(I8).unwrap_or_else(|| int_fault("右移溢出")),
289 I16(i) => i.checked_shr(shift).map(I16).unwrap_or_else(|| int_fault("右移溢出")),
290 I32(i) => i.checked_shr(shift).map(I32).unwrap_or_else(|| int_fault("右移溢出")),
291 I64(i) => i.checked_shr(shift).map(I64).unwrap_or_else(|| int_fault("右移溢出")),
292 U8(i) => i.checked_shr(shift).map(U8).unwrap_or_else(|| int_fault("右移溢出")),
293 U16(i) => i.checked_shr(shift).map(U16).unwrap_or_else(|| int_fault("右移溢出")),
294 U32(i) => i.checked_shr(shift).map(U32).unwrap_or_else(|| int_fault("右移溢出")),
295 U64(i) => i.checked_shr(shift).map(U64).unwrap_or_else(|| int_fault("右移溢出")),
296 _ => Dynamic::I64(0),
297 }
298 }
299}
300
301use std::ops::{BitAnd, BitOr, BitXor};
302impl BitAnd for Dynamic {
303 type Output = Self;
304 fn bitand(self, rhs: Self) -> Self::Output {
305 let ty = self.get_type() + rhs.get_type();
306 let Ok(left) = ty.force(self) else {
307 return int_fault("按位与左操作数类型错误");
308 };
309 let Ok(right) = ty.force(rhs) else {
310 return int_fault("按位与右操作数类型错误");
311 };
312 match (left, right) {
313 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l & r),
314 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l & r),
315 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l & r),
316 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l & r),
317 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l & r),
318 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l & r),
319 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l & r),
320 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l & r),
321 (_, _) => Dynamic::Null,
322 }
323 }
324}
325
326#[cfg(test)]
327mod tests {
328 use super::*;
329
330 #[test]
331 fn negating_signed_min_values_does_not_panic() {
332 assert_eq!(-Dynamic::I8(i8::MIN), Dynamic::I8(i8::MIN));
333 assert_eq!(-Dynamic::I16(i16::MIN), Dynamic::I16(i16::MIN));
334 assert_eq!(-Dynamic::I32(i32::MIN), Dynamic::I32(i32::MIN));
335 assert_eq!(-Dynamic::I64(i64::MIN), Dynamic::I64(i64::MIN));
336 }
337
338 #[test]
339 fn not_is_logical_for_bool_and_bitwise_for_ints() {
340 assert_eq!(!Dynamic::Bool(false), Dynamic::Bool(true));
341 assert_eq!(!Dynamic::I32(0b1010), Dynamic::I32(!0b1010));
342 assert_eq!(!Dynamic::U32(0b1010), Dynamic::U32(!0b1010));
343 }
344}
345
346impl BitOr for Dynamic {
347 type Output = Self;
348 fn bitor(self, rhs: Self) -> Self::Output {
349 let ty = self.get_type() + rhs.get_type();
350 let Ok(left) = ty.force(self) else {
351 return int_fault("按位或左操作数类型错误");
352 };
353 let Ok(right) = ty.force(rhs) else {
354 return int_fault("按位或右操作数类型错误");
355 };
356 match (left, right) {
357 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l | r),
358 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l | r),
359 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l | r),
360 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l | r),
361 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l | r),
362 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l | r),
363 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l | r),
364 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l | r),
365 (_, _) => Dynamic::Null,
366 }
367 }
368}
369
370impl BitXor for Dynamic {
371 type Output = Self;
372 fn bitxor(self, rhs: Self) -> Self::Output {
373 let ty = self.get_type() + rhs.get_type();
374 let Ok(left) = ty.force(self) else {
375 return int_fault("按位异或左操作数类型错误");
376 };
377 let Ok(right) = ty.force(rhs) else {
378 return int_fault("按位异或右操作数类型错误");
379 };
380 match (left, right) {
381 (Dynamic::I8(l), Dynamic::I8(r)) => Dynamic::I8(l ^ r),
382 (Dynamic::I16(l), Dynamic::I16(r)) => Dynamic::I16(l ^ r),
383 (Dynamic::I32(l), Dynamic::I32(r)) => Dynamic::I32(l ^ r),
384 (Dynamic::I64(l), Dynamic::I64(r)) => Dynamic::I64(l ^ r),
385 (Dynamic::U8(l), Dynamic::U8(r)) => Dynamic::U8(l ^ r),
386 (Dynamic::U16(l), Dynamic::U16(r)) => Dynamic::U16(l ^ r),
387 (Dynamic::U32(l), Dynamic::U32(r)) => Dynamic::U32(l ^ r),
388 (Dynamic::U64(l), Dynamic::U64(r)) => Dynamic::U64(l ^ r),
389 (_, _) => Dynamic::Null,
390 }
391 }
392}