1use super::{from_raw_parts, memchr};
4use crate::ascii;
5use crate::cmp::{self, BytewiseEq, Ordering};
6use crate::intrinsics::compare_bytes;
7use crate::mem::SizedTypeProperties;
8use crate::num::NonZero;
9use crate::ops::ControlFlow;
10
11#[stable(feature = "rust1", since = "1.0.0")]
12#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
13impl<T, U> const PartialEq<[U]> for [T]
14where
15 T: [const] PartialEq<U>,
16{
17 #[inline]
18 #[ferrocene::prevalidated]
19 fn eq(&self, other: &[U]) -> bool {
20 let len = self.len();
21 if len == other.len() {
22 unsafe { SlicePartialEq::equal_same_length(self.as_ptr(), other.as_ptr(), len) }
25 } else {
26 false
27 }
28 }
29}
30
31#[stable(feature = "rust1", since = "1.0.0")]
32#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
33impl<T: [const] Eq> const Eq for [T] {}
34
35#[stable(feature = "rust1", since = "1.0.0")]
37impl<T: Ord> Ord for [T] {
38 fn cmp(&self, other: &[T]) -> Ordering {
39 SliceOrd::compare(self, other)
40 }
41}
42
43#[inline]
44const fn as_underlying(x: ControlFlow<bool>) -> u8 {
45 unsafe { crate::mem::transmute(x) }
52}
53
54#[stable(feature = "rust1", since = "1.0.0")]
56impl<T: PartialOrd> PartialOrd for [T] {
57 #[inline]
58 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
59 SlicePartialOrd::partial_compare(self, other)
60 }
61 #[inline]
62 fn lt(&self, other: &Self) -> bool {
63 as_underlying(self.__chaining_lt(other)) == 1
72 }
73 #[inline]
74 fn le(&self, other: &Self) -> bool {
75 as_underlying(self.__chaining_le(other)) != 0
76 }
77 #[inline]
78 fn gt(&self, other: &Self) -> bool {
79 as_underlying(self.__chaining_gt(other)) == 1
80 }
81 #[inline]
82 fn ge(&self, other: &Self) -> bool {
83 as_underlying(self.__chaining_ge(other)) != 0
84 }
85 #[inline]
86 fn __chaining_lt(&self, other: &Self) -> ControlFlow<bool> {
87 SliceChain::chaining_lt(self, other)
88 }
89 #[inline]
90 fn __chaining_le(&self, other: &Self) -> ControlFlow<bool> {
91 SliceChain::chaining_le(self, other)
92 }
93 #[inline]
94 fn __chaining_gt(&self, other: &Self) -> ControlFlow<bool> {
95 SliceChain::chaining_gt(self, other)
96 }
97 #[inline]
98 fn __chaining_ge(&self, other: &Self) -> ControlFlow<bool> {
99 SliceChain::chaining_ge(self, other)
100 }
101}
102
103#[doc(hidden)]
104#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
106const trait SlicePartialEq<B> {
107 unsafe fn equal_same_length(lhs: *const Self, rhs: *const B, len: usize) -> bool;
110}
111
112#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
114impl<A, B> const SlicePartialEq<B> for A
115where
116 A: [const] PartialEq<B>,
117{
118 #[rustc_no_mir_inline]
123 #[ferrocene::prevalidated]
124 default unsafe fn equal_same_length(lhs: *const Self, rhs: *const B, len: usize) -> bool {
125 let mut idx = 0;
130 while idx < len {
131 if unsafe { *lhs.add(idx) != *rhs.add(idx) } {
133 return false;
134 }
135 idx += 1;
136 }
137
138 true
139 }
140}
141
142#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
145impl<A, B> const SlicePartialEq<B> for A
146where
147 A: [const] BytewiseEq<B>,
148{
149 #[inline]
150 #[ferrocene::prevalidated]
151 unsafe fn equal_same_length(lhs: *const Self, rhs: *const B, len: usize) -> bool {
152 unsafe {
156 let size = crate::intrinsics::unchecked_mul(len, Self::SIZE);
157 compare_bytes(lhs as _, rhs as _, size) == 0
158 }
159 }
160}
161
162#[doc(hidden)]
163#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
164const trait SlicePartialOrd: Sized {
166 fn partial_compare(left: &[Self], right: &[Self]) -> Option<Ordering>;
167}
168
169#[doc(hidden)]
170#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
171const trait SliceChain: Sized {
173 fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
174 fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
175 fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
176 fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
177}
178
179type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
180
181impl<A: PartialOrd> SlicePartialOrd for A {
182 default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
183 let elem_chain = |a, b| match PartialOrd::partial_cmp(a, b) {
184 Some(Ordering::Equal) => ControlFlow::Continue(()),
185 non_eq => ControlFlow::Break(non_eq),
186 };
187 let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b));
188 let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
189 b
190 }
191}
192
193impl<A: PartialOrd> SliceChain for A {
194 default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
195 chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
196 }
197 default fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
198 chaining_impl(left, right, PartialOrd::__chaining_le, usize::__chaining_le)
199 }
200 default fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
201 chaining_impl(left, right, PartialOrd::__chaining_gt, usize::__chaining_gt)
202 }
203 default fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
204 chaining_impl(left, right, PartialOrd::__chaining_ge, usize::__chaining_ge)
205 }
206}
207
208#[inline]
209fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
210 left: &'l [A],
211 right: &'r [A],
212 elem_chain: impl Fn(&'l A, &'r A) -> ControlFlow<B>,
213 len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
214) -> ControlFlow<B, C> {
215 let l = cmp::min(left.len(), right.len());
216
217 let lhs = &left[..l];
220 let rhs = &right[..l];
221
222 for i in 0..l {
223 elem_chain(&lhs[i], &rhs[i])?;
224 }
225
226 len_chain(&left.len(), &right.len())
227}
228
229#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
243impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A {
244 fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
245 Some(SliceOrd::compare(left, right))
246 }
247}
248
249#[rustc_specialization_trait]
250#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
251const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
252
253macro_rules! always_applicable_ord {
254 ($([$($p:tt)*] $t:ty,)*) => {
255 $(impl<$($p)*> AlwaysApplicableOrd for $t {})*
256 }
257}
258
259always_applicable_ord! {
260 [] u8, [] u16, [] u32, [] u64, [] u128, [] usize,
261 [] i8, [] i16, [] i32, [] i64, [] i128, [] isize,
262 [] bool, [] char,
263 [T: ?Sized] *const T, [T: ?Sized] *mut T,
264 [T: AlwaysApplicableOrd] &T,
265 [T: AlwaysApplicableOrd] &mut T,
266 [T: AlwaysApplicableOrd] Option<T>,
267}
268
269#[doc(hidden)]
270#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
271const trait SliceOrd: Sized {
273 fn compare(left: &[Self], right: &[Self]) -> Ordering;
274}
275
276impl<A: Ord> SliceOrd for A {
277 default fn compare(left: &[Self], right: &[Self]) -> Ordering {
278 let elem_chain = |a, b| match Ord::cmp(a, b) {
279 Ordering::Equal => ControlFlow::Continue(()),
280 non_eq => ControlFlow::Break(non_eq),
281 };
282 let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
283 let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
284 b
285 }
286}
287
288#[rustc_specialization_trait]
296const unsafe trait UnsignedBytewiseOrd: [const] Ord {}
297
298#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
299unsafe impl const UnsignedBytewiseOrd for bool {}
300#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
301unsafe impl const UnsignedBytewiseOrd for u8 {}
302#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
303unsafe impl const UnsignedBytewiseOrd for NonZero<u8> {}
304#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
305unsafe impl const UnsignedBytewiseOrd for Option<NonZero<u8>> {}
306#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
307unsafe impl const UnsignedBytewiseOrd for ascii::Char {}
308
309#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
312impl<A: [const] Ord + [const] UnsignedBytewiseOrd> const SliceOrd for A {
313 #[inline]
314 fn compare(left: &[Self], right: &[Self]) -> Ordering {
315 let diff = left.len() as isize - right.len() as isize;
318 let len = if left.len() < right.len() { left.len() } else { right.len() };
321 let left = left.as_ptr().cast();
322 let right = right.as_ptr().cast();
323 let mut order = unsafe { compare_bytes(left, right, len) as isize };
329 if order == 0 {
330 order = diff;
331 }
332 order.cmp(&0)
333 }
334}
335
336#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
339impl<A: [const] PartialOrd + [const] UnsignedBytewiseOrd> const SliceChain for A {
340 #[inline]
341 fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
342 match SliceOrd::compare(left, right) {
343 Ordering::Equal => ControlFlow::Continue(()),
344 ne => ControlFlow::Break(ne.is_lt()),
345 }
346 }
347 #[inline]
348 fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
349 match SliceOrd::compare(left, right) {
350 Ordering::Equal => ControlFlow::Continue(()),
351 ne => ControlFlow::Break(ne.is_le()),
352 }
353 }
354 #[inline]
355 fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
356 match SliceOrd::compare(left, right) {
357 Ordering::Equal => ControlFlow::Continue(()),
358 ne => ControlFlow::Break(ne.is_gt()),
359 }
360 }
361 #[inline]
362 fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
363 match SliceOrd::compare(left, right) {
364 Ordering::Equal => ControlFlow::Continue(()),
365 ne => ControlFlow::Break(ne.is_ge()),
366 }
367 }
368}
369
370pub(super) trait SliceContains: Sized {
371 fn slice_contains(&self, x: &[Self]) -> bool;
372}
373
374impl<T> SliceContains for T
375where
376 T: PartialEq,
377{
378 default fn slice_contains(&self, x: &[Self]) -> bool {
379 x.iter().any(|y| *y == *self)
380 }
381}
382
383impl SliceContains for u8 {
384 #[inline]
385 fn slice_contains(&self, x: &[Self]) -> bool {
386 memchr::memchr(*self, x).is_some()
387 }
388}
389
390impl SliceContains for i8 {
391 #[inline]
392 fn slice_contains(&self, x: &[Self]) -> bool {
393 let byte = *self as u8;
394 let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) };
399 memchr::memchr(byte, bytes).is_some()
400 }
401}
402
403macro_rules! impl_slice_contains {
404 ($($t:ty),*) => {
405 $(
406 impl SliceContains for $t {
407 #[inline]
408 fn slice_contains(&self, arr: &[$t]) -> bool {
409 const LANE_COUNT: usize = 4 * (128 / (size_of::<$t>() * 8));
412 let mut chunks = arr.chunks_exact(LANE_COUNT);
414 for chunk in &mut chunks {
415 if chunk.iter().fold(false, |acc, x| acc | (*x == *self)) {
416 return true;
417 }
418 }
419 return chunks.remainder().iter().any(|x| *x == *self);
421 }
422 }
423 )*
424 };
425}
426
427impl_slice_contains!(u16, u32, u64, i16, i32, i64, f32, f64, usize, isize, char);