rune/modules/
cmp.rs

1//! Comparison and ordering.
2
3use core::cmp::Ordering;
4
5use crate as rune;
6use crate::alloc;
7use crate::alloc::fmt::TryWrite;
8use crate::runtime::{Formatter, Protocol, Value};
9use crate::shared::Caller;
10use crate::{docstring, hash_in};
11use crate::{ContextError, Hash, Module, VmError};
12
13/// Comparison and ordering.
14#[rune::module(::std::cmp)]
15pub fn module() -> Result<Module, ContextError> {
16    let mut m = Module::from_meta(self::module__meta)?;
17
18    {
19        let ty = m.ty::<Ordering>()?.docs(docstring! {
20            /// An `Ordering` is the result of a comparison between two values.
21            ///
22            /// # Examples
23            ///
24            /// ```rune
25            /// use std::cmp::Ordering;
26            /// use std::ops::cmp;
27            ///
28            /// let result = 1.cmp(2);
29            /// assert_eq!(Ordering::Less, result);
30            ///
31            /// let result = 1.cmp(1);
32            /// assert_eq!(Ordering::Equal, result);
33            ///
34            /// let result = 2.cmp(1);
35            /// assert_eq!(Ordering::Greater, result);
36            /// ```
37        })?;
38
39        let mut ty = ty.make_enum(&["Less", "Equal", "Greater"])?;
40
41        ty.variant_mut(0)?
42            .make_empty()?
43            .constructor(|| Ordering::Less)?
44            .docs(docstring! {
45                /// "An ordering where a compared value is less than another.
46            })?;
47
48        ty.variant_mut(1)?
49            .make_empty()?
50            .constructor(|| Ordering::Equal)?
51            .docs(docstring! {
52                /// "An ordering where a compared value is equal to another.
53            })?;
54
55        ty.variant_mut(2)?
56            .make_empty()?
57            .constructor(|| Ordering::Greater)?
58            .docs(docstring! {
59                /// "An ordering where a compared value is greater than another.
60            })?;
61
62        m.function_meta(ordering_is_variant__meta)?;
63    }
64
65    m.function_meta(ordering_partial_eq__meta)?;
66    m.implement_trait::<Ordering>(rune::item!(::std::cmp::PartialEq))?;
67
68    m.function_meta(ordering_eq__meta)?;
69    m.implement_trait::<Ordering>(rune::item!(::std::cmp::Eq))?;
70
71    m.function_meta(ordering_debug_fmt)?;
72    m.function_meta(min__meta)?;
73    m.function_meta(max__meta)?;
74
75    let mut t = m.define_trait(["PartialEq"])?;
76
77    t.docs(docstring! {
78        /// Trait for comparisons using the equality operator.
79        ///
80        /// Implementing this trait for types provides the `==` and `!=`
81        /// operators for those types.
82        ///
83        /// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written
84        /// `x != y`. We use the easier-to-read infix notation in the remainder
85        /// of this documentation.
86        ///
87        /// This trait allows for comparisons using the equality operator, for
88        /// types that do not have a full equivalence relation. For example, in
89        /// floating point numbers `NaN != NaN`, so floating point types
90        /// implement `PartialEq` but not [`trait@Eq`]. Formally speaking, when
91        /// `Rhs == Self`, this trait corresponds to a [partial equivalence
92        /// relation].
93        ///
94        /// [partial equivalence relation]:
95        ///     https://en.wikipedia.org/wiki/Partial_equivalence_relation
96        ///
97        /// Implementations must ensure that `eq` and `ne` are consistent with
98        /// each other:
99        ///
100        /// - `a != b` if and only if `!(a == b)`.
101        ///
102        /// The default implementation of `ne` provides this consistency and is
103        /// almost always sufficient. It should not be overridden without very
104        /// good reason.
105        ///
106        /// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and
107        /// `Rhs`, their methods must also be consistent with `PartialEq` (see
108        /// the documentation of those traits for the exact requirements). It's
109        /// easy to accidentally make them disagree by deriving some of the
110        /// traits and manually implementing others.
111        ///
112        /// The equality relation `==` must satisfy the following conditions
113        /// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
114        ///
115        /// - **Symmetry**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then
116        ///   **`a == b` implies `b == a`**; and
117        ///
118        /// - **Transitivity**: if `A: PartialEq<B>` and `B: PartialEq<C>` and
119        ///   `A: PartialEq<C>`, then **`a == b` and `b == c` implies `a ==
120        ///   c`**. This must also work for longer chains, such as when `A:
121        ///   PartialEq<B>`, `B: PartialEq<C>`, `C: PartialEq<D>`, and `A:
122        ///   PartialEq<D>` all exist.
123        ///
124        /// Note that the `B: PartialEq<A>` (symmetric) and `A: PartialEq<C>`
125        /// (transitive) impls are not forced to exist, but these requirements
126        /// apply whenever they do exist.
127        ///
128        /// Violating these requirements is a logic error. The behavior
129        /// resulting from a logic error is not specified, but users of the
130        /// trait must ensure that such logic errors do *not* result in
131        /// undefined behavior. This means that `unsafe` code **must not** rely
132        /// on the correctness of these methods.
133        ///
134        /// ## Cross-crate considerations
135        ///
136        /// Upholding the requirements stated above can become tricky when one
137        /// crate implements `PartialEq` for a type of another crate (i.e., to
138        /// allow comparing one of its own types with a type from the standard
139        /// library). The recommendation is to never implement this trait for a
140        /// foreign type. In other words, such a crate should do `impl
141        /// PartialEq<ForeignType> for LocalType`, but it should *not* do `impl
142        /// PartialEq<LocalType> for ForeignType`.
143        ///
144        /// This avoids the problem of transitive chains that criss-cross crate
145        /// boundaries: for all local types `T`, you may assume that no other
146        /// crate will add `impl`s that allow comparing `T == U`. In other
147        /// words, if other crates add `impl`s that allow building longer
148        /// transitive chains `U1 == ... == T == V1 == ...`, then all the types
149        /// that appear to the right of `T` must be types that the crate
150        /// defining `T` already knows about. This rules out transitive chains
151        /// where downstream crates can add new `impl`s that "stitch together"
152        /// comparisons of foreign types in ways that violate transitivity.
153        ///
154        /// Not having such foreign `impl`s also avoids forward compatibility
155        /// issues where one crate adding more `PartialEq` implementations can
156        /// cause build failures in downstream crates.
157        ///
158        /// # Examples
159        ///
160        /// ```rune
161        /// let x = 0;
162        /// let y = 1;
163        ///
164        /// assert_eq!(x == y, false);
165        /// assert_eq!(x.eq(y), false);
166        ///
167        /// assert!((1.0).eq(1.0));
168        /// assert!(!(1.0).eq(2.0));
169        ///
170        /// assert!(1.0 == 1.0);
171        /// assert!(1.0 != 2.0);
172        /// ```
173    })?;
174
175    t.handler(|cx| {
176        let partial_eq = cx.find(&Protocol::PARTIAL_EQ)?;
177        let partial_eq = Caller::<(Value, Value), 2, bool>::new(partial_eq);
178
179        cx.function("ne", move |a: Value, b: Value| -> Result<bool, VmError> {
180            Ok(!partial_eq.call((a, b))?)
181        })?;
182
183        Ok(())
184    })?;
185
186    t.function("eq")?
187        .argument_types::<(Value, Value)>()?
188        .return_type::<bool>()?
189        .docs(docstring! {
190            /// Compare two values for equality.
191            ///
192            /// # Examples
193            ///
194            /// ```rune
195            /// assert_eq!(1.eq(2), false);
196            /// assert_eq!(2.eq(2), true);
197            /// assert_eq!(2.eq(1), false);
198            /// ```
199        })?;
200
201    t.function("ne")?
202        .argument_types::<(Value, Value)>()?
203        .return_type::<bool>()?
204        .docs(docstring! {
205            /// Compare two values for inequality.
206            ///
207            /// # Examples
208            ///
209            /// ```rune
210            /// assert_eq!(1.ne(2), true);
211            /// assert_eq!(2.ne(2), false);
212            /// assert_eq!(2.ne(1), true);
213            /// ```
214        })?;
215
216    let mut t = m.define_trait(["Eq"])?;
217
218    t.docs(docstring! {
219        /// Trait for comparisons corresponding to [equivalence relations](
220        /// https://en.wikipedia.org/wiki/Equivalence_relation).
221        ///
222        /// This means, that in addition to `a == b` and `a != b` being strict
223        /// inverses, the relation must be (for all `a`, `b` and `c`):
224        ///
225        /// - reflexive: `a == a`;
226        /// - symmetric: `a == b` implies `b == a` (required by `PartialEq` as
227        ///   well); and
228        /// - transitive: `a == b` and `b == c` implies `a == c` (required by
229        ///   `PartialEq` as well).
230        ///
231        /// This property cannot be checked by the compiler, and therefore `Eq`
232        /// implies [`PartialEq`], and has no extra methods.
233        ///
234        /// Violating this property is a logic error. The behavior resulting
235        /// from a logic error is not specified, but users of the trait must
236        /// ensure that such logic errors do *not* result in undefined behavior.
237        /// This means that `unsafe` code **must not** rely on the correctness
238        /// of these methods.
239        ///
240        /// Implement `Eq` in addition to `PartialEq` if it's guaranteed that
241        /// `PartialEq::eq(a, a)` always returns `true` (reflexivity), in
242        /// addition to the symmetric and transitive properties already required
243        /// by `PartialEq`.
244        /// ```
245    })?;
246
247    t.handler(|cx| {
248        _ = cx.find(&Protocol::EQ)?;
249        Ok(())
250    })?;
251
252    t.docs(docstring! {
253        /// Trait for equality comparisons.
254        ///
255        /// This trait allows for comparing whether two values are equal or not.
256        ///
257        /// # Examples
258        ///
259        /// ```rune
260        /// use std::cmp::Eq;
261        ///
262        /// assert!(1.eq(1));
263        /// assert!(!1.eq(2));
264        /// ```
265    })?;
266
267    let mut t = m.define_trait(["PartialOrd"])?;
268
269    t.docs(docstring! {
270        /// Trait for types that form a [partial
271        /// order](https://en.wikipedia.org/wiki/Partial_order).
272        ///
273        /// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called
274        /// using the `<`, `<=`, `>`, and `>=` operators, respectively.
275        ///
276        /// The methods of this trait must be consistent with each other and
277        /// with those of [`PartialEq`]. The following conditions must hold:
278        ///
279        /// 1. `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
280        /// 2. `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
281        /// 3. `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
282        /// 4. `a <= b` if and only if `a < b || a == b` 5. `a >= b` if and only
283        /// if `a > b || a == b`
284        /// 6. `a != b` if and only if `!(a == b)`.
285        ///
286        /// Conditions 2–5 above are ensured by the default implementation.
287        /// Condition 6 is already ensured by [`PartialEq`].
288        ///
289        /// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be
290        /// consistent with `partial_cmp` (see the documentation of that trait
291        /// for the exact requirements). It's easy to accidentally make them
292        /// disagree by deriving some of the traits and manually implementing
293        /// others.
294        ///
295        /// The comparison relations must satisfy the following conditions (for
296        /// all `a`, `b`, `c` of type `A`, `B`, `C`):
297        ///
298        /// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and
299        ///   `A: PartialOrd<C>`, then `a < b` and `b < c` implies `a < c`. The
300        ///   same must hold for both `==` and `>`. This must also work for
301        ///   longer chains, such as when `A: PartialOrd<B>`, `B:
302        ///   PartialOrd<C>`, `C: PartialOrd<D>`, and `A: PartialOrd<D>` all
303        ///   exist.
304        /// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a
305        ///   < b` if and only if `b > a`.
306        ///
307        /// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>`
308        /// (transitive) impls are not forced to exist, but these requirements
309        /// apply whenever they do exist.
310        ///
311        /// Violating these requirements is a logic error. The behavior
312        /// resulting from a logic error is not specified, but users of the
313        /// trait must ensure that such logic errors do *not* result in
314        /// undefined behavior. This means that `unsafe` code **must not** rely
315        /// on the correctness of these methods.
316        ///
317        /// ## Cross-crate considerations
318        ///
319        /// Upholding the requirements stated above can become tricky when one
320        /// crate implements `PartialOrd` for a type of another crate (i.e., to
321        /// allow comparing one of its own types with a type from the standard
322        /// library). The recommendation is to never implement this trait for a
323        /// foreign type. In other words, such a crate should do `impl
324        /// PartialOrd<ForeignType> for LocalType`, but it should *not* do `impl
325        /// PartialOrd<LocalType> for ForeignType`.
326        ///
327        /// This avoids the problem of transitive chains that criss-cross crate
328        /// boundaries: for all local types `T`, you may assume that no other
329        /// crate will add `impl`s that allow comparing `T < U`. In other words,
330        /// if other crates add `impl`s that allow building longer transitive
331        /// chains `U1 < ... < T < V1 < ...`, then all the types that appear to
332        /// the right of `T` must be types that the crate defining `T` already
333        /// knows about. This rules out transitive chains where downstream
334        /// crates can add new `impl`s that "stitch together" comparisons of
335        /// foreign types in ways that violate transitivity.
336        ///
337        /// Not having such foreign `impl`s also avoids forward compatibility
338        /// issues where one crate adding more `PartialOrd` implementations can
339        /// cause build failures in downstream crates.
340        ///
341        /// ## Corollaries
342        ///
343        /// The following corollaries follow from the above requirements:
344        ///
345        /// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
346        /// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
347        /// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b,
348        ///   a).map(Ordering::reverse)`
349        ///
350        /// ## Strict and non-strict partial orders
351        ///
352        /// The `<` and `>` operators behave according to a *strict* partial
353        /// order. However, `<=` and `>=` do **not** behave according to a
354        /// *non-strict* partial order. That is because mathematically, a
355        /// non-strict partial order would require reflexivity, i.e. `a <= a`
356        /// would need to be true for every `a`. This isn't always the case for
357        /// types that implement `PartialOrd`, for example:
358        ///
359        /// ```
360        /// let a = f64::sqrt(-1.0);
361        /// assert_eq!(a <= a, false);
362        /// ```
363        ///
364        /// ## How can I implement `PartialOrd`?
365        ///
366        /// `PartialOrd` only requires implementation of the [`PARTIAL_CMP`]
367        /// protocol, with the others generated from default implementations.
368        ///
369        /// However it remains possible to implement the others separately for
370        /// types which do not have a total order. For example, for floating
371        /// point numbers, `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE
372        /// 754-2008 section 5.11).
373        ///
374        /// `PARTIAL_CMP` requires your type to be [`PARTIAL_EQ`].
375        ///
376        /// If your type is [`ORD`], you can implement [`PARTIAL_CMP`] by using
377        /// [`CMP`].
378        ///
379        /// You may also find it useful to use [`PARTIAL_CMP`] on your type's
380        /// fields.
381        ///
382        /// # Examples
383        ///
384        /// ```rune
385        /// let x = 0;
386        /// let y = 1;
387        ///
388        /// assert_eq!(x < y, true);
389        /// assert_eq!(x.lt(y), true);
390        /// ```
391        ///
392        /// [`partial_cmp`]: PartialOrd::partial_cmp
393        /// [`cmp`]: Ord::cmp
394    })?;
395
396    t.handler(|cx| {
397        let partial_cmp = cx.find(&Protocol::PARTIAL_CMP)?;
398        let partial_cmp = Caller::<(Value, Value), 2, Option<Ordering>>::new(partial_cmp);
399
400        cx.find_or_define(&Protocol::LT, {
401            let partial_cmp = partial_cmp.clone();
402
403            move |a: Value, b: Value| -> Result<bool, VmError> {
404                let Some(o) = partial_cmp.call((a.clone(), b.clone()))? else {
405                    return Ok(false);
406                };
407
408                Ok(matches!(o, Ordering::Less))
409            }
410        })?;
411
412        cx.find_or_define(&Protocol::LE, {
413            let partial_cmp = partial_cmp.clone();
414
415            move |a: Value, b: Value| -> Result<bool, VmError> {
416                let Some(o) = partial_cmp.call((a.clone(), b.clone()))? else {
417                    return Ok(false);
418                };
419
420                Ok(matches!(o, Ordering::Less | Ordering::Equal))
421            }
422        })?;
423
424        cx.find_or_define(&Protocol::GT, {
425            let partial_cmp = partial_cmp.clone();
426
427            move |a: Value, b: Value| -> Result<bool, VmError> {
428                let Some(o) = partial_cmp.call((a.clone(), b.clone()))? else {
429                    return Ok(false);
430                };
431
432                Ok(matches!(o, Ordering::Greater))
433            }
434        })?;
435
436        cx.find_or_define(&Protocol::GE, {
437            let partial_cmp = partial_cmp.clone();
438
439            move |a: Value, b: Value| -> Result<bool, VmError> {
440                let Some(o) = partial_cmp.call((a.clone(), b.clone()))? else {
441                    return Ok(false);
442                };
443
444                Ok(matches!(o, Ordering::Greater | Ordering::Equal))
445            }
446        })?;
447
448        Ok(())
449    })?;
450
451    t.function("partial_cmp")?
452        .argument_types::<(Value, Value)>()?
453        .return_type::<Option<Ordering>>()?
454        .docs(docstring! {
455            /// Compare two values.
456            ///
457            /// # Examples
458            ///
459            /// ```rune
460            /// use std::cmp::Ordering;
461            ///
462            /// assert_eq!(1.partial_cmp(2), Some(Ordering::Less));
463            /// assert_eq!(2.partial_cmp(2), Some(Ordering::Equal));
464            /// assert_eq!(2.partial_cmp(1), Some(Ordering::Greater));
465            /// ```
466        })?;
467
468    t.function("lt")?
469        .argument_types::<(Value, Value)>()?
470        .return_type::<bool>()?
471        .docs(docstring! {
472            /// Tests less than (for `self` and `other`) and is used by the `<` operator.
473            ///
474            /// # Examples
475            ///
476            /// ```rune
477            /// assert_eq!(1.0 < 1.0, false);
478            /// assert_eq!(1.0 < 2.0, true);
479            /// assert_eq!(2.0 < 1.0, false);
480            /// ```
481        })?;
482
483    t.function("le")?
484        .argument_types::<(Value, Value)>()?
485        .return_type::<bool>()?
486        .docs(docstring! {
487            /// Tests less than or equal to (for `self` and `other`) and is used
488            /// by the `<=` operator.
489            ///
490            /// # Examples
491            ///
492            /// ```rune
493            /// assert_eq!(1.0 <= 1.0, true);
494            /// assert_eq!(1.0 <= 2.0, true);
495            /// assert_eq!(2.0 <= 1.0, false);
496            /// ```
497        })?;
498
499    t.function("gt")?
500        .argument_types::<(Value, Value)>()?
501        .return_type::<bool>()?
502        .docs(docstring! {
503            /// Tests greater than (for `self` and `other`) and is used by the
504            /// `>` operator.
505            ///
506            /// # Examples
507            ///
508            /// ```rune
509            /// assert_eq!(1.0 > 1.0, false);
510            /// assert_eq!(1.0 > 2.0, false);
511            /// assert_eq!(2.0 > 1.0, true);
512            /// ```
513        })?;
514
515    t.function("ge")?
516        .argument_types::<(Value, Value)>()?
517        .return_type::<bool>()?
518        .docs(docstring! {
519            /// Tests greater than or equal to (for `self` and `other`) and is
520            /// used by the `>=` operator.
521            ///
522            /// # Examples
523            ///
524            /// ```rune
525            /// assert_eq!(1.0 >= 1.0, true);
526            /// assert_eq!(1.0 >= 2.0, false);
527            /// assert_eq!(2.0 >= 1.0, true);
528            /// ```
529        })?;
530
531    let mut t = m.define_trait(["Ord"])?;
532
533    t.docs(docstring! {
534        /// Trait for types that form a [total
535        /// order](https://en.wikipedia.org/wiki/Total_order).
536        ///
537        /// Implementations must be consistent with the [`PartialOrd`]
538        /// implementation, and ensure `max`, `min`, and `clamp` are consistent
539        /// with `cmp`:
540        ///
541        /// - `partial_cmp(a, b) == Some(cmp(a, b))`.
542        /// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default
543        ///   implementation).
544        /// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default
545        ///   implementation).
546        /// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
547        ///   (ensured by the default implementation).
548        ///
549        /// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
550        /// deriving some of the traits and manually implementing others.
551        ///
552        /// Violating these requirements is a logic error. The behavior
553        /// resulting from a logic error is not specified, but users of the
554        /// trait must ensure that such logic errors do *not* result in
555        /// undefined behavior. This means that `unsafe` code **must not** rely
556        /// on the correctness of these methods.
557        ///
558        /// ## Corollaries
559        ///
560        /// From the above and the requirements of `PartialOrd`, it follows that
561        /// for all `a`, `b` and `c`:
562        ///
563        /// - exactly one of `a < b`, `a == b` or `a > b` is true; and
564        /// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same
565        ///   must hold for both `==` and `>`.
566        ///
567        /// Mathematically speaking, the `<` operator defines a strict [weak
568        /// order]. In cases where `==` conforms to mathematical equality, it
569        /// also defines a strict [total order].
570        ///
571        /// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering
572        /// [total order]: https://en.wikipedia.org/wiki/Total_order
573        ///
574        /// ## Lexicographical comparison
575        ///
576        /// Lexicographical comparison is an operation with the following
577        /// properties:
578        ///  - Two sequences are compared element by element.
579        ///  - The first mismatching element defines which sequence is
580        ///    lexicographically less or greater than the other.
581        ///  - If one sequence is a prefix of another, the shorter sequence is
582        ///    lexicographically less than the other.
583        ///  - If two sequences have equivalent elements and are of the same
584        ///    length, then the sequences are lexicographically equal.
585        ///  - An empty sequence is lexicographically less than any non-empty
586        ///    sequence.
587        ///  - Two empty sequences are lexicographically equal.
588        ///
589        /// ## How can I implement `Ord`?
590        ///
591        /// `Ord` requires that the type also be [`PARTIAL_RD`] and [`EQ`]
592        /// (which requires [`PARTIAL_EQ`]).
593        ///
594        /// Then you must define an implementation for [`CMP`]. You may find it
595        /// useful to use [`CMP`] on your type's fields.
596    })?;
597
598    t.handler(|cx| {
599        let cmp = cx.find(&Protocol::CMP)?;
600        let cmp = Caller::<(Value, Value), 2, Ordering>::new(cmp);
601
602        cx.find_or_define(&Protocol::MIN, {
603            let cmp = cmp.clone();
604
605            move |a: Value, b: Value| -> Result<_, VmError> {
606                match cmp.call((a.clone(), b.clone()))? {
607                    Ordering::Less | Ordering::Equal => Ok(a),
608                    Ordering::Greater => Ok(b),
609                }
610            }
611        })?;
612
613        cx.find_or_define(&Protocol::MAX, {
614            let cmp = cmp.clone();
615
616            move |a: Value, b: Value| -> Result<_, VmError> {
617                match cmp.call((a.clone(), b.clone()))? {
618                    Ordering::Less | Ordering::Equal => Ok(b),
619                    Ordering::Greater => Ok(a),
620                }
621            }
622        })?;
623
624        Ok(())
625    })?;
626
627    t.function("cmp")?
628        .argument_types::<(Value, Value)>()?
629        .return_type::<Ordering>()?
630        .docs(docstring! {
631            /// Compare two values.
632            ///
633            /// # Examples
634            ///
635            /// ```rune
636            /// use std::cmp::Ordering;
637            ///
638            /// assert_eq!(1.cmp(2), Ordering::Less);
639            /// assert_eq!(2.cmp(2), Ordering::Equal);
640            /// assert_eq!(2.cmp(1), Ordering::Greater);
641            /// ```
642        })?;
643
644    t.function("min")?
645        .argument_types::<(Value, Value)>()?
646        .return_type::<Ordering>()?
647        .docs(docstring! {
648            /// Return the minimum of two values.
649            ///
650            /// # Examples
651            ///
652            /// ```rune
653            /// assert_eq!(1.min(2), 1);
654            /// assert_eq!(2.min(2), 2);
655            /// assert_eq!(2.min(1), 1);
656            /// ```
657        })?;
658
659    t.function("max")?
660        .argument_types::<(Value, Value)>()?
661        .return_type::<Ordering>()?
662        .docs(docstring! {
663            /// Return the maximum of two values.
664            ///
665            /// # Examples
666            ///
667            /// ```rune
668            /// assert_eq!(1.max(2), 2);
669            /// assert_eq!(2.max(2), 2);
670            /// assert_eq!(2.max(1), 2);
671            /// ```
672        })?;
673
674    Ok(m)
675}
676
677#[rune::function(keep, instance, protocol = IS_VARIANT)]
678#[inline]
679pub(crate) fn ordering_is_variant(this: Ordering, hash: Hash) -> bool {
680    match (this, hash) {
681        (Ordering::Less, hash_in!(crate, ::std::cmp::Ordering::Less)) => true,
682        (Ordering::Equal, hash_in!(crate, ::std::cmp::Ordering::Equal)) => true,
683        (Ordering::Greater, hash_in!(crate, ::std::cmp::Ordering::Greater)) => true,
684        _ => false,
685    }
686}
687
688/// Compares and returns the maximum of two values.
689///
690/// Returns the second argument if the comparison determines them to be equal.
691///
692/// Internally uses the [`CMP`] protocol.
693///
694/// # Examples
695///
696/// ```rune
697/// use std::cmp::max;
698///
699/// assert_eq!(max(1, 2), 2);
700/// assert_eq!(max(2, 2), 2);
701/// ```
702#[rune::function(keep)]
703fn max(v1: Value, v2: Value) -> Result<Value, VmError> {
704    Ok(match Value::cmp(&v1, &v2)? {
705        Ordering::Less | Ordering::Equal => v2,
706        Ordering::Greater => v1,
707    })
708}
709
710/// Compares and returns the minimum of two values.
711///
712/// Returns the first argument if the comparison determines them to be equal.
713///
714/// Internally uses the [`CMP`] protocol.
715///
716/// # Examples
717///
718/// ```rune
719/// use std::cmp::min;
720///
721/// assert_eq!(min(1, 2), 1);
722/// assert_eq!(min(2, 2), 2);
723/// ```
724#[rune::function(keep)]
725fn min(v1: Value, v2: Value) -> Result<Value, VmError> {
726    Ok(match Value::cmp(&v1, &v2)? {
727        Ordering::Less | Ordering::Equal => v1,
728        Ordering::Greater => v2,
729    })
730}
731
732/// Perform a partial ordering equality test.
733///
734/// # Examples
735///
736/// ```rune
737/// use std::cmp::Ordering;
738///
739/// assert!(Ordering::Less == Ordering::Less);
740/// assert!(Ordering::Less != Ordering::Equal);
741/// ```
742#[rune::function(keep, instance, protocol = PARTIAL_EQ)]
743fn ordering_partial_eq(this: Ordering, other: Ordering) -> bool {
744    this == other
745}
746
747/// Perform a total ordering equality test.
748///
749/// # Examples
750///
751/// ```rune
752/// use std::ops::eq;
753/// use std::cmp::Ordering;
754///
755/// assert!(eq(Ordering::Less, Ordering::Less));
756/// assert!(!eq(Ordering::Less, Ordering::Equal));
757/// ```
758#[rune::function(keep, instance, protocol = EQ)]
759fn ordering_eq(this: Ordering, other: Ordering) -> bool {
760    this == other
761}
762
763/// Debug format [`Ordering`].
764///
765/// # Examples
766///
767/// ```rune
768/// use std::cmp::Ordering;
769///
770/// assert_eq!(format!("{:?}", Ordering::Less), "Less");
771/// ```
772#[rune::function(instance, protocol = DEBUG_FMT)]
773fn ordering_debug_fmt(this: Ordering, s: &mut Formatter) -> alloc::Result<()> {
774    write!(s, "{this:?}")
775}