#ord #partial-ord #wrapper #derive-debug #require

ordered

A wrapper for adding arbitrary partial/total order to a type

5 releases

0.2.2 Dec 17, 2023
0.2.1 Dec 15, 2023
0.2.0 Dec 13, 2023
0.1.1 Dec 5, 2023
0.1.0 Dec 5, 2023

#204 in Data structures

Download history 44/week @ 2024-01-10 335/week @ 2024-01-17 432/week @ 2024-01-24 856/week @ 2024-01-31 747/week @ 2024-02-07 638/week @ 2024-02-14 1155/week @ 2024-02-21 876/week @ 2024-02-28 1055/week @ 2024-03-06 974/week @ 2024-03-13 923/week @ 2024-03-20 806/week @ 2024-03-27 750/week @ 2024-04-03 728/week @ 2024-04-10 562/week @ 2024-04-17

3,051 downloads per month
Used in bitcoin

CC0 license

10KB
91 lines

Arbitrary Ordering

Provides a wrapper for types that can technically implement PartialOrd/Ord but for semantic reasons it is nonsensical.

Examples

You might want to use a type as a key in a BTreeMap, this requires Ord even though it might be nonsensical to implement a total order for the type.

use std::cmp::Ordering;
use std::collections::BTreeMap;
use ordered::{ArbitraryOrd, Ordered};

/// A Foo type.
///
/// We do not want users to be able to write `a < b` because it is meaningless
/// to compare the two but we wish to use `Foo`, for example, as a `BTreeMap` key.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Foo {
    /// A space foo.
    Space(u32),
    /// A time foo.
    Time(u32)
}

impl ArbitraryOrd for Foo {
    fn arbitrary_cmp(&self, other: &Self) -> Ordering {
        use Foo::*;
        match (self, other) {
            (Space(_), Time(_)) => Ordering::Less,
            (Time(_), Space(_)) => Ordering::Greater,
            (Space(this), Space(that)) => this.cmp(that),
            (Time(this), Time(that)) => this.cmp(that),
        }
    }
}

let a = Foo::Space(50);
let b = Foo::Time(50);

let mut map = BTreeMap::new();

// error[E0277]: the trait bound `Foo: Ord` is not satisfied
// map.insert(a, "some interesting value");

map.insert(Ordered(a), "some interesting value");
map.insert(Ordered(b), "some other interesting value");

Perhaps you would like to derive Ord on a complex type that contains a type that does not implement Ord.

/// An example struct that contains a `Foo` but derives `PartialOrd` and `Ord`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct Adt {
    x: u32,
    p: Ordered<Foo>,
}

// Then there are various ways to get at the inner data.

let adt = Adt { x: 42, p: Foo::Space(50).into() };

println!("We can explicitly deref: {}", *adt.p);
println!("Or use deref coercion: {}", adt.p);
println!("Or we can use borrow: {}", &adt.p);

// And if all that is too complicated just use the inherent methods:

println!("Explicitly get a reference: {}", adt.p.as_inner());
println!("Or the inner type: {}", adt.p.into_inner());

Minimum Supported Rust Version (MSRV)

The crate MSRV is Rust v1.56.1

Licensing

The code in this project is licensed under the Creative Commons CC0 1.0 Universal license. We use the SPDX license list and SPDX IDs.

No runtime deps