Skip to content

Commit f0ed6cf

Browse files
authored
Fix ordering in the least bad way possible maybe (fixes #38) (#39)
1 parent b12add9 commit f0ed6cf

File tree

7 files changed

+147
-56
lines changed

7 files changed

+147
-56
lines changed

fixed-map-derive/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ toks! {
6161
hash_t = [::core::hash::Hash],
6262
hasher_t = [::core::hash::Hasher],
6363
into_iterator_t = [::core::iter::IntoIterator],
64+
iterator_cmp = [crate::macro_support::__storage_iterator_cmp],
6465
iterator_flat_map = [::core::iter::FlatMap],
6566
iterator_flatten = [::core::iter::Flatten],
67+
iterator_partial_cmp = [crate::macro_support::__storage_iterator_partial_cmp],
6668
iterator_t = [::core::iter::Iterator],
6769
key_t = [crate::key::Key],
6870
mem = [::core::mem],

fixed-map-derive/src/unit_variants.rs

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result<TokenStream, ()>
1919
let hash = cx.toks.hash_t();
2020
let hasher = cx.toks.hasher_t();
2121
let into_iterator_t = cx.toks.into_iterator_t();
22+
let iterator_cmp = cx.toks.iterator_cmp();
2223
let iterator_flat_map = cx.toks.iterator_flat_map();
2324
let iterator_flatten = cx.toks.iterator_flatten();
25+
let iterator_partial_cmp = cx.toks.iterator_partial_cmp();
2426
let iterator_t = cx.toks.iterator_t();
2527
let key_trait = cx.toks.key_t();
2628
let mem = cx.toks.mem();
@@ -192,53 +194,15 @@ pub(crate) fn implement(cx: &Ctxt<'_>, en: &DataEnum) -> Result<TokenStream, ()>
192194
impl<V> #partial_ord_t for Storage<V> where V: #partial_ord_t {
193195
#[inline]
194196
fn partial_cmp(&self, other: &Self) -> Option<#ordering> {
195-
#partial_ord_t::partial_cmp(&self.data, &other.data)
196-
}
197-
198-
#[inline]
199-
fn lt(&self, other: &Self) -> bool {
200-
#partial_ord_t::lt(&self.data, &other.data)
201-
}
202-
203-
#[inline]
204-
fn le(&self, other: &Self) -> bool {
205-
#partial_ord_t::le(&self.data, &other.data)
206-
}
207-
208-
#[inline]
209-
fn gt(&self, other: &Self) -> bool {
210-
#partial_ord_t::gt(&self.data, &other.data)
211-
}
212-
213-
#[inline]
214-
fn ge(&self, other: &Self) -> bool {
215-
#partial_ord_t::ge(&self.data, &other.data)
197+
#iterator_partial_cmp(&self.data, &other.data)
216198
}
217199
}
218200

219201
#[automatically_derived]
220202
impl<V> #ord_t for Storage<V> where V: #ord_t {
221203
#[inline]
222204
fn cmp(&self, other: &Self) -> #ordering {
223-
#ord_t::cmp(self, other)
224-
}
225-
226-
#[inline]
227-
fn max(self, other: Self) -> Self {
228-
Self { data: #ord_t::max(self.data, other.data) }
229-
}
230-
231-
#[inline]
232-
fn min(self, other: Self) -> Self {
233-
Self { data: #ord_t::min(self.data, other.data) }
234-
}
235-
236-
#[inline]
237-
fn clamp(self, min: Self, max: Self) -> Self
238-
where
239-
Self: #partial_ord_t<Self>
240-
{
241-
Self { data: #ord_t::clamp(self.data, min.data, max.data) }
205+
#iterator_cmp(&self.data, &other.data)
242206
}
243207
}
244208

src/key.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,73 @@ use crate::storage::{BooleanStorage, OptionStorage, SingletonStorage, Storage};
5252
/// Second,
5353
/// }
5454
/// ```
55+
///
56+
/// ## Ordering
57+
///
58+
/// Keys provide their own ordering semantics instead of relying on the
59+
/// [`PartialOrd`] and [`Ord`] traits.
60+
///
61+
/// Therefore keys when stored in a collection such as [`Map`] and [`Set`] are
62+
/// always ordered in *declaration order*. This allows those containers
63+
/// themselves to be ordered if the underlying key supports, it similarly to how
64+
/// [`BTreeMap`] and [`BTreeSet`] works.
65+
///
66+
/// ```
67+
/// use fixed_map::{Key, Set};
68+
///
69+
/// #[derive(Clone, Copy, Key)]
70+
/// enum Key {
71+
/// First,
72+
/// Second,
73+
/// Third,
74+
/// }
75+
///
76+
/// let mut a = Set::new();
77+
/// a.insert(Key::First);
78+
///
79+
/// let mut b = Set::new();
80+
/// b.insert(Key::Third);
81+
///
82+
/// let mut c = Set::new();
83+
/// c.insert(Key::First);
84+
/// c.insert(Key::Third);
85+
///
86+
/// assert!(a < b);
87+
/// assert!(c < b);
88+
/// assert!(a < c);
89+
/// ```
90+
///
91+
/// The same example with [`BTreeSet`]:
92+
///
93+
/// ```
94+
/// use std::collections::BTreeSet;
95+
///
96+
/// #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
97+
/// enum Key {
98+
/// First,
99+
/// Second,
100+
/// Third,
101+
/// }
102+
///
103+
/// let mut a = BTreeSet::new();
104+
/// a.insert(Key::First);
105+
///
106+
/// let mut b = BTreeSet::new();
107+
/// b.insert(Key::Third);
108+
///
109+
/// let mut c = BTreeSet::new();
110+
/// c.insert(Key::First);
111+
/// c.insert(Key::Third);
112+
///
113+
/// assert!(a < b);
114+
/// assert!(c < b);
115+
/// assert!(a < c);
116+
/// ```
117+
///
118+
/// [`BTreeMap`]: std::collections::BTreeMap
119+
/// [`BTreeSet`]: std::collections::BTreeSet
120+
/// [`Map`]: crate::Map
121+
/// [`Set`]: crate::Set
55122
pub trait Key: Copy {
56123
/// The `Storage` implementation to use for the key implementing this trait.
57124
type Storage<V>: Storage<Self, V>;

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,6 @@ pub mod storage;
347347
#[doc(hidden)]
348348
#[cfg(feature = "entry")]
349349
pub mod option_bucket;
350+
351+
#[doc(hidden)]
352+
pub mod macro_support;

src/macro_support.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! ## PRIVATE API
2+
//!
3+
//! This API is private, for use only in the `derive(Key)` macro. Usage for
4+
//! other purposes is not supported, and this API will not abide by semver
5+
//! stability guarantees.
6+
7+
use core::cmp::Ordering;
8+
9+
#[inline]
10+
fn flatten<T>(value: (usize, &Option<T>)) -> Option<(usize, &T)> {
11+
match value {
12+
(index, Some(value)) => Some((index, value)),
13+
_ => None,
14+
}
15+
}
16+
17+
/// `partial_cmp` implementation over iterators which ensures that storage
18+
/// ordering between `None` and `Some` is handled in a reasonable manner.
19+
#[allow(clippy::missing_inline_in_public_items)]
20+
pub fn __storage_iterator_partial_cmp<'a, A, B, T: 'a>(a: A, b: B) -> Option<Ordering>
21+
where
22+
A: IntoIterator<Item = &'a Option<T>>,
23+
B: IntoIterator<Item = &'a Option<T>>,
24+
T: PartialOrd<T>,
25+
{
26+
let a = a.into_iter().enumerate().filter_map(flatten);
27+
let b = b.into_iter().enumerate().filter_map(flatten);
28+
a.partial_cmp(b)
29+
}
30+
31+
/// `cmp` implementation over iterators which ensures that storage ordering
32+
/// between `None` and `Some` is handled in a reasonable manner.
33+
#[allow(clippy::missing_inline_in_public_items)]
34+
pub fn __storage_iterator_cmp<'a, A, B, T: 'a>(a: A, b: B) -> Ordering
35+
where
36+
A: IntoIterator<Item = &'a Option<T>>,
37+
B: IntoIterator<Item = &'a Option<T>>,
38+
T: Ord,
39+
{
40+
let a = a.into_iter().enumerate().filter_map(flatten);
41+
let b = b.into_iter().enumerate().filter_map(flatten);
42+
a.cmp(b)
43+
}

src/map.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,8 @@ where
10881088

10891089
/// [`PartialOrd`] implementation for a [`Map`].
10901090
///
1091+
/// For more details on ordering, see the [`Key`] documentation.
1092+
///
10911093
/// # Examples
10921094
///
10931095
/// ```
@@ -1097,18 +1099,20 @@ where
10971099
/// enum Key {
10981100
/// First,
10991101
/// Second,
1102+
/// Third,
11001103
/// }
11011104
///
11021105
/// let mut a = Map::new();
11031106
/// a.insert(Key::First, 1);
11041107
///
11051108
/// let mut b = Map::new();
1106-
/// b.insert(Key::Second, 1);
1109+
/// b.insert(Key::Third, 1);
11071110
///
1108-
/// assert!(a > b);
1109-
/// assert!(a >= b);
1110-
/// assert!(!(a < b));
1111-
/// assert!(!(a <= b));
1111+
/// assert!(a < b);
1112+
///
1113+
/// let mut empty = Map::new();
1114+
/// assert!(empty < a);
1115+
/// assert!(empty < b);
11121116
/// ```
11131117
///
11141118
/// Using a composite key:
@@ -1129,7 +1133,7 @@ where
11291133
/// b.insert(Key::Second, 1);
11301134
///
11311135
/// // TODO: support this
1132-
/// // assert!(a > b);
1136+
/// // assert!(a < b);
11331137
/// ```
11341138
impl<K, V> PartialOrd for Map<K, V>
11351139
where
@@ -1164,6 +1168,8 @@ where
11641168

11651169
/// [`Ord`] implementation for a [`Map`].
11661170
///
1171+
/// For more details on ordering, see the [`Key`] documentation.
1172+
///
11671173
/// # Examples
11681174
///
11691175
/// ```
@@ -1181,10 +1187,10 @@ where
11811187
/// let mut b = Map::new();
11821188
/// b.insert(Key::Second, 1);
11831189
///
1184-
/// let mut list = vec![a, b];
1190+
/// let mut list = vec![b, a];
11851191
/// list.sort();
11861192
///
1187-
/// assert_eq!(list, [b, a]);
1193+
/// assert_eq!(list, [a, b]);
11881194
/// ```
11891195
///
11901196
/// Using a composite key:

src/set.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@ where
645645

646646
/// [`PartialOrd`] implementation for a [`Set`].
647647
///
648+
/// For more details on ordering, see the [`Key`] documentation.
649+
///
648650
/// # Examples
649651
///
650652
/// ```
@@ -654,18 +656,20 @@ where
654656
/// enum Key {
655657
/// First,
656658
/// Second,
659+
/// Third,
657660
/// }
658661
///
659662
/// let mut a = Set::new();
660663
/// a.insert(Key::First);
661664
///
662665
/// let mut b = Set::new();
663-
/// b.insert(Key::Second);
666+
/// b.insert(Key::Third);
664667
///
665-
/// assert!(a > b);
666-
/// assert!(a >= b);
667-
/// assert!(!(a < b));
668-
/// assert!(!(a <= b));
668+
/// assert!(a < b);
669+
///
670+
/// let mut empty = Set::new();
671+
/// assert!(empty < a);
672+
/// assert!(empty < b);
669673
/// ```
670674
///
671675
/// Using a composite key:
@@ -686,7 +690,7 @@ where
686690
/// b.insert(Key::Second);
687691
///
688692
/// // TODO: support this
689-
/// // assert!(a > b);
693+
/// // assert!(a < b);
690694
/// ```
691695
impl<K> PartialOrd for Set<K>
692696
where
@@ -721,6 +725,8 @@ where
721725

722726
/// [`Ord`] implementation for a [`Set`].
723727
///
728+
/// For more details on ordering, see the [`Key`] documentation.
729+
///
724730
/// # Examples
725731
///
726732
/// ```
@@ -738,10 +744,10 @@ where
738744
/// let mut b = Set::new();
739745
/// b.insert(Key::Second);
740746
///
741-
/// let mut list = vec![a, b];
747+
/// let mut list = vec![b, a];
742748
/// list.sort();
743749
///
744-
/// assert_eq!(list, [b, a]);
750+
/// assert_eq!(list, [a, b]);
745751
/// ```
746752
///
747753
/// Using a composite key:

0 commit comments

Comments
 (0)