multisql/data/value/methods/
binary.rs1#![allow(clippy::should_implement_trait)] use {
4 super::ValueCore,
5 crate::{Convert, ConvertFrom, Result, Value, ValueError},
6};
7
8macro_rules! natural_binary_op {
10 ($name: ident, $trait: ident, $op: tt) => {
11 pub fn $name<Core>(self, other: Self) -> Result<Self>
12 where
13 Core: ValueCore + $trait<Output = Core>,
14 {
15 let (left, right) = (Core::convert_from(self)?, Core::convert_from(other)?);
16 let result = left $op right;
17 Ok(result.into())
18 }
19 };
20}
21macro_rules! natural_binary_ops {
22 ($(($name: ident, $trait: ident, $op: tt, $generic_name: ident)),+) => {
23 use std::ops::{$($trait),+};
24 impl Value {
25 $(
26 natural_binary_op!($name, $trait, $op);
27 generic!($name, $generic_name);
28 )+
29 }
30 }
31}
32
33macro_rules! boolean_binary_op {
34 ($name: ident, $op: tt) => {
35 pub fn $name(self, other: Self) -> Result<Self>
36 {
37 let (left, right): (bool, bool) = (self.convert()?, other.convert()?);
38 let result = left $op right;
39 Ok(result.into())
40 }
41 };
42}
43macro_rules! boolean_binary_ops {
44 ($(($name: ident, $op: tt)),+) => {
45 impl Value {
46 $(boolean_binary_op!($name, $op);)+
47 }
48 }
49}
50
51macro_rules! comparative_binary_op {
52 ($name: ident, $op: tt) => {
53 pub fn $name(self, other: Self) -> Result<Self> {
54 Ok(Value::Bool(self $op other))
55 }
56 };
57}
58macro_rules! comparative_binary_ops {
59 ($(($name: ident, $op: tt)),+) => {
60 impl Value {
61 $(comparative_binary_op!($name, $op);)+
62 }
63 }
64}
65
66macro_rules! generic {
67 ($name: ident, $generic_name: ident) => {
68 pub fn $generic_name(self, other: Self) -> Result<Self> {
69 if matches!(self, Value::Null) || matches!(other, Value::Null) {
70 Ok(Value::Null)
71 } else if !i64::convert_from(self.clone()).is_err()
72 && !i64::convert_from(other.clone()).is_err()
73 {
74 self.$name::<i64>(other)
75 } else if !f64::convert_from(self.clone()).is_err()
76 && !f64::convert_from(other.clone()).is_err()
77 {
78 self.$name::<f64>(other)
79 } else {
80 Err(ValueError::OnlySupportsNumeric(
81 if f64::convert_from(self.clone()).is_err() {
82 self
83 } else {
84 other
85 },
86 stringify!($name),
87 )
88 .into())
89 }
90 }
91 };
92}
93
94natural_binary_ops!(
95 (add, Add, +, generic_add),
96 (subtract, Sub, -, generic_subtract),
97 (multiply, Mul, *, generic_multiply),
98 (divide, Div, /, generic_divide),
99 (modulus, Rem, %, generic_modulus)
100);
101
102boolean_binary_ops!(
103 (and, &),
104 (or, |),
105 (xor, ^)
106);
107
108comparative_binary_ops!(
109 (eq, ==),
110 (not_eq, !=),
111 (gt, >),
112 (gt_eq, >=),
113 (lt, <),
114 (lt_eq, <=)
115);
116
117impl Value {
118 pub fn string_concat(self, other: Self) -> Result<Self> {
119 if matches!(self, Value::Null) || matches!(other, Value::Null) {
120 Ok(Value::Null)
121 } else {
122 Ok(format!(
123 "{}{}",
124 String::convert_from(self)?,
125 String::convert_from(other)?
126 )
127 .into())
128 }
129 }
130}