rbatis_codegen/
ops_div.rs1use crate::ops::{AsProxy, Div};
2use crate::ops_compare::integer_value;
3use crate::ops_macros::{impl_numeric_binary_op, impl_same_type_binary_op, impl_value_binary_op};
4use rbs::Value;
5
6fn op_div_u64(value: &Value, other: u64) -> u64 {
7 if other == 0 {
8 return 0;
9 }
10 value.u64() / other
11}
12
13fn op_div_i64(value: &Value, other: i64) -> i64 {
14 if other == 0 {
15 return 0;
16 }
17 value.i64() / other
18}
19
20fn op_div_f64(value: &Value, other: f64) -> f64 {
21 if other == 0.0 {
22 0.0
23 } else {
24 value.f64() / other
25 }
26}
27
28fn op_div_i64_value(value: &Value, other: i64) -> i64 {
29 let rhs = value.i64();
30 if rhs == 0 {
31 return 0;
32 }
33 other / rhs
34}
35
36fn op_div_u64_value(value: &Value, other: u64) -> u64 {
37 let rhs = value.u64();
38 if rhs == 0 {
39 return 0;
40 }
41 other / rhs
42}
43
44fn op_div_f64_value(value: &Value, other: f64) -> f64 {
45 let rhs = value.f64();
46 if rhs == 0.0 {
47 0.0
48 } else {
49 other / rhs
50 }
51}
52
53fn integer_div(left: i128, rhs: &Value) -> Option<i128> {
54 let rhs = integer_value(rhs)?;
55 if rhs == 0 {
56 Some(0)
57 } else {
58 Some(left / rhs)
59 }
60}
61
62fn op_div_value(left: Value, rhs: Value) -> Value {
63 match left {
64 Value::I32(value) => {
65 if let Some(result) = integer_div(value as i128, &rhs) {
66 return i32::try_from(result)
67 .map(Value::I32)
68 .unwrap_or(Value::I32(0));
69 }
70 let rhs = rhs.f64();
71 if rhs == 0.0 {
72 return Value::I32(0);
73 }
74 Value::I32((value as f64 / rhs) as i32)
75 }
76 Value::I64(value) => {
77 if let Some(result) = integer_div(value as i128, &rhs) {
78 return i64::try_from(result)
79 .map(Value::I64)
80 .unwrap_or(Value::I64(0));
81 }
82 let rhs = rhs.f64();
83 if rhs == 0.0 {
84 return Value::I64(0);
85 }
86 Value::I64((value as f64 / rhs) as i64)
87 }
88 Value::U32(value) => {
89 if let Some(result) = integer_div(value as i128, &rhs) {
90 return u32::try_from(result)
91 .map(Value::U32)
92 .unwrap_or(Value::U32(0));
93 }
94 let rhs = rhs.f64();
95 if rhs == 0.0 {
96 return Value::U32(0);
97 }
98 Value::U32((value as f64 / rhs) as u32)
99 }
100 Value::U64(value) => {
101 if let Some(result) = integer_div(value as i128, &rhs) {
102 return u64::try_from(result)
103 .map(Value::U64)
104 .unwrap_or(Value::U64(0));
105 }
106 let rhs = rhs.f64();
107 if rhs == 0.0 {
108 return Value::U64(0);
109 }
110 Value::U64((value as f64 / rhs) as u64)
111 }
112 Value::F32(value) => Value::F32(value / rhs.f64() as f32),
113 Value::F64(value) => Value::F64(value / rhs.f64()),
114 Value::Ext(_, value) => op_div_value(*value, rhs),
115 _ => Value::Null,
116 }
117}
118
119impl_value_binary_op!(Div, op_div, op_div_value);
120impl_numeric_binary_op!(
121 Div,
122 op_div,
123 op_div_u64,
124 op_div_u64_value,
125 [u8, u16, u32, u64],
126 u64
127);
128impl_numeric_binary_op!(
129 Div,
130 op_div,
131 op_div_i64,
132 op_div_i64_value,
133 [i8, i16, i32, i64, isize, usize],
134 i64
135);
136impl_numeric_binary_op!(Div, op_div, op_div_f64, op_div_f64_value, [f32, f64], f64);
137impl_same_type_binary_op!(
138 Div,
139 op_div,
140 /,
141 [
142 u8, u16, u32, u64, i8, i16, i32, i64, isize, usize, f32, f64
143 ]
144);
145
146#[cfg(test)]
147mod test {
148 use crate::ops::Div;
149 use rbs::Value;
150
151 #[test]
152 fn test_div() {
153 let value = Value::I32(12);
154 assert_eq!((&value).op_div(&4i64), 3i64);
155 assert_eq!(value.op_div(4i64), 3i64);
156 assert_eq!(Value::I32(12).op_div(&&Value::I32(4)), Value::I32(3));
157 }
158
159 #[test]
160 fn test_div_by_zero() {
161 assert_eq!(Value::I32(12).op_div(0i64), 0i64);
162 assert_eq!((&Value::I32(12)).op_div(&&Value::I32(0)), Value::I32(0));
163 }
164
165 #[test]
166 fn test_integer_div_keeps_precision() {
167 let large = Value::I64(9_007_199_254_740_993);
168 assert_eq!(
169 large.op_div(&Value::I64(1)),
170 Value::I64(9_007_199_254_740_993)
171 );
172 assert_eq!(Value::I64(10).op_div(&Value::U64(3)), Value::I64(3));
173 }
174}