konst/macros/
declare_cmp_fn_macros.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! __declare_string_cmp_fns {
4    (
5        import_path = $path:expr,
6
7        equality_fn = $eq_str:ident,
8        ordering_fn = $cmp_str:ident,
9        /// Equivalent to ordering_fn, but returns a U8Ordering
10        ordering_fn_inner = $cmp_str_inner:ident,
11    ) => {
12        $crate::__declare_string_cmp_fns! {
13            @inner
14            equality_fn = $eq_str,
15            ordering_fn = $cmp_str,
16            use_eq_str = concat!("use ", $path, "::", stringify!($eq_str), ";"),
17            use_cmp_str = concat!("use ", $path, "::", stringify!($cmp_str), ";"),
18        }
19    };
20    (@inner
21
22        equality_fn = $eq_str:ident,
23        ordering_fn = $cmp_str:ident,
24        use_eq_str = $eq_str_import:expr,
25        use_cmp_str = $cmp_str_import:expr,
26    ) => {
27        $crate::__delegate_const_eq! {
28            skip_coerce;
29            /// A const equivalent of `&str` equality comparison.
30            ///
31            /// # Example
32            ///
33            /// ```rust
34            #[doc = $eq_str_import]
35            ///
36            /// const FOO: &str = "foo";
37            /// const BAR: &str = "fooooo";
38            /// const BAZ: &str = "bar";
39            ///
40            ///
41            /// const FOO_EQ_FOO: bool = eq_str(FOO, FOO);
42            /// assert!( FOO_EQ_FOO );
43            ///
44            /// const FOO_EQ_BAR: bool = eq_str(FOO, BAR);
45            /// assert!( !FOO_EQ_BAR );
46            ///
47            /// const FOO_EQ_BAZ: bool = eq_str(FOO, BAZ);
48            /// assert!( !FOO_EQ_BAZ );
49            ///
50            /// ```
51            ///
52            #[inline]
53            pub const fn eq_str(ref left: &str, right: &str) -> bool {
54                let left = left.as_bytes();
55                let right = right.as_bytes();
56
57                if left.len() != right.len() {
58                    return false;
59                }
60
61                let mut i = 0;
62                while i != left.len() {
63                    if left[i] != right[i] {
64                        return false;
65                    }
66                    i += 1;
67                }
68
69                true
70            }
71        }
72
73        __delegate_const_ord! {
74            skip_coerce;
75            /// A const equivalent of `str::cmp`.
76            ///
77            /// # Example
78            ///
79            /// ```rust
80            #[doc = $cmp_str_import]
81            ///
82            /// use std::cmp::Ordering;
83            ///
84            /// const FOO: &str = "foo";
85            /// const BAR: &str = "fooooo";
86            /// const BAZ: &str = "bar";
87            ///
88            ///
89            /// const FOO_CMP_FOO: Ordering = cmp_str(FOO, FOO);
90            /// assert_eq!(FOO_CMP_FOO, Ordering::Equal);
91            ///
92            /// const FOO_CMP_BAR: Ordering = cmp_str(FOO, BAR);
93            /// assert_eq!(FOO_CMP_BAR, Ordering::Less);
94            ///
95            /// const FOO_CMP_BAZ: Ordering = cmp_str(FOO, BAZ);
96            /// assert_eq!(FOO_CMP_BAZ, Ordering::Greater);
97            ///
98            /// ```
99            ///
100            #[inline]
101            pub const fn cmp_str(ref left: &str, right: &str) -> $crate::__::Ordering {
102                cmp_str_inner(left.as_bytes(), right.as_bytes()).to_ordering()
103            }
104        }
105
106        #[inline]
107        const fn cmp_str_inner(left: &[u8], right: &[u8]) -> $crate::__::U8Ordering {
108            use $crate::__::U8Ordering;
109
110            let left_len = left.len();
111            let right_len = right.len();
112            let (min_len, on_ne) = if left_len < right_len {
113                (left_len, U8Ordering::LESS)
114            } else {
115                (right_len, U8Ordering::GREATER)
116            };
117
118            let mut i = 0;
119            while i < min_len {
120                $crate::__priv_ret_if_ne! {left[i], right[i]}
121                i += 1;
122            }
123
124            if left_len == right_len {
125                U8Ordering::EQUAL
126            } else {
127                on_ne
128            }
129        }
130    };
131}
132
133#[doc(hidden)]
134#[macro_export]
135macro_rules!  __declare_slice_cmp_fns{
136    (
137        import_path = $path:expr,
138
139
140        $((
141            $(#[$attr_both:meta])*,
142            $(#[$attr_eq:meta])*,
143            $(#[$attr_ord:meta])*,
144            $type:ty,
145            $eq_fn_name:ident,
146            $cmp_fn_name:ident,
147        ))*
148    )=>{
149        $(
150            __declare_slice_cmp_fns!{
151                @step_two
152                    import_path = $path,
153
154                    $(#[$attr_both])*,
155                    $(#[$attr_eq])*,
156                    $(#[$attr_ord])*,
157                    concat!(
158                        "Compares two `&[",
159                        stringify!($type),
160                        "]` for equality.",
161                    ),
162                    concat!(
163                        "Compares two `&[",
164                        stringify!($type),
165                        "]`, returning the order of `left` relative to `right`.",
166                    ),
167                    $type,
168                    $eq_fn_name,
169                    $cmp_fn_name,
170            }
171        )*
172    };
173    (@step_two
174        import_path = $path:expr,
175
176        $(#[$attr_both:meta])*,
177        $(#[$attr_eq:meta])*,
178        $(#[$attr_ord:meta])*,
179        $docs_eq:expr,
180        $docs_ord:expr,
181        $ty:ty,
182        $eq_fn_name:ident,
183        $cmp_fn_name:ident,
184    ) => {
185        $crate::__delegate_const_eq!{
186            skip_coerce;
187
188            #[doc = $docs_eq]
189            $(#[$attr_both])*
190            $(#[$attr_eq])*
191            #[inline]
192            pub const fn $eq_fn_name(ref left: &[$ty], right: &[$ty]) -> bool {
193                if left.len() != right.len() {
194                    return false;
195                }
196
197                let mut i = 0;
198                while i != left.len() {
199                    if left[i] != right[i] {
200                        return false;
201                    }
202                    i += 1;
203                }
204
205                true
206            }
207        }
208
209
210
211        __delegate_const_ord!{
212            skip_coerce;
213            for['a,]
214
215            #[doc = $docs_ord]
216            $(#[$attr_both])*
217            $(#[$attr_ord])*
218            #[inline]
219            pub const fn $cmp_fn_name(ref left: &[$ty], right: &[$ty]) -> $crate::__::Ordering {
220                use $crate::__::U8Ordering;
221
222                const fn cmp_inner(left: &[$ty], right: &[$ty]) -> $crate::__::U8Ordering {
223                    let left_len = left.len();
224
225                    $crate::__priv_ret_if_ne! {left_len, right.len()}
226
227                    let mut i = 0;
228                    while i < left_len {
229                        $crate::__priv_ret_if_ne! {left[i], right[i]}
230                        i += 1;
231                    }
232
233                    U8Ordering::EQUAL
234                }
235
236                cmp_inner(left, right).to_ordering()
237            }
238        }
239
240    };
241}
242
243#[doc(hidden)]
244#[macro_export]
245macro_rules!  __declare_fns_with_docs{
246    (
247        $(($($args:tt)*))*
248
249        docs $docs:tt
250
251        macro = $macro:ident ! $macro_prefix:tt,
252    )=>{
253        $(
254            $crate::__declare_fns_with_docs!{
255                @inner
256                ($($args)*)
257
258                docs $docs
259
260                macro = $macro ! $macro_prefix,
261            }
262        )*
263    };
264    (@inner
265        (
266            $type:ty,
267            ($($func_name:ident),* $(,)?)
268            $($rem:tt)*
269        )
270
271        docs(
272            $(($before:expr, $after:expr))*
273        )
274
275        macro = $macro:ident ! ($($prefix:tt)*),
276    ) => {
277
278        $macro!{
279            $($prefix)*
280            ($type, ($($func_name),*) $($rem)* )
281
282            docs(
283                $(concat!($before, stringify!($type), $after)),*
284            )
285        }
286
287
288    };
289    (@inner
290        (
291            $type:ty,
292            ($($func_name:ident),* $(,)?)
293            $($rem:tt)*
294        )
295
296        docs(default)
297
298        macro = $macro:ident ! ($($prefix:tt)*),
299    ) => {
300
301        $macro!{
302            $($prefix)*
303            ($type, ($($func_name),*) $($rem)* )
304
305            docs(
306                concat!(
307                    "Compares two `",
308                    stringify!($type),
309                    "` for equality.",
310                ),
311                concat!(
312                    "Compares two `",
313                    stringify!($type),
314                    "`, returning the ordering of `left` relative to `right`."
315                ),
316            )
317        }
318
319
320    };
321}
322
323macro_rules! __impl_option_cmp_fns {
324    (
325        $(#[$attr:meta])*
326        $(for[$($impl:tt)*])?
327        params($l:ident, $r:ident)
328        eq_comparison = $eq_comparison:expr,
329        cmp_comparison = $cmp_comparison:expr,
330        parameter_copyability = $copyab:ident,
331
332        ($type:ty, ($eq_fn_name:ident, $cmp_fn_name:ident))
333
334        docs( $docs_eq:expr, $docs_cmp:expr, )
335    ) => (
336        __delegate_const_eq!{
337            $(for[$($impl)*])?
338
339            #[doc = $docs_eq]
340            $(#[$attr])*
341            pub const fn $eq_fn_name($copyab left: $type, right: $type) -> bool {
342                match (left, right) {
343                    (Some($l), Some($r)) => $eq_comparison,
344                    (None, None) => true,
345                    _ => false,
346                }
347            }
348        }
349
350        __delegate_const_ord!{
351            $(for[$($impl)*])?
352
353            #[doc = $docs_cmp]
354            $(#[$attr])*
355            pub const fn $cmp_fn_name($copyab left: $type, right: $type) -> core::cmp::Ordering {
356                use core::cmp::Ordering;
357
358                match (left, right) {
359                    (Some($l), Some($r)) => $cmp_comparison,
360                    (Some(_), None) => Ordering::Greater,
361                    (None, Some(_)) => Ordering::Less,
362                    (None, None) => Ordering::Equal,
363                }
364            }
365        }
366    )
367}