Skip to content

Commit 2b90df3

Browse files
committed
Fix ordering in the least bad way possible maybe (fixes #38)
1 parent b12add9 commit 2b90df3

File tree

6 files changed

+116
-52
lines changed

6 files changed

+116
-52
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/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: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use core::cmp::Ordering;
2+
3+
/// `partial_cmp` implementation for a single `Option<T>` field.
4+
fn __storage_option_partial_cmp<T>(x: &Option<T>, y: &Option<T>) -> Option<Ordering>
5+
where
6+
T: PartialOrd<T>,
7+
{
8+
match (x, y) {
9+
(Some(x), Some(y)) => x.partial_cmp(&y),
10+
(None, Some(_)) => Some(Ordering::Greater),
11+
(Some(_), None) => Some(Ordering::Less),
12+
_ => Some(Ordering::Equal),
13+
}
14+
}
15+
16+
/// `cmp` implementation for a single `Option<T>` field.
17+
fn __storage_option_cmp<T>(x: &Option<T>, y: &Option<T>) -> Ordering
18+
where
19+
T: Ord,
20+
{
21+
match (x, y) {
22+
(Some(x), Some(y)) => x.cmp(&y),
23+
(None, Some(_)) => Ordering::Greater,
24+
(Some(_), None) => Ordering::Less,
25+
_ => Ordering::Equal,
26+
}
27+
}
28+
29+
/// `partial_cmp` implementation over iterators which ensures that storage
30+
/// ordering between `None` and `Some` is handled in a reasonable manner.
31+
#[doc(hidden)]
32+
pub fn __storage_iterator_partial_cmp<T>(a: &[Option<T>], b: &[Option<T>]) -> Option<Ordering>
33+
where
34+
T: PartialOrd<T>,
35+
{
36+
let mut a = a.into_iter();
37+
let mut b = b.into_iter();
38+
39+
loop {
40+
let x = match a.next() {
41+
None => {
42+
if b.next().is_none() {
43+
return Some(Ordering::Equal);
44+
} else {
45+
return Some(Ordering::Less);
46+
}
47+
}
48+
Some(x) => x,
49+
};
50+
51+
let y = match b.next() {
52+
None => return Some(Ordering::Greater),
53+
Some(y) => y,
54+
};
55+
56+
match __storage_option_partial_cmp(x, y) {
57+
Some(Ordering::Equal) => (),
58+
ordering => return ordering,
59+
}
60+
}
61+
}
62+
63+
/// `cmp` implementation over iterators which ensures that storage ordering
64+
/// between `None` and `Some` is handled in a reasonable manner.
65+
#[doc(hidden)]
66+
pub fn __storage_iterator_cmp<T>(a: &[Option<T>], b: &[Option<T>]) -> Ordering
67+
where
68+
T: Ord,
69+
{
70+
let mut a = a.into_iter();
71+
let mut b = b.into_iter();
72+
73+
loop {
74+
let x = match a.next() {
75+
None => {
76+
if b.next().is_none() {
77+
return Ordering::Equal;
78+
} else {
79+
return Ordering::Less;
80+
}
81+
}
82+
Some(x) => x,
83+
};
84+
85+
let y = match b.next() {
86+
None => return Ordering::Greater,
87+
Some(y) => y,
88+
};
89+
90+
match __storage_option_cmp(x, y) {
91+
Ordering::Equal => (),
92+
ordering => return ordering,
93+
}
94+
}
95+
}

src/map.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,10 +1105,10 @@ where
11051105
/// let mut b = Map::new();
11061106
/// b.insert(Key::Second, 1);
11071107
///
1108-
/// assert!(a > b);
1109-
/// assert!(a >= b);
1110-
/// assert!(!(a < b));
1111-
/// assert!(!(a <= b));
1108+
/// assert!(a < b);
1109+
/// assert!(a <= b);
1110+
/// assert!(!(a > b));
1111+
/// assert!(!(a >= b));
11121112
/// ```
11131113
///
11141114
/// Using a composite key:
@@ -1181,10 +1181,10 @@ where
11811181
/// let mut b = Map::new();
11821182
/// b.insert(Key::Second, 1);
11831183
///
1184-
/// let mut list = vec![a, b];
1184+
/// let mut list = vec![b, a];
11851185
/// list.sort();
11861186
///
1187-
/// assert_eq!(list, [b, a]);
1187+
/// assert_eq!(list, [a, b]);
11881188
/// ```
11891189
///
11901190
/// Using a composite key:

src/set.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,10 +662,10 @@ where
662662
/// let mut b = Set::new();
663663
/// b.insert(Key::Second);
664664
///
665-
/// assert!(a > b);
666-
/// assert!(a >= b);
667-
/// assert!(!(a < b));
668-
/// assert!(!(a <= b));
665+
/// assert!(a < b);
666+
/// assert!(a <= b);
667+
/// assert!(!(a > b));
668+
/// assert!(!(a >= b));
669669
/// ```
670670
///
671671
/// Using a composite key:
@@ -738,10 +738,10 @@ where
738738
/// let mut b = Set::new();
739739
/// b.insert(Key::Second);
740740
///
741-
/// let mut list = vec![a, b];
741+
/// let mut list = vec![b, a];
742742
/// list.sort();
743743
///
744-
/// assert_eq!(list, [b, a]);
744+
/// assert_eq!(list, [a, b]);
745745
/// ```
746746
///
747747
/// Using a composite key:

0 commit comments

Comments
 (0)