Skip to main content

int_cmp/
lib.rs

1//! Allow for comparisons between an unsigned integer and a signed integer
2//! # Example
3//!
4//! ```rust, no_run
5//! use int_cmp::IntCmp;
6//!
7//! let a = -25_i8;
8//! let b = 64_u8;
9//! assert!(a.cmp_lt(b));
10//!
11//! let x = -45000_i32;
12//! let y = 2560000_u64;
13//! assert!(x.cmp_ne(y));
14//!
15//! ```
16
17macro_rules! impl_signed_cmp {
18    // First type has to be unsigned and second signed
19    // Use this when MAX value of first type is smaller than max value of second type
20    ($u_small:ty => $i_big:ty) => {
21        impl IntCmp<$i_big> for $u_small {
22            #[inline(always)]
23            fn cmp_eq(self, other: $i_big) -> bool {
24                if other < 0 || other > <$u_small>::MAX as $i_big {
25                    return false;
26                }
27
28                self == other as $u_small
29            }
30
31            #[inline(always)]
32            fn cmp_ne(self, other: $i_big) -> bool {
33                if other < 0 || other > <$u_small>::MAX as $i_big {
34                    return true;
35                }
36
37                self != other as $u_small
38            }
39
40            #[inline(always)]
41            fn cmp_ge(self, other: $i_big) -> bool {
42                if other < 0 {
43                    return true;
44                } else if other > <$u_small>::MAX as $i_big {
45                    return false;
46                }
47
48                self >= other as $u_small
49            }
50
51            #[inline(always)]
52            fn cmp_gt(self, other: $i_big) -> bool {
53                if other < 0 {
54                    return true;
55                } else if other > <$u_small>::MAX as $i_big {
56                    return false;
57                }
58
59                self > other as $u_small
60            }
61
62            #[inline(always)]
63            fn cmp_le(self, other: $i_big) -> bool {
64                if other < 0 {
65                    return false;
66                } else if other > <$u_small>::MAX as $i_big {
67                    return true;
68                }
69
70                self <= other as $u_small
71            }
72
73            #[inline(always)]
74            fn cmp_lt(self, other: $i_big) -> bool {
75                if other < 0 {
76                    return false;
77                } else if other > <$u_small>::MAX as $i_big {
78                    return true;
79                }
80
81                self < other as $u_small
82            }
83        }
84    };
85
86    // First type has to be unsigned and second signed
87    // Use this when MAX value of first type is bigger than max value of second type
88    ($u_big:ty > $i_small:ty) => {
89        impl IntCmp<$i_small> for $u_big {
90            #[inline(always)]
91            fn cmp_eq(self, other: $i_small) -> bool {
92                if other < 0 {
93                    return false;
94                }
95
96                self == other as $u_big
97            }
98
99            #[inline(always)]
100            fn cmp_ne(self, other: $i_small) -> bool {
101                if other < 0 {
102                    return true;
103                }
104
105                self != other as $u_big
106            }
107
108            #[inline(always)]
109            fn cmp_ge(self, other: $i_small) -> bool {
110                if other < 0 {
111                    return true;
112                }
113
114                self >= other as $u_big
115            }
116
117            #[inline(always)]
118            fn cmp_gt(self, other: $i_small) -> bool {
119                if other < 0 {
120                    return true;
121                }
122
123                self > other as $u_big
124            }
125
126            #[inline(always)]
127            fn cmp_le(self, other: $i_small) -> bool {
128                if other < 0 {
129                    return false;
130                }
131
132                self <= other as $u_big
133            }
134
135            #[inline(always)]
136            fn cmp_lt(self, other: $i_small) -> bool {
137                if other < 0 {
138                    return false;
139                }
140
141                self < other as $u_big
142            }
143        }
144    };
145
146    // First type has to be signed and second unsigned
147    // Use this when MAX value of first type is smaller than max value of second type
148    ($i_small:ty ; $u_big:ty) => {
149        impl IntCmp<$u_big> for $i_small {
150            #[inline(always)]
151            fn cmp_eq(self, other: $u_big) -> bool {
152                if self < 0 {
153                    return false;
154                }
155
156                self as $u_big == other
157            }
158
159            #[inline(always)]
160            fn cmp_ne(self, other: $u_big) -> bool {
161                if self < 0 {
162                    return true;
163                }
164
165                self as $u_big != other
166            }
167
168            #[inline(always)]
169            fn cmp_ge(self, other: $u_big) -> bool {
170                if self < 0 {
171                    return false;
172                }
173
174                self as $u_big >= other
175            }
176
177            #[inline(always)]
178            fn cmp_gt(self, other: $u_big) -> bool {
179                if self < 0 {
180                    return false;
181                }
182
183                self as $u_big > other
184            }
185
186            #[inline(always)]
187            fn cmp_le(self, other: $u_big) -> bool {
188                if self < 0 {
189                    return true;
190                }
191
192                self as $u_big <= other
193            }
194
195            #[inline(always)]
196            fn cmp_lt(self, other: $u_big) -> bool {
197                if self < 0 {
198                    return true;
199                }
200
201                self as $u_big < other
202            }
203        }
204    };
205
206    // First type has to be signed and second unsigned
207    // Use this when MAX value of first type is bigger than max value of second type
208    ($i_big:ty | $u_small:ty) => {
209        impl IntCmp<$u_small> for $i_big {
210            #[inline(always)]
211            fn cmp_eq(self, other: $u_small) -> bool {
212                if self < 0 || self > <$u_small>::MAX as $i_big {
213                    return false;
214                }
215
216                self as $u_small == other
217            }
218
219            #[inline(always)]
220            fn cmp_ne(self, other: $u_small) -> bool {
221                if self < 0 || self > <$u_small>::MAX as $i_big {
222                    return true;
223                }
224
225                self as $u_small != other
226            }
227
228            #[inline(always)]
229            fn cmp_ge(self, other: $u_small) -> bool {
230                if self < 0 {
231                    return false;
232                } else if self > <$u_small>::MAX as $i_big {
233                    return true;
234                }
235
236                self as $u_small >= other
237            }
238
239            #[inline(always)]
240            fn cmp_gt(self, other: $u_small) -> bool {
241                if self < 0 {
242                    return false;
243                } else if self > <$u_small>::MAX as $i_big {
244                    return true;
245                }
246
247                self as $u_small > other
248            }
249
250            #[inline(always)]
251            fn cmp_le(self, other: $u_small) -> bool {
252                if self < 0 {
253                    return true;
254                } else if self > <$u_small>::MAX as $i_big {
255                    return false;
256                }
257
258                self as $u_small <= other
259            }
260
261            #[inline(always)]
262            fn cmp_lt(self, other: $u_small) -> bool {
263                if self < 0 {
264                    return true;
265                } else if self > <$u_small>::MAX as $i_big {
266                    return false;
267                }
268
269                self as $u_small < other
270            }
271        }
272    };
273}
274
275/// Comparison trait for integer types
276pub trait IntCmp<Other: Integer>: Integer {
277    fn cmp_eq(self, other: Other) -> bool;
278
279    fn cmp_ne(self, other: Other) -> bool;
280
281    fn cmp_ge(self, other: Other) -> bool;
282
283    fn cmp_gt(self, other: Other) -> bool;
284
285    fn cmp_le(self, other: Other) -> bool;
286
287    fn cmp_lt(self, other: Other) -> bool;
288}
289
290/// Standard integer type trait
291pub trait Integer {}
292
293impl Integer for u8 {}
294impl Integer for u16 {}
295impl Integer for u32 {}
296impl Integer for u64 {}
297impl Integer for u128 {}
298impl Integer for usize {}
299impl Integer for i8 {}
300impl Integer for i16 {}
301impl Integer for i32 {}
302impl Integer for i64 {}
303impl Integer for i128 {}
304
305impl_signed_cmp! {u8 > i8}
306impl_signed_cmp! {u8 => i16}
307impl_signed_cmp! {u8 => i32}
308impl_signed_cmp! {u8 => i64}
309impl_signed_cmp! {u8 => i128}
310
311impl_signed_cmp! {u16 > i8}
312impl_signed_cmp! {u16 > i16}
313impl_signed_cmp! {u16 => i32}
314impl_signed_cmp! {u16 => i64}
315impl_signed_cmp! {u16 => i128}
316
317impl_signed_cmp! {u32 > i8}
318impl_signed_cmp! {u32 > i16}
319impl_signed_cmp! {u32 > i32}
320impl_signed_cmp! {u32 => i64}
321impl_signed_cmp! {u32 => i128}
322
323impl_signed_cmp! {u64 > i8}
324impl_signed_cmp! {u64 > i16}
325impl_signed_cmp! {u64 > i32}
326impl_signed_cmp! {u64 > i64}
327impl_signed_cmp! {u64 => i128}
328
329impl_signed_cmp! {u128 > i8}
330impl_signed_cmp! {u128 > i16}
331impl_signed_cmp! {u128 > i32}
332impl_signed_cmp! {u128 > i64}
333impl_signed_cmp! {u128 > i128}
334
335impl_signed_cmp! {usize > i8}
336impl_signed_cmp! {usize > i16}
337impl_signed_cmp! {usize > i32}
338#[cfg(target_pointer_width = "32")]
339impl_signed_cmp! {usize => i64}
340#[cfg(target_pointer_width = "64")]
341impl_signed_cmp! {usize > i64}
342impl_signed_cmp! {usize => i128}
343
344impl_signed_cmp! {i8 ; u8}
345impl_signed_cmp! {i8 ; u16}
346impl_signed_cmp! {i8 ; u32}
347impl_signed_cmp! {i8 ; u64}
348impl_signed_cmp! {i8 ; u128}
349impl_signed_cmp! {i8 ; usize}
350
351impl_signed_cmp! {i16 | u8}
352impl_signed_cmp! {i16 ; u16}
353impl_signed_cmp! {i16 ; u32}
354impl_signed_cmp! {i16 ; u64}
355impl_signed_cmp! {i16 ; u128}
356impl_signed_cmp! {i16 ; usize}
357
358impl_signed_cmp! {i32 | u8}
359impl_signed_cmp! {i32 | u16}
360impl_signed_cmp! {i32 ; u32}
361impl_signed_cmp! {i32 ; u64}
362impl_signed_cmp! {i32 ; u128}
363impl_signed_cmp! {i32 ; usize}
364
365impl_signed_cmp! {i64 | u8}
366impl_signed_cmp! {i64 | u16}
367impl_signed_cmp! {i64 | u32}
368impl_signed_cmp! {i64 ; u64}
369impl_signed_cmp! {i64 ; u128}
370#[cfg(target_pointer_width = "32")]
371impl_signed_cmp! {i64 | usize}
372#[cfg(target_pointer_width = "64")]
373impl_signed_cmp! {i64 ; usize}
374
375impl_signed_cmp! {i128 | u8}
376impl_signed_cmp! {i128 | u16}
377impl_signed_cmp! {i128 | u32}
378impl_signed_cmp! {i128 | u64}
379impl_signed_cmp! {i128 ; u128}
380impl_signed_cmp! {i128 | usize}