copse/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(any(feature = "std", test)), no_std)]
3#![cfg_attr(feature = "allocator_api", feature(allocator_api))]
4#![cfg_attr(feature = "core_intrinsics", feature(core_intrinsics))]
5#![cfg_attr(feature = "dropck_eyepatch", feature(dropck_eyepatch))]
6#![cfg_attr(feature = "error_in_core", feature(error_in_core))]
7#![cfg_attr(feature = "exact_size_is_empty", feature(exact_size_is_empty))]
8#![cfg_attr(feature = "exclusive_range_pattern", feature(exclusive_range_pattern))]
9#![cfg_attr(feature = "extend_one", feature(extend_one))]
10#![cfg_attr(feature = "hasher_prefixfree_extras", feature(hasher_prefixfree_extras))]
11#![cfg_attr(feature = "inline_const", feature(inline_const))]
12#![cfg_attr(feature = "inplace_iteration", feature(inplace_iteration))]
13#![cfg_attr(feature = "is_sorted", feature(is_sorted))]
14#![cfg_attr(feature = "maybe_uninit_slice", feature(maybe_uninit_slice))]
15#![cfg_attr(feature = "new_uninit", feature(new_uninit))]
16#![cfg_attr(feature = "rustc_attrs", feature(rustc_attrs))]
17#![cfg_attr(feature = "slice_ptr_get", feature(slice_ptr_get))]
18#![cfg_attr(feature = "specialization", feature(specialization))]
19#![cfg_attr(feature = "trusted_len", feature(trusted_len))]
20// documentation controls
21#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))]
22#![cfg_attr(docsrs, doc(cfg_hide(no_global_oom_handling)))]
23#![deny(missing_docs)]
24// linting controls
25#![cfg_attr(feature = "specialization", allow(incomplete_features))]
26
27#[macro_use]
28extern crate alloc;
29
30use core::cmp::Ordering;
31
32#[macro_use]
33mod polyfill;
34pub mod default;
35
36// port of stdlib implementation
37mod liballoc;
38pub use liballoc::collections::{binary_heap, btree_map, btree_set};
39
40#[cfg(not(no_global_oom_handling))]
41#[doc(no_inline)]
42pub use binary_heap::BinaryHeap;
43
44#[cfg(not(no_global_oom_handling))]
45#[doc(no_inline)]
46pub use btree_map::BTreeMap;
47
48#[cfg(not(no_global_oom_handling))]
49#[doc(no_inline)]
50pub use btree_set::BTreeSet;
51
52/// A strict [total order] over the associated type [`OrderedType`].
53///
54/// This means that for all `a`, `b` and `c`:
55///
56/// 1. exactly one of `a < b`, `a == b` or `a > b` is true;
57/// 2. `<` is the dual of `>`: that is, `a < b` if and only if `b > a`; and
58/// 3. `<` is transitive: `a < b` and `b < c` implies `a < c`.
59///    The same must hold for both `==` and `>`.
60///
61/// [total order]: https://en.wikipedia.org/wiki/Total_order
62/// [`OrderedType`]: TotalOrder::OrderedType
63pub trait TotalOrder {
64    /// The type over which this total order is defined.
65    type OrderedType: ?Sized;
66
67    /// This method returns the [`Ordering`] between `this` and `that` under
68    /// this total order.
69    ///
70    /// By convention, `self.cmp(&this, &that)` returns the ordering matching
71    /// the expression `this <operator> that` if true.
72    fn cmp(&self, this: &Self::OrderedType, that: &Self::OrderedType) -> Ordering;
73
74    /// This method returns the [`Ordering`] between `this` and `that` under
75    /// this total order.
76    ///
77    /// By convention, `self.cmp(&this, &that)` returns the ordering matching
78    /// the expression `this <operator> that` if true.
79    #[doc(hidden)]
80    #[inline]
81    fn cmp_any<A, B>(&self, this: &A, that: &B) -> Ordering
82    where
83        A: ?Sized + SortableBy<Self>,
84        B: ?Sized + SortableBy<Self>,
85    {
86        self.cmp(this.sort_key(), that.sort_key())
87    }
88
89    /// Tests whether `this == that` under this total order.  It is a logic
90    /// error for this method to be inconsistent with [`TotalOrder::cmp`],
91    /// and therefore the default implementation should rarely be overriden.
92    #[doc(hidden)]
93    #[inline]
94    fn eq<A, B>(&self, this: &A, that: &B) -> bool
95    where
96        A: ?Sized + SortableBy<Self>,
97        B: ?Sized + SortableBy<Self>,
98    {
99        self.cmp_any(this, that).is_eq()
100    }
101    /// Tests whether `this != that` under this total order.  It is a logic
102    /// error for this method to be inconsistent with [`TotalOrder::cmp`],
103    /// and therefore the default implementation should rarely be overriden.
104    #[doc(hidden)]
105    #[inline]
106    fn ne<A, B>(&self, this: &A, that: &B) -> bool
107    where
108        A: ?Sized + SortableBy<Self>,
109        B: ?Sized + SortableBy<Self>,
110    {
111        self.cmp_any(this, that).is_ne()
112    }
113
114    /// Tests whether `this >= that` under this total order.  It is a logic
115    /// error for this method to be inconsistent with [`TotalOrder::cmp`],
116    /// and therefore the default implementation should rarely be overriden.
117    #[doc(hidden)]
118    #[inline]
119    fn ge<A, B>(&self, this: &A, that: &B) -> bool
120    where
121        A: ?Sized + SortableBy<Self>,
122        B: ?Sized + SortableBy<Self>,
123    {
124        self.cmp_any(this, that).is_ge()
125    }
126    /// Tests whether `this > that` under this total order.  It is a logic
127    /// error for this method to be inconsistent with [`TotalOrder::cmp`],
128    /// and therefore the default implementation should rarely be overriden.
129    #[doc(hidden)]
130    #[inline]
131    fn gt<A, B>(&self, this: &A, that: &B) -> bool
132    where
133        A: ?Sized + SortableBy<Self>,
134        B: ?Sized + SortableBy<Self>,
135    {
136        self.cmp_any(this, that).is_gt()
137    }
138    /// Tests whether `this <= that` under this total order.  It is a logic
139    /// error for this method to be inconsistent with [`TotalOrder::cmp`],
140    /// and therefore the default implementation should rarely be overriden.
141    #[doc(hidden)]
142    #[inline]
143    fn le<A, B>(&self, this: &A, that: &B) -> bool
144    where
145        A: ?Sized + SortableBy<Self>,
146        B: ?Sized + SortableBy<Self>,
147    {
148        self.cmp_any(this, that).is_le()
149    }
150    /// Tests whether `this < that` under this total order.  It is a logic
151    /// error for this method to be inconsistent with [`TotalOrder::cmp`],
152    /// and therefore the default implementation should rarely be overriden.
153    #[doc(hidden)]
154    #[inline]
155    fn lt<A, B>(&self, this: &A, that: &B) -> bool
156    where
157        A: ?Sized + SortableBy<Self>,
158        B: ?Sized + SortableBy<Self>,
159    {
160        self.cmp_any(this, that).is_lt()
161    }
162}
163
164/// A type that is sortable by its [`sort_key`] under total orders of type parameter `O`.
165///
166/// **Note that if you wish to use `O::OrderedType` itself with copse's collections, you
167/// must explicitly implement `SortableBy<O>` for it even though that implementation will
168/// typically be a no-op.**  This case cannot currently be provided for you by way of a
169/// blanket implementation because that would conflict with the [blanket borrowing
170/// implementation] that is provided for the default [`OrdTotalOrder`]; implementations
171/// for `O::OrderedType` that are not no-ops are strongly discouraged, as they are prone
172/// to causing considerable confusion—for any such use-case, consider defining a distinct
173/// [`TotalOrder`] instead.
174///
175/// # Example
176/// ```rust
177/// use copse::{BTreeSet, SortableBy, TotalOrder};
178/// use std::cmp::Ordering;
179///
180/// struct MyOrdering;
181///
182/// impl TotalOrder for MyOrdering {
183///     type OrderedType = str;
184///     fn cmp(&self, this: &str, that: &str) -> Ordering { this.cmp(that) }
185/// }
186///
187/// impl SortableBy<MyOrdering> for String {
188///     fn sort_key(&self) -> &str { self.as_str() }
189/// }
190/// impl SortableBy<MyOrdering> for str {
191///     fn sort_key(&self) -> &str { self }
192/// }
193///
194/// let mut set = BTreeSet::new(MyOrdering);
195/// set.insert(String::from("a"));
196/// assert!(set.contains("a"));
197/// ```
198///
199/// [`sort_key`]: SortableBy::sort_key
200/// [blanket borrowing implementation]: #impl-SortableBy%3COrdTotalOrder%3CT%3E%3E-for-K
201/// [`OrdTotalOrder`]: default::OrdTotalOrder
202pub trait SortableBy<O: ?Sized + TotalOrder> {
203    /// Extract the sort key by which `self` is ordered under total orders of type `O`.
204    fn sort_key(&self) -> &O::OrderedType;
205}