|
3 | 3 | use super::{from_raw_parts, memchr};
|
4 | 4 | use crate::cmp::{self, BytewiseEq, Ordering};
|
5 | 5 | use crate::intrinsics::compare_bytes;
|
6 |
| -use crate::mem; |
| 6 | +use crate::num::NonZero; |
| 7 | +use crate::{ascii, mem}; |
7 | 8 |
|
8 | 9 | #[stable(feature = "rust1", since = "1.0.0")]
|
9 | 10 | impl<T, U> PartialEq<[U]> for [T]
|
@@ -182,19 +183,31 @@ impl<A: Ord> SliceOrd for A {
|
182 | 183 | }
|
183 | 184 | }
|
184 | 185 |
|
| 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 | + |
185 | 196 | // `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 { |
188 | 198 | #[inline]
|
189 | 199 | fn compare(left: &[Self], right: &[Self]) -> Ordering {
|
190 | 200 | // Since the length of a slice is always less than or equal to isize::MAX, this never underflows.
|
191 | 201 | let diff = left.len() as isize - right.len() as isize;
|
192 | 202 | // This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags.
|
193 | 203 | 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(); |
194 | 206 | // 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 }; |
198 | 211 | if order == 0 {
|
199 | 212 | order = diff;
|
200 | 213 | }
|
|
0 commit comments