1#[cfg(not(feature = "ferrocene_certified"))]
4use super::ParseBoolError;
5#[cfg(not(feature = "ferrocene_certified"))]
6use crate::cmp::Ordering;
7#[cfg(not(feature = "ferrocene_certified"))]
8use crate::intrinsics::unchecked_sub;
9#[cfg(not(feature = "ferrocene_certified"))]
10use crate::slice::SliceIndex;
11#[cfg(not(feature = "ferrocene_certified"))]
12use crate::ub_checks::assert_unsafe_precondition;
13#[cfg(not(feature = "ferrocene_certified"))]
14use crate::{ops, ptr, range};
15
16#[stable(feature = "rust1", since = "1.0.0")]
24#[cfg(not(feature = "ferrocene_certified"))]
25impl Ord for str {
26 #[inline]
27 fn cmp(&self, other: &str) -> Ordering {
28 self.as_bytes().cmp(other.as_bytes())
29 }
30}
31
32#[stable(feature = "rust1", since = "1.0.0")]
33#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
34#[cfg(not(feature = "ferrocene_certified"))]
35impl const PartialEq for str {
36 #[inline]
37 fn eq(&self, other: &str) -> bool {
38 self.as_bytes() == other.as_bytes()
39 }
40}
41
42#[stable(feature = "rust1", since = "1.0.0")]
43#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
44#[cfg(not(feature = "ferrocene_certified"))]
45impl const Eq for str {}
46
47#[stable(feature = "rust1", since = "1.0.0")]
55#[cfg(not(feature = "ferrocene_certified"))]
56impl PartialOrd for str {
57 #[inline]
58 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
59 Some(self.cmp(other))
60 }
61}
62
63#[stable(feature = "rust1", since = "1.0.0")]
64#[rustc_const_unstable(feature = "const_index", issue = "143775")]
65#[cfg(not(feature = "ferrocene_certified"))]
66impl<I> const ops::Index<I> for str
67where
68 I: [const] SliceIndex<str>,
69{
70 type Output = I::Output;
71
72 #[inline]
73 fn index(&self, index: I) -> &I::Output {
74 index.index(self)
75 }
76}
77
78#[stable(feature = "rust1", since = "1.0.0")]
79#[rustc_const_unstable(feature = "const_index", issue = "143775")]
80#[cfg(not(feature = "ferrocene_certified"))]
81impl<I> const ops::IndexMut<I> for str
82where
83 I: [const] SliceIndex<str>,
84{
85 #[inline]
86 fn index_mut(&mut self, index: I) -> &mut I::Output {
87 index.index_mut(self)
88 }
89}
90
91#[inline(never)]
92#[cold]
93#[track_caller]
94#[cfg(not(feature = "ferrocene_certified"))]
95const fn str_index_overflow_fail() -> ! {
96 panic!("attempted to index str up to maximum usize");
97}
98
99#[stable(feature = "str_checked_slicing", since = "1.20.0")]
112#[rustc_const_unstable(feature = "const_index", issue = "143775")]
113#[cfg(not(feature = "ferrocene_certified"))]
114unsafe impl const SliceIndex<str> for ops::RangeFull {
115 type Output = str;
116 #[inline]
117 fn get(self, slice: &str) -> Option<&Self::Output> {
118 Some(slice)
119 }
120 #[inline]
121 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
122 Some(slice)
123 }
124 #[inline]
125 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
126 slice
127 }
128 #[inline]
129 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
130 slice
131 }
132 #[inline]
133 fn index(self, slice: &str) -> &Self::Output {
134 slice
135 }
136 #[inline]
137 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
138 slice
139 }
140}
141
142#[stable(feature = "str_checked_slicing", since = "1.20.0")]
178#[rustc_const_unstable(feature = "const_index", issue = "143775")]
179#[cfg(not(feature = "ferrocene_certified"))]
180unsafe impl const SliceIndex<str> for ops::Range<usize> {
181 type Output = str;
182 #[inline]
183 fn get(self, slice: &str) -> Option<&Self::Output> {
184 if self.start <= self.end
185 && slice.is_char_boundary(self.start)
186 && slice.is_char_boundary(self.end)
187 {
188 Some(unsafe { &*self.get_unchecked(slice) })
192 } else {
193 None
194 }
195 }
196 #[inline]
197 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
198 if self.start <= self.end
199 && slice.is_char_boundary(self.start)
200 && slice.is_char_boundary(self.end)
201 {
202 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
205 } else {
206 None
207 }
208 }
209 #[inline]
210 #[track_caller]
211 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
212 let slice = slice as *const [u8];
213
214 assert_unsafe_precondition!(
215 check_library_ub,
222 "str::get_unchecked requires that the range is within the string slice",
223 (
224 start: usize = self.start,
225 end: usize = self.end,
226 len: usize = slice.len()
227 ) => end >= start && end <= len,
228 );
229
230 unsafe {
233 let new_len = unchecked_sub(self.end, self.start);
234 ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
235 }
236 }
237 #[inline]
238 #[track_caller]
239 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
240 let slice = slice as *mut [u8];
241
242 assert_unsafe_precondition!(
243 check_library_ub,
244 "str::get_unchecked_mut requires that the range is within the string slice",
245 (
246 start: usize = self.start,
247 end: usize = self.end,
248 len: usize = slice.len()
249 ) => end >= start && end <= len,
250 );
251
252 unsafe {
254 let new_len = unchecked_sub(self.end, self.start);
255 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
256 }
257 }
258 #[inline]
259 fn index(self, slice: &str) -> &Self::Output {
260 let (start, end) = (self.start, self.end);
261 match self.get(slice) {
262 Some(s) => s,
263 None => super::slice_error_fail(slice, start, end),
264 }
265 }
266 #[inline]
267 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
268 if self.start <= self.end
271 && slice.is_char_boundary(self.start)
272 && slice.is_char_boundary(self.end)
273 {
274 unsafe { &mut *self.get_unchecked_mut(slice) }
277 } else {
278 super::slice_error_fail(slice, self.start, self.end)
279 }
280 }
281}
282
283#[unstable(feature = "new_range_api", issue = "125687")]
284#[rustc_const_unstable(feature = "const_index", issue = "143775")]
285#[cfg(not(feature = "ferrocene_certified"))]
286unsafe impl const SliceIndex<str> for range::Range<usize> {
287 type Output = str;
288 #[inline]
289 fn get(self, slice: &str) -> Option<&Self::Output> {
290 if self.start <= self.end
291 && slice.is_char_boundary(self.start)
292 && slice.is_char_boundary(self.end)
293 {
294 Some(unsafe { &*self.get_unchecked(slice) })
298 } else {
299 None
300 }
301 }
302 #[inline]
303 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
304 if self.start <= self.end
305 && slice.is_char_boundary(self.start)
306 && slice.is_char_boundary(self.end)
307 {
308 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
311 } else {
312 None
313 }
314 }
315 #[inline]
316 #[track_caller]
317 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
318 let slice = slice as *const [u8];
319
320 assert_unsafe_precondition!(
321 check_library_ub,
328 "str::get_unchecked requires that the range is within the string slice",
329 (
330 start: usize = self.start,
331 end: usize = self.end,
332 len: usize = slice.len()
333 ) => end >= start && end <= len,
334 );
335
336 unsafe {
339 let new_len = unchecked_sub(self.end, self.start);
340 ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
341 }
342 }
343 #[inline]
344 #[track_caller]
345 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
346 let slice = slice as *mut [u8];
347
348 assert_unsafe_precondition!(
349 check_library_ub,
350 "str::get_unchecked_mut requires that the range is within the string slice",
351 (
352 start: usize = self.start,
353 end: usize = self.end,
354 len: usize = slice.len()
355 ) => end >= start && end <= len,
356 );
357
358 unsafe {
360 let new_len = unchecked_sub(self.end, self.start);
361 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
362 }
363 }
364 #[inline]
365 fn index(self, slice: &str) -> &Self::Output {
366 let (start, end) = (self.start, self.end);
367 match self.get(slice) {
368 Some(s) => s,
369 None => super::slice_error_fail(slice, start, end),
370 }
371 }
372 #[inline]
373 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
374 if self.start <= self.end
377 && slice.is_char_boundary(self.start)
378 && slice.is_char_boundary(self.end)
379 {
380 unsafe { &mut *self.get_unchecked_mut(slice) }
383 } else {
384 super::slice_error_fail(slice, self.start, self.end)
385 }
386 }
387}
388
389#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")]
403#[cfg(not(feature = "ferrocene_certified"))]
404unsafe impl SliceIndex<str> for (ops::Bound<usize>, ops::Bound<usize>) {
405 type Output = str;
406
407 #[inline]
408 fn get(self, slice: &str) -> Option<&str> {
409 crate::slice::index::into_range(slice.len(), self)?.get(slice)
410 }
411
412 #[inline]
413 fn get_mut(self, slice: &mut str) -> Option<&mut str> {
414 crate::slice::index::into_range(slice.len(), self)?.get_mut(slice)
415 }
416
417 #[inline]
418 unsafe fn get_unchecked(self, slice: *const str) -> *const str {
419 let len = (slice as *const [u8]).len();
420 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked(slice) }
422 }
423
424 #[inline]
425 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str {
426 let len = (slice as *mut [u8]).len();
427 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked_mut(slice) }
429 }
430
431 #[inline]
432 fn index(self, slice: &str) -> &str {
433 crate::slice::index::into_slice_range(slice.len(), self).index(slice)
434 }
435
436 #[inline]
437 fn index_mut(self, slice: &mut str) -> &mut str {
438 crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice)
439 }
440}
441
442#[stable(feature = "str_checked_slicing", since = "1.20.0")]
458#[rustc_const_unstable(feature = "const_index", issue = "143775")]
459#[cfg(not(feature = "ferrocene_certified"))]
460unsafe impl const SliceIndex<str> for ops::RangeTo<usize> {
461 type Output = str;
462 #[inline]
463 fn get(self, slice: &str) -> Option<&Self::Output> {
464 if slice.is_char_boundary(self.end) {
465 Some(unsafe { &*self.get_unchecked(slice) })
468 } else {
469 None
470 }
471 }
472 #[inline]
473 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
474 if slice.is_char_boundary(self.end) {
475 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
478 } else {
479 None
480 }
481 }
482 #[inline]
483 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
484 unsafe { (0..self.end).get_unchecked(slice) }
486 }
487 #[inline]
488 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
489 unsafe { (0..self.end).get_unchecked_mut(slice) }
491 }
492 #[inline]
493 fn index(self, slice: &str) -> &Self::Output {
494 let end = self.end;
495 match self.get(slice) {
496 Some(s) => s,
497 None => super::slice_error_fail(slice, 0, end),
498 }
499 }
500 #[inline]
501 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
502 if slice.is_char_boundary(self.end) {
503 unsafe { &mut *self.get_unchecked_mut(slice) }
506 } else {
507 super::slice_error_fail(slice, 0, self.end)
508 }
509 }
510}
511
512#[stable(feature = "str_checked_slicing", since = "1.20.0")]
528#[rustc_const_unstable(feature = "const_index", issue = "143775")]
529#[cfg(not(feature = "ferrocene_certified"))]
530unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
531 type Output = str;
532 #[inline]
533 fn get(self, slice: &str) -> Option<&Self::Output> {
534 if slice.is_char_boundary(self.start) {
535 Some(unsafe { &*self.get_unchecked(slice) })
538 } else {
539 None
540 }
541 }
542 #[inline]
543 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
544 if slice.is_char_boundary(self.start) {
545 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
548 } else {
549 None
550 }
551 }
552 #[inline]
553 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
554 let len = (slice as *const [u8]).len();
555 unsafe { (self.start..len).get_unchecked(slice) }
557 }
558 #[inline]
559 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
560 let len = (slice as *mut [u8]).len();
561 unsafe { (self.start..len).get_unchecked_mut(slice) }
563 }
564 #[inline]
565 fn index(self, slice: &str) -> &Self::Output {
566 let (start, end) = (self.start, slice.len());
567 match self.get(slice) {
568 Some(s) => s,
569 None => super::slice_error_fail(slice, start, end),
570 }
571 }
572 #[inline]
573 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
574 if slice.is_char_boundary(self.start) {
575 unsafe { &mut *self.get_unchecked_mut(slice) }
578 } else {
579 super::slice_error_fail(slice, self.start, slice.len())
580 }
581 }
582}
583
584#[unstable(feature = "new_range_api", issue = "125687")]
585#[rustc_const_unstable(feature = "const_index", issue = "143775")]
586#[cfg(not(feature = "ferrocene_certified"))]
587unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
588 type Output = str;
589 #[inline]
590 fn get(self, slice: &str) -> Option<&Self::Output> {
591 if slice.is_char_boundary(self.start) {
592 Some(unsafe { &*self.get_unchecked(slice) })
595 } else {
596 None
597 }
598 }
599 #[inline]
600 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
601 if slice.is_char_boundary(self.start) {
602 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
605 } else {
606 None
607 }
608 }
609 #[inline]
610 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
611 let len = (slice as *const [u8]).len();
612 unsafe { (self.start..len).get_unchecked(slice) }
614 }
615 #[inline]
616 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
617 let len = (slice as *mut [u8]).len();
618 unsafe { (self.start..len).get_unchecked_mut(slice) }
620 }
621 #[inline]
622 fn index(self, slice: &str) -> &Self::Output {
623 let (start, end) = (self.start, slice.len());
624 match self.get(slice) {
625 Some(s) => s,
626 None => super::slice_error_fail(slice, start, end),
627 }
628 }
629 #[inline]
630 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
631 if slice.is_char_boundary(self.start) {
632 unsafe { &mut *self.get_unchecked_mut(slice) }
635 } else {
636 super::slice_error_fail(slice, self.start, slice.len())
637 }
638 }
639}
640
641#[stable(feature = "inclusive_range", since = "1.26.0")]
658#[rustc_const_unstable(feature = "const_index", issue = "143775")]
659#[cfg(not(feature = "ferrocene_certified"))]
660unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
661 type Output = str;
662 #[inline]
663 fn get(self, slice: &str) -> Option<&Self::Output> {
664 if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
665 }
666 #[inline]
667 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
668 if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
669 }
670 #[inline]
671 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
672 unsafe { self.into_slice_range().get_unchecked(slice) }
674 }
675 #[inline]
676 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
677 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
679 }
680 #[inline]
681 fn index(self, slice: &str) -> &Self::Output {
682 if *self.end() == usize::MAX {
683 str_index_overflow_fail();
684 }
685 self.into_slice_range().index(slice)
686 }
687 #[inline]
688 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
689 if *self.end() == usize::MAX {
690 str_index_overflow_fail();
691 }
692 self.into_slice_range().index_mut(slice)
693 }
694}
695
696#[unstable(feature = "new_range_api", issue = "125687")]
697#[rustc_const_unstable(feature = "const_index", issue = "143775")]
698#[cfg(not(feature = "ferrocene_certified"))]
699unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
700 type Output = str;
701 #[inline]
702 fn get(self, slice: &str) -> Option<&Self::Output> {
703 if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) }
704 }
705 #[inline]
706 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
707 if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
708 }
709 #[inline]
710 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
711 unsafe { self.into_slice_range().get_unchecked(slice) }
713 }
714 #[inline]
715 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
716 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
718 }
719 #[inline]
720 fn index(self, slice: &str) -> &Self::Output {
721 if self.last == usize::MAX {
722 str_index_overflow_fail();
723 }
724 self.into_slice_range().index(slice)
725 }
726 #[inline]
727 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
728 if self.last == usize::MAX {
729 str_index_overflow_fail();
730 }
731 self.into_slice_range().index_mut(slice)
732 }
733}
734
735#[stable(feature = "inclusive_range", since = "1.26.0")]
750#[rustc_const_unstable(feature = "const_index", issue = "143775")]
751#[cfg(not(feature = "ferrocene_certified"))]
752unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
753 type Output = str;
754 #[inline]
755 fn get(self, slice: &str) -> Option<&Self::Output> {
756 (0..=self.end).get(slice)
757 }
758 #[inline]
759 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
760 (0..=self.end).get_mut(slice)
761 }
762 #[inline]
763 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
764 unsafe { (0..=self.end).get_unchecked(slice) }
766 }
767 #[inline]
768 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
769 unsafe { (0..=self.end).get_unchecked_mut(slice) }
771 }
772 #[inline]
773 fn index(self, slice: &str) -> &Self::Output {
774 (0..=self.end).index(slice)
775 }
776 #[inline]
777 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
778 (0..=self.end).index_mut(slice)
779 }
780}
781
782#[stable(feature = "rust1", since = "1.0.0")]
852#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
853pub const trait FromStr: Sized {
854 #[stable(feature = "rust1", since = "1.0.0")]
856 type Err;
857
858 #[stable(feature = "rust1", since = "1.0.0")]
877 #[rustc_diagnostic_item = "from_str_method"]
878 fn from_str(s: &str) -> Result<Self, Self::Err>;
879}
880
881#[stable(feature = "rust1", since = "1.0.0")]
882#[cfg(not(feature = "ferrocene_certified"))]
883impl FromStr for bool {
884 type Err = ParseBoolError;
885
886 #[inline]
909 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
910 match s {
911 "true" => Ok(true),
912 "false" => Ok(false),
913 _ => Err(ParseBoolError),
914 }
915 }
916}