Skip to content

Commit b927541

Browse files
committed
core: use compare_bytes for more slice element types
1 parent 32894e2 commit b927541

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

Diff for: core/src/slice/cmp.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
use super::{from_raw_parts, memchr};
44
use crate::cmp::{self, BytewiseEq, Ordering};
55
use crate::intrinsics::compare_bytes;
6-
use crate::mem;
6+
use crate::num::NonZero;
7+
use crate::{ascii, mem};
78

89
#[stable(feature = "rust1", since = "1.0.0")]
910
impl<T, U> PartialEq<[U]> for [T]
@@ -182,19 +183,31 @@ impl<A: Ord> SliceOrd for A {
182183
}
183184
}
184185

186+
// The type should be treated as an unsigned byte for comparisons.
187+
#[rustc_specialization_trait]
188+
unsafe trait UnsignedByte {}
189+
190+
unsafe impl UnsignedByte for bool {}
191+
unsafe impl UnsignedByte for u8 {}
192+
unsafe impl UnsignedByte for NonZero<u8> {}
193+
unsafe impl UnsignedByte for Option<NonZero<u8>> {}
194+
unsafe impl UnsignedByte for ascii::Char {}
195+
185196
// `compare_bytes` compares a sequence of unsigned bytes lexicographically.
186-
// this matches the order we want for [u8], but no others (not even [i8]).
187-
impl SliceOrd for u8 {
197+
impl<A: Ord + UnsignedByte> SliceOrd for A {
188198
#[inline]
189199
fn compare(left: &[Self], right: &[Self]) -> Ordering {
190200
// Since the length of a slice is always less than or equal to isize::MAX, this never underflows.
191201
let diff = left.len() as isize - right.len() as isize;
192202
// This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags.
193203
let len = if left.len() < right.len() { left.len() } else { right.len() };
204+
let left = left.as_ptr().cast();
205+
let right = right.as_ptr().cast();
194206
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
195-
// We use the minimum of both lengths which guarantees that both regions are
196-
// valid for reads in that interval.
197-
let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize };
207+
// `UnsignedByte` is only implemented for types that are valid u8s. We use the
208+
// minimum of both lengths which guarantees that both regions are valid for reads
209+
// in that interval.
210+
let mut order = unsafe { compare_bytes(left, right, len) as isize };
198211
if order == 0 {
199212
order = diff;
200213
}

0 commit comments

Comments
 (0)