1#[cfg(not(feature = "ferrocene_certified"))]
4use super::ParseBoolError;
5#[cfg(not(feature = "ferrocene_certified"))]
6use crate::cmp::Ordering;
7use crate::intrinsics::unchecked_sub;
8use crate::slice::SliceIndex;
9use crate::ub_checks::assert_unsafe_precondition;
10#[cfg(not(feature = "ferrocene_certified"))]
11use crate::{ops, ptr, range};
12
13#[cfg(feature = "ferrocene_certified")]
15#[rustfmt::skip]
16use crate::{ops, ptr};
17
18#[stable(feature = "rust1", since = "1.0.0")]
26#[cfg(not(feature = "ferrocene_certified"))]
27impl Ord for str {
28 #[inline]
29 fn cmp(&self, other: &str) -> Ordering {
30 self.as_bytes().cmp(other.as_bytes())
31 }
32}
33
34#[stable(feature = "rust1", since = "1.0.0")]
35#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
36#[cfg(not(feature = "ferrocene_certified"))]
37impl const PartialEq for str {
38 #[inline]
39 fn eq(&self, other: &str) -> bool {
40 self.as_bytes() == other.as_bytes()
41 }
42}
43
44#[stable(feature = "rust1", since = "1.0.0")]
45#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
46#[cfg(not(feature = "ferrocene_certified"))]
47impl const Eq for str {}
48
49#[stable(feature = "rust1", since = "1.0.0")]
57#[cfg(not(feature = "ferrocene_certified"))]
58impl PartialOrd for str {
59 #[inline]
60 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
61 Some(self.cmp(other))
62 }
63}
64
65#[stable(feature = "rust1", since = "1.0.0")]
66#[rustc_const_unstable(feature = "const_index", issue = "143775")]
67impl<I> const ops::Index<I> for str
68where
69 I: [const] SliceIndex<str>,
70{
71 type Output = I::Output;
72
73 #[inline]
74 fn index(&self, index: I) -> &I::Output {
75 index.index(self)
76 }
77}
78
79#[stable(feature = "rust1", since = "1.0.0")]
80#[rustc_const_unstable(feature = "const_index", issue = "143775")]
81#[cfg(not(feature = "ferrocene_certified"))]
82impl<I> const ops::IndexMut<I> for str
83where
84 I: [const] SliceIndex<str>,
85{
86 #[inline]
87 fn index_mut(&mut self, index: I) -> &mut I::Output {
88 index.index_mut(self)
89 }
90}
91
92#[inline(never)]
93#[cold]
94#[track_caller]
95#[cfg(not(feature = "ferrocene_certified"))]
96const fn str_index_overflow_fail() -> ! {
97 panic!("attempted to index str up to maximum usize");
98}
99
100#[stable(feature = "str_checked_slicing", since = "1.20.0")]
113#[rustc_const_unstable(feature = "const_index", issue = "143775")]
114#[cfg(not(feature = "ferrocene_certified"))]
115unsafe impl const SliceIndex<str> for ops::RangeFull {
116 type Output = str;
117 #[inline]
118 fn get(self, slice: &str) -> Option<&Self::Output> {
119 Some(slice)
120 }
121 #[inline]
122 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
123 Some(slice)
124 }
125 #[inline]
126 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
127 slice
128 }
129 #[inline]
130 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
131 slice
132 }
133 #[inline]
134 fn index(self, slice: &str) -> &Self::Output {
135 slice
136 }
137 #[inline]
138 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
139 slice
140 }
141}
142
143#[stable(feature = "str_checked_slicing", since = "1.20.0")]
179#[rustc_const_unstable(feature = "const_index", issue = "143775")]
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")]
459unsafe impl const SliceIndex<str> for ops::RangeTo<usize> {
460 type Output = str;
461 #[inline]
462 fn get(self, slice: &str) -> Option<&Self::Output> {
463 if slice.is_char_boundary(self.end) {
464 Some(unsafe { &*self.get_unchecked(slice) })
467 } else {
468 None
469 }
470 }
471 #[inline]
472 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
473 if slice.is_char_boundary(self.end) {
474 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
477 } else {
478 None
479 }
480 }
481 #[inline]
482 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
483 unsafe { (0..self.end).get_unchecked(slice) }
485 }
486 #[inline]
487 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
488 unsafe { (0..self.end).get_unchecked_mut(slice) }
490 }
491 #[inline]
492 fn index(self, slice: &str) -> &Self::Output {
493 let end = self.end;
494 match self.get(slice) {
495 Some(s) => s,
496 None => super::slice_error_fail(slice, 0, end),
497 }
498 }
499 #[inline]
500 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
501 if slice.is_char_boundary(self.end) {
502 unsafe { &mut *self.get_unchecked_mut(slice) }
505 } else {
506 super::slice_error_fail(slice, 0, self.end)
507 }
508 }
509}
510
511#[stable(feature = "str_checked_slicing", since = "1.20.0")]
527#[rustc_const_unstable(feature = "const_index", issue = "143775")]
528unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
529 type Output = str;
530 #[inline]
531 fn get(self, slice: &str) -> Option<&Self::Output> {
532 if slice.is_char_boundary(self.start) {
533 Some(unsafe { &*self.get_unchecked(slice) })
536 } else {
537 None
538 }
539 }
540 #[inline]
541 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
542 if slice.is_char_boundary(self.start) {
543 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
546 } else {
547 None
548 }
549 }
550 #[inline]
551 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
552 let len = (slice as *const [u8]).len();
553 unsafe { (self.start..len).get_unchecked(slice) }
555 }
556 #[inline]
557 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
558 let len = (slice as *mut [u8]).len();
559 unsafe { (self.start..len).get_unchecked_mut(slice) }
561 }
562 #[inline]
563 fn index(self, slice: &str) -> &Self::Output {
564 let (start, end) = (self.start, slice.len());
565 match self.get(slice) {
566 Some(s) => s,
567 None => super::slice_error_fail(slice, start, end),
568 }
569 }
570 #[inline]
571 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
572 if slice.is_char_boundary(self.start) {
573 unsafe { &mut *self.get_unchecked_mut(slice) }
576 } else {
577 super::slice_error_fail(slice, self.start, slice.len())
578 }
579 }
580}
581
582#[unstable(feature = "new_range_api", issue = "125687")]
583#[rustc_const_unstable(feature = "const_index", issue = "143775")]
584#[cfg(not(feature = "ferrocene_certified"))]
585unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
586 type Output = str;
587 #[inline]
588 fn get(self, slice: &str) -> Option<&Self::Output> {
589 if slice.is_char_boundary(self.start) {
590 Some(unsafe { &*self.get_unchecked(slice) })
593 } else {
594 None
595 }
596 }
597 #[inline]
598 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
599 if slice.is_char_boundary(self.start) {
600 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
603 } else {
604 None
605 }
606 }
607 #[inline]
608 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
609 let len = (slice as *const [u8]).len();
610 unsafe { (self.start..len).get_unchecked(slice) }
612 }
613 #[inline]
614 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
615 let len = (slice as *mut [u8]).len();
616 unsafe { (self.start..len).get_unchecked_mut(slice) }
618 }
619 #[inline]
620 fn index(self, slice: &str) -> &Self::Output {
621 let (start, end) = (self.start, slice.len());
622 match self.get(slice) {
623 Some(s) => s,
624 None => super::slice_error_fail(slice, start, end),
625 }
626 }
627 #[inline]
628 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
629 if slice.is_char_boundary(self.start) {
630 unsafe { &mut *self.get_unchecked_mut(slice) }
633 } else {
634 super::slice_error_fail(slice, self.start, slice.len())
635 }
636 }
637}
638
639#[stable(feature = "inclusive_range", since = "1.26.0")]
656#[rustc_const_unstable(feature = "const_index", issue = "143775")]
657#[cfg(not(feature = "ferrocene_certified"))]
658unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
659 type Output = str;
660 #[inline]
661 fn get(self, slice: &str) -> Option<&Self::Output> {
662 if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
663 }
664 #[inline]
665 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
666 if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
667 }
668 #[inline]
669 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
670 unsafe { self.into_slice_range().get_unchecked(slice) }
672 }
673 #[inline]
674 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
675 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
677 }
678 #[inline]
679 fn index(self, slice: &str) -> &Self::Output {
680 if *self.end() == usize::MAX {
681 str_index_overflow_fail();
682 }
683 self.into_slice_range().index(slice)
684 }
685 #[inline]
686 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
687 if *self.end() == usize::MAX {
688 str_index_overflow_fail();
689 }
690 self.into_slice_range().index_mut(slice)
691 }
692}
693
694#[unstable(feature = "new_range_api", issue = "125687")]
695#[rustc_const_unstable(feature = "const_index", issue = "143775")]
696#[cfg(not(feature = "ferrocene_certified"))]
697unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
698 type Output = str;
699 #[inline]
700 fn get(self, slice: &str) -> Option<&Self::Output> {
701 if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) }
702 }
703 #[inline]
704 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
705 if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
706 }
707 #[inline]
708 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
709 unsafe { self.into_slice_range().get_unchecked(slice) }
711 }
712 #[inline]
713 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
714 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
716 }
717 #[inline]
718 fn index(self, slice: &str) -> &Self::Output {
719 if self.last == usize::MAX {
720 str_index_overflow_fail();
721 }
722 self.into_slice_range().index(slice)
723 }
724 #[inline]
725 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
726 if self.last == usize::MAX {
727 str_index_overflow_fail();
728 }
729 self.into_slice_range().index_mut(slice)
730 }
731}
732
733#[stable(feature = "inclusive_range", since = "1.26.0")]
748#[rustc_const_unstable(feature = "const_index", issue = "143775")]
749#[cfg(not(feature = "ferrocene_certified"))]
750unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
751 type Output = str;
752 #[inline]
753 fn get(self, slice: &str) -> Option<&Self::Output> {
754 (0..=self.end).get(slice)
755 }
756 #[inline]
757 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
758 (0..=self.end).get_mut(slice)
759 }
760 #[inline]
761 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
762 unsafe { (0..=self.end).get_unchecked(slice) }
764 }
765 #[inline]
766 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
767 unsafe { (0..=self.end).get_unchecked_mut(slice) }
769 }
770 #[inline]
771 fn index(self, slice: &str) -> &Self::Output {
772 (0..=self.end).index(slice)
773 }
774 #[inline]
775 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
776 (0..=self.end).index_mut(slice)
777 }
778}
779
780#[stable(feature = "rust1", since = "1.0.0")]
850#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
851pub const trait FromStr: Sized {
852 #[stable(feature = "rust1", since = "1.0.0")]
854 type Err;
855
856 #[stable(feature = "rust1", since = "1.0.0")]
875 #[rustc_diagnostic_item = "from_str_method"]
876 fn from_str(s: &str) -> Result<Self, Self::Err>;
877}
878
879#[stable(feature = "rust1", since = "1.0.0")]
880#[cfg(not(feature = "ferrocene_certified"))]
881impl FromStr for bool {
882 type Err = ParseBoolError;
883
884 #[inline]
907 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
908 match s {
909 "true" => Ok(true),
910 "false" => Ok(false),
911 _ => Err(ParseBoolError),
912 }
913 }
914}