1#[cfg(not(feature = "ferrocene_certified"))]
4use super::{from_raw_parts, memchr};
5#[cfg(not(feature = "ferrocene_certified"))]
6use crate::ascii;
7#[cfg(not(feature = "ferrocene_certified"))]
8use crate::cmp::{self, BytewiseEq, Ordering};
9#[cfg(not(feature = "ferrocene_certified"))]
10use crate::intrinsics::compare_bytes;
11#[cfg(not(feature = "ferrocene_certified"))]
12use crate::num::NonZero;
13#[cfg(not(feature = "ferrocene_certified"))]
14use crate::ops::ControlFlow;
15
16#[stable(feature = "rust1", since = "1.0.0")]
17#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
18impl<T, U> const PartialEq<[U]> for [T]
19where
20 T: [const] PartialEq<U>,
21{
22 fn eq(&self, other: &[U]) -> bool {
23 SlicePartialEq::equal(self, other)
24 }
25
26 fn ne(&self, other: &[U]) -> bool {
27 SlicePartialEq::not_equal(self, other)
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")]
37#[cfg(not(feature = "ferrocene_certified"))]
38impl<T: Ord> Ord for [T] {
39 fn cmp(&self, other: &[T]) -> Ordering {
40 SliceOrd::compare(self, other)
41 }
42}
43
44#[inline]
45#[cfg(not(feature = "ferrocene_certified"))]
46const fn as_underlying(x: ControlFlow<bool>) -> u8 {
47 unsafe { crate::mem::transmute(x) }
54}
55
56#[stable(feature = "rust1", since = "1.0.0")]
58#[cfg(not(feature = "ferrocene_certified"))]
59impl<T: PartialOrd> PartialOrd for [T] {
60 #[inline]
61 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
62 SlicePartialOrd::partial_compare(self, other)
63 }
64 #[inline]
65 fn lt(&self, other: &Self) -> bool {
66 as_underlying(self.__chaining_lt(other)) == 1
75 }
76 #[inline]
77 fn le(&self, other: &Self) -> bool {
78 as_underlying(self.__chaining_le(other)) != 0
79 }
80 #[inline]
81 fn gt(&self, other: &Self) -> bool {
82 as_underlying(self.__chaining_gt(other)) == 1
83 }
84 #[inline]
85 fn ge(&self, other: &Self) -> bool {
86 as_underlying(self.__chaining_ge(other)) != 0
87 }
88 #[inline]
89 fn __chaining_lt(&self, other: &Self) -> ControlFlow<bool> {
90 SliceChain::chaining_lt(self, other)
91 }
92 #[inline]
93 fn __chaining_le(&self, other: &Self) -> ControlFlow<bool> {
94 SliceChain::chaining_le(self, other)
95 }
96 #[inline]
97 fn __chaining_gt(&self, other: &Self) -> ControlFlow<bool> {
98 SliceChain::chaining_gt(self, other)
99 }
100 #[inline]
101 fn __chaining_ge(&self, other: &Self) -> ControlFlow<bool> {
102 SliceChain::chaining_ge(self, other)
103 }
104}
105
106#[doc(hidden)]
107#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
109const trait SlicePartialEq<B> {
110 fn equal(&self, other: &[B]) -> bool;
111
112 fn not_equal(&self, other: &[B]) -> bool {
113 !self.equal(other)
114 }
115}
116
117#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
119impl<A, B> const SlicePartialEq<B> for [A]
120where
121 A: [const] PartialEq<B>,
122{
123 default fn equal(&self, other: &[B]) -> bool {
124 if self.len() != other.len() {
125 return false;
126 }
127
128 let mut idx = 0;
133 while idx < self.len() {
134 if self[idx] != other[idx] {
136 return false;
137 }
138 idx += 1;
139 }
140
141 true
142 }
143}
144
145#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
148#[cfg(not(feature = "ferrocene_certified"))]
149impl<A, B> const SlicePartialEq<B> for [A]
150where
151 A: [const] BytewiseEq<B>,
152{
153 fn equal(&self, other: &[B]) -> bool {
154 if self.len() != other.len() {
155 return false;
156 }
157
158 unsafe {
161 let size = size_of_val(self);
162 compare_bytes(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0
163 }
164 }
165}
166
167#[doc(hidden)]
168#[const_trait]
169#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
170#[cfg(not(feature = "ferrocene_certified"))]
172trait SlicePartialOrd: Sized {
173 fn partial_compare(left: &[Self], right: &[Self]) -> Option<Ordering>;
174}
175
176#[doc(hidden)]
177#[const_trait]
178#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
179#[cfg(not(feature = "ferrocene_certified"))]
181trait SliceChain: Sized {
182 fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
183 fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
184 fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
185 fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
186}
187
188#[cfg(not(feature = "ferrocene_certified"))]
189type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
190
191#[cfg(not(feature = "ferrocene_certified"))]
192impl<A: PartialOrd> SlicePartialOrd for A {
193 default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
194 let elem_chain = |a, b| match PartialOrd::partial_cmp(a, b) {
195 Some(Ordering::Equal) => ControlFlow::Continue(()),
196 non_eq => ControlFlow::Break(non_eq),
197 };
198 let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b));
199 let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
200 b
201 }
202}
203
204#[cfg(not(feature = "ferrocene_certified"))]
205impl<A: PartialOrd> SliceChain for A {
206 default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
207 chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
208 }
209 default fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
210 chaining_impl(left, right, PartialOrd::__chaining_le, usize::__chaining_le)
211 }
212 default fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
213 chaining_impl(left, right, PartialOrd::__chaining_gt, usize::__chaining_gt)
214 }
215 default fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
216 chaining_impl(left, right, PartialOrd::__chaining_ge, usize::__chaining_ge)
217 }
218}
219
220#[inline]
221#[cfg(not(feature = "ferrocene_certified"))]
222fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
223 left: &'l [A],
224 right: &'r [A],
225 elem_chain: impl Fn(&'l A, &'r A) -> ControlFlow<B>,
226 len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
227) -> ControlFlow<B, C> {
228 let l = cmp::min(left.len(), right.len());
229
230 let lhs = &left[..l];
233 let rhs = &right[..l];
234
235 for i in 0..l {
236 elem_chain(&lhs[i], &rhs[i])?;
237 }
238
239 len_chain(&left.len(), &right.len())
240}
241
242#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
256#[cfg(not(feature = "ferrocene_certified"))]
257impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A {
258 fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
259 Some(SliceOrd::compare(left, right))
260 }
261}
262
263#[rustc_specialization_trait]
264#[const_trait]
265#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
266#[cfg(not(feature = "ferrocene_certified"))]
267trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
268
269#[cfg(not(feature = "ferrocene_certified"))]
270macro_rules! always_applicable_ord {
271 ($([$($p:tt)*] $t:ty,)*) => {
272 $(impl<$($p)*> AlwaysApplicableOrd for $t {})*
273 }
274}
275
276#[cfg(not(feature = "ferrocene_certified"))]
277always_applicable_ord! {
278 [] u8, [] u16, [] u32, [] u64, [] u128, [] usize,
279 [] i8, [] i16, [] i32, [] i64, [] i128, [] isize,
280 [] bool, [] char,
281 [T: ?Sized] *const T, [T: ?Sized] *mut T,
282 [T: AlwaysApplicableOrd] &T,
283 [T: AlwaysApplicableOrd] &mut T,
284 [T: AlwaysApplicableOrd] Option<T>,
285}
286
287#[doc(hidden)]
288#[const_trait]
289#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
290#[cfg(not(feature = "ferrocene_certified"))]
292trait SliceOrd: Sized {
293 fn compare(left: &[Self], right: &[Self]) -> Ordering;
294}
295
296#[cfg(not(feature = "ferrocene_certified"))]
297impl<A: Ord> SliceOrd for A {
298 default fn compare(left: &[Self], right: &[Self]) -> Ordering {
299 let elem_chain = |a, b| match Ord::cmp(a, b) {
300 Ordering::Equal => ControlFlow::Continue(()),
301 non_eq => ControlFlow::Break(non_eq),
302 };
303 let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
304 let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
305 b
306 }
307}
308
309#[rustc_specialization_trait]
317#[const_trait]
318#[cfg(not(feature = "ferrocene_certified"))]
319unsafe trait UnsignedBytewiseOrd: [const] Ord {}
320
321#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
322#[cfg(not(feature = "ferrocene_certified"))]
323unsafe impl const UnsignedBytewiseOrd for bool {}
324#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
325#[cfg(not(feature = "ferrocene_certified"))]
326unsafe impl const UnsignedBytewiseOrd for u8 {}
327#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
328#[cfg(not(feature = "ferrocene_certified"))]
329unsafe impl const UnsignedBytewiseOrd for NonZero<u8> {}
330#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
331#[cfg(not(feature = "ferrocene_certified"))]
332unsafe impl const UnsignedBytewiseOrd for Option<NonZero<u8>> {}
333#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
334#[cfg(not(feature = "ferrocene_certified"))]
335unsafe impl const UnsignedBytewiseOrd for ascii::Char {}
336
337#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
340#[cfg(not(feature = "ferrocene_certified"))]
341impl<A: [const] Ord + [const] UnsignedBytewiseOrd> const SliceOrd for A {
342 #[inline]
343 fn compare(left: &[Self], right: &[Self]) -> Ordering {
344 let diff = left.len() as isize - right.len() as isize;
347 let len = if left.len() < right.len() { left.len() } else { right.len() };
350 let left = left.as_ptr().cast();
351 let right = right.as_ptr().cast();
352 let mut order = unsafe { compare_bytes(left, right, len) as isize };
358 if order == 0 {
359 order = diff;
360 }
361 order.cmp(&0)
362 }
363}
364
365#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
368#[cfg(not(feature = "ferrocene_certified"))]
369impl<A: [const] PartialOrd + [const] UnsignedBytewiseOrd> const SliceChain for A {
370 #[inline]
371 fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
372 match SliceOrd::compare(left, right) {
373 Ordering::Equal => ControlFlow::Continue(()),
374 ne => ControlFlow::Break(ne.is_lt()),
375 }
376 }
377 #[inline]
378 fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
379 match SliceOrd::compare(left, right) {
380 Ordering::Equal => ControlFlow::Continue(()),
381 ne => ControlFlow::Break(ne.is_le()),
382 }
383 }
384 #[inline]
385 fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
386 match SliceOrd::compare(left, right) {
387 Ordering::Equal => ControlFlow::Continue(()),
388 ne => ControlFlow::Break(ne.is_gt()),
389 }
390 }
391 #[inline]
392 fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
393 match SliceOrd::compare(left, right) {
394 Ordering::Equal => ControlFlow::Continue(()),
395 ne => ControlFlow::Break(ne.is_ge()),
396 }
397 }
398}
399
400#[cfg(not(feature = "ferrocene_certified"))]
401pub(super) trait SliceContains: Sized {
402 fn slice_contains(&self, x: &[Self]) -> bool;
403}
404
405#[cfg(not(feature = "ferrocene_certified"))]
406impl<T> SliceContains for T
407where
408 T: PartialEq,
409{
410 default fn slice_contains(&self, x: &[Self]) -> bool {
411 x.iter().any(|y| *y == *self)
412 }
413}
414
415#[cfg(not(feature = "ferrocene_certified"))]
416impl SliceContains for u8 {
417 #[inline]
418 fn slice_contains(&self, x: &[Self]) -> bool {
419 memchr::memchr(*self, x).is_some()
420 }
421}
422
423#[cfg(not(feature = "ferrocene_certified"))]
424impl SliceContains for i8 {
425 #[inline]
426 fn slice_contains(&self, x: &[Self]) -> bool {
427 let byte = *self as u8;
428 let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) };
433 memchr::memchr(byte, bytes).is_some()
434 }
435}
436
437#[cfg(not(feature = "ferrocene_certified"))]
438macro_rules! impl_slice_contains {
439 ($($t:ty),*) => {
440 $(
441 impl SliceContains for $t {
442 #[inline]
443 fn slice_contains(&self, arr: &[$t]) -> bool {
444 const LANE_COUNT: usize = 4 * (128 / (size_of::<$t>() * 8));
447 let mut chunks = arr.chunks_exact(LANE_COUNT);
449 for chunk in &mut chunks {
450 if chunk.iter().fold(false, |acc, x| acc | (*x == *self)) {
451 return true;
452 }
453 }
454 return chunks.remainder().iter().any(|x| *x == *self);
456 }
457 }
458 )*
459 };
460}
461
462#[cfg(not(feature = "ferrocene_certified"))]
463impl_slice_contains!(u16, u32, u64, i16, i32, i64, f32, f64, usize, isize, char);