rbatis_codegen/
ops_rem.rs1use crate::ops::{AsProxy, Rem};
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_rem_u64(value: &Value, other: u64) -> u64 {
7 if other == 0 {
8 return 0;
9 }
10 value.u64() % other
11}
12
13fn op_rem_i64(value: &Value, other: i64) -> i64 {
14 if other == 0 {
15 return 0;
16 }
17 value.i64() % other
18}
19
20fn op_rem_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_rem_u64_value(value: &Value, other: u64) -> u64 {
29 let rhs = value.u64();
30 if rhs == 0 {
31 return 0;
32 }
33 other % rhs
34}
35
36fn op_rem_i64_value(value: &Value, other: i64) -> i64 {
37 let rhs = value.i64();
38 if rhs == 0 {
39 return 0;
40 }
41 other % rhs
42}
43
44fn op_rem_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_rem(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_rem_value(left: Value, rhs: Value) -> Value {
63 match left {
64 Value::I32(value) => {
65 if let Some(result) = integer_rem(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_rem(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_rem(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_rem(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) => {
113 let rhs = rhs.f64() as f32;
114 if rhs == 0.0 {
115 return Value::F32(0.0);
116 }
117 Value::F32(value % rhs)
118 }
119 Value::F64(value) => {
120 let rhs = rhs.f64();
121 if rhs == 0.0 {
122 return Value::F64(0.0);
123 }
124 Value::F64(value % rhs)
125 }
126 Value::Ext(_, value) => op_rem_value(*value, rhs),
127 _ => Value::Null,
128 }
129}
130
131impl_value_binary_op!(Rem, op_rem, op_rem_value);
132impl_numeric_binary_op!(
133 Rem,
134 op_rem,
135 op_rem_u64,
136 op_rem_u64_value,
137 [u8, u16, u32, u64],
138 u64
139);
140impl_numeric_binary_op!(
141 Rem,
142 op_rem,
143 op_rem_i64,
144 op_rem_i64_value,
145 [i8, i16, i32, i64, isize, usize],
146 i64
147);
148impl_numeric_binary_op!(Rem, op_rem, op_rem_f64, op_rem_f64_value, [f32, f64], f64);
149impl_same_type_binary_op!(
150 Rem,
151 op_rem,
152 %,
153 [
154 u8, u16, u32, u64, i8, i16, i32, i64, isize, usize, f32, f64
155 ]
156);
157
158#[cfg(test)]
159mod test {
160 use crate::ops::Rem;
161 use rbs::Value;
162
163 #[test]
164 fn test_rem() {
165 let value = Value::I32(13);
166 assert_eq!((&value).op_rem(&5i64), 3i64);
167 assert_eq!(value.op_rem(5i64), 3i64);
168 assert_eq!(Value::I32(13).op_rem(&&Value::I32(5)), Value::I32(3));
169 }
170
171 #[test]
172 fn test_rem_by_zero() {
173 assert_eq!(Value::I32(13).op_rem(0i64), 0i64);
174 assert_eq!((&Value::I32(13)).op_rem(&&Value::I32(0)), Value::I32(0));
175 }
176
177 #[test]
178 fn test_integer_rem_keeps_precision() {
179 assert_eq!(
180 Value::I64(9_007_199_254_740_993).op_rem(&Value::I64(2)),
181 Value::I64(1)
182 );
183 assert_eq!(Value::I64(-5).op_rem(&Value::U64(2)), Value::I64(-1));
184 }
185}