1use super::ParseBoolError;
4use crate::cmp::Ordering;
5use crate::intrinsics::unchecked_sub;
6use crate::slice::SliceIndex;
7use crate::ub_checks::assert_unsafe_precondition;
8use crate::{ops, range};
9
10#[stable(feature = "rust1", since = "1.0.0")]
18#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
19const impl Ord for str {
20 #[inline]
21 fn cmp(&self, other: &str) -> Ordering {
22 self.as_bytes().cmp(other.as_bytes())
23 }
24}
25
26#[stable(feature = "rust1", since = "1.0.0")]
27#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
28const impl PartialEq for str {
29 #[inline]
30 #[ferrocene::prevalidated]
31 fn eq(&self, other: &str) -> bool {
32 self.as_bytes() == other.as_bytes()
33 }
34}
35
36#[stable(feature = "rust1", since = "1.0.0")]
37#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
38const impl Eq for str {}
39
40#[stable(feature = "rust1", since = "1.0.0")]
48#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
49const impl PartialOrd for str {
50 #[inline]
51 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
52 Some(self.cmp(other))
53 }
54}
55
56#[stable(feature = "rust1", since = "1.0.0")]
57#[rustc_const_unstable(feature = "const_index", issue = "143775")]
58const impl<I> ops::Index<I> for str
59where
60 I: [const] SliceIndex<str>,
61{
62 type Output = I::Output;
63
64 #[inline]
65 #[ferrocene::prevalidated]
66 fn index(&self, index: I) -> &I::Output {
67 index.index(self)
68 }
69}
70
71#[stable(feature = "rust1", since = "1.0.0")]
72#[rustc_const_unstable(feature = "const_index", issue = "143775")]
73const impl<I> ops::IndexMut<I> for str
74where
75 I: [const] SliceIndex<str>,
76{
77 #[inline]
78 fn index_mut(&mut self, index: I) -> &mut I::Output {
79 index.index_mut(self)
80 }
81}
82
83#[stable(feature = "str_checked_slicing", since = "1.20.0")]
96#[rustc_const_unstable(feature = "const_index", issue = "143775")]
97const unsafe impl SliceIndex<str> for ops::RangeFull {
98 type Output = str;
99 #[inline]
100 fn get(self, slice: &str) -> Option<&Self::Output> {
101 Some(slice)
102 }
103 #[inline]
104 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
105 Some(slice)
106 }
107 #[inline]
108 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
109 slice
110 }
111 #[inline]
112 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
113 slice
114 }
115 #[inline]
116 fn index(self, slice: &str) -> &Self::Output {
117 slice
118 }
119 #[inline]
120 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
121 slice
122 }
123}
124
125#[ferrocene::prevalidated]
129#[inline(always)]
130const fn check_range(slice: &str, range: crate::range::Range<usize>) -> bool {
131 let crate::range::Range { start, end } = range;
132 let bytes = slice.as_bytes();
133
134 if start > end || end > slice.len() {
135 return false;
136 }
137
138 if start == slice.len() {
139 return true;
141 }
142
143 unsafe {
150 (start == 0 || bytes.as_ptr().add(start).read().is_utf8_char_boundary())
151 && (end == slice.len() || bytes.as_ptr().add(end).read().is_utf8_char_boundary())
152 }
153}
154
155#[stable(feature = "str_checked_slicing", since = "1.20.0")]
191#[rustc_const_unstable(feature = "const_index", issue = "143775")]
192const unsafe impl SliceIndex<str> for ops::Range<usize> {
193 type Output = str;
194 #[inline]
195 #[ferrocene::prevalidated]
196 fn get(self, slice: &str) -> Option<&Self::Output> {
197 range::Range::from(self).get(slice)
198 }
199 #[inline]
200 #[ferrocene::prevalidated]
201 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
202 range::Range::from(self).get_mut(slice)
203 }
204 #[inline]
205 #[track_caller]
206 #[ferrocene::prevalidated]
207 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
208 let slice = slice as *const [u8];
209
210 assert_unsafe_precondition!(
211 check_library_ub,
218 "str::get_unchecked requires that the range is within the string slice",
219 (
220 start: usize = self.start,
221 end: usize = self.end,
222 len: usize = slice.len()
223 ) => end >= start && end <= len,
224 );
225
226 unsafe {
229 let new_len = unchecked_sub(self.end, self.start);
230 slice.as_ptr().add(self.start).cast_slice(new_len) as *const str
231 }
232 }
233 #[inline]
234 #[track_caller]
235 #[ferrocene::prevalidated]
236 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
237 let slice = slice as *mut [u8];
238
239 assert_unsafe_precondition!(
240 check_library_ub,
241 "str::get_unchecked_mut requires that the range is within the string slice",
242 (
243 start: usize = self.start,
244 end: usize = self.end,
245 len: usize = slice.len()
246 ) => end >= start && end <= len,
247 );
248
249 unsafe {
251 let new_len = unchecked_sub(self.end, self.start);
252 slice.as_mut_ptr().add(self.start).cast_slice(new_len) as *mut str
253 }
254 }
255 #[inline]
256 #[ferrocene::prevalidated]
257 fn index(self, slice: &str) -> &Self::Output {
258 range::Range::from(self).index(slice)
259 }
260 #[inline]
261 #[ferrocene::prevalidated]
262 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
263 range::Range::from(self).index_mut(slice)
264 }
265}
266
267#[stable(feature = "new_range_api", since = "1.96.0")]
268#[rustc_const_unstable(feature = "const_index", issue = "143775")]
269const unsafe impl SliceIndex<str> for range::Range<usize> {
270 type Output = str;
271 #[ferrocene::prevalidated]
272 #[inline]
273 fn get(self, slice: &str) -> Option<&Self::Output> {
274 if check_range(slice, self) {
275 Some(unsafe { &*self.get_unchecked(slice) })
279 } else {
280 None
281 }
282 }
283 #[ferrocene::prevalidated]
284 #[inline]
285 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
286 if check_range(slice, self) {
287 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
290 } else {
291 None
292 }
293 }
294 #[ferrocene::prevalidated]
295 #[inline]
296 #[track_caller]
297 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
298 let slice = slice as *const [u8];
299
300 assert_unsafe_precondition!(
301 check_library_ub,
308 "str::get_unchecked requires that the range is within the string slice",
309 (
310 start: usize = self.start,
311 end: usize = self.end,
312 len: usize = slice.len()
313 ) => end >= start && end <= len,
314 );
315
316 unsafe {
319 let new_len = unchecked_sub(self.end, self.start);
320 slice.as_ptr().add(self.start).cast_slice(new_len) as *const str
321 }
322 }
323 #[ferrocene::prevalidated]
324 #[inline]
325 #[track_caller]
326 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
327 let slice = slice as *mut [u8];
328
329 assert_unsafe_precondition!(
330 check_library_ub,
331 "str::get_unchecked_mut requires that the range is within the string slice",
332 (
333 start: usize = self.start,
334 end: usize = self.end,
335 len: usize = slice.len()
336 ) => end >= start && end <= len,
337 );
338
339 unsafe {
341 let new_len = unchecked_sub(self.end, self.start);
342 slice.as_mut_ptr().add(self.start).cast_slice(new_len) as *mut str
343 }
344 }
345 #[ferrocene::prevalidated]
346 #[inline]
347 fn index(self, slice: &str) -> &Self::Output {
348 let (start, end) = (self.start, self.end);
349 match self.get(slice) {
350 Some(s) => s,
351 None => super::slice_error_fail(slice, start, end),
352 }
353 }
354 #[ferrocene::prevalidated]
355 #[inline]
356 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
357 if check_range(slice, self) {
359 unsafe { &mut *self.get_unchecked_mut(slice) }
362 } else {
363 super::slice_error_fail(slice, self.start, self.end)
364 }
365 }
366}
367
368#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")]
382unsafe impl SliceIndex<str> for (ops::Bound<usize>, ops::Bound<usize>) {
383 type Output = str;
384
385 #[inline]
386 fn get(self, slice: &str) -> Option<&str> {
387 crate::slice::index::try_into_slice_range(slice.len(), self).ok()?.get(slice)
388 }
389
390 #[inline]
391 fn get_mut(self, slice: &mut str) -> Option<&mut str> {
392 crate::slice::index::try_into_slice_range(slice.len(), self).ok()?.get_mut(slice)
393 }
394
395 #[inline]
396 unsafe fn get_unchecked(self, slice: *const str) -> *const str {
397 let len = (slice as *const [u8]).len();
398 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked(slice) }
400 }
401
402 #[inline]
403 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str {
404 let len = (slice as *mut [u8]).len();
405 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked_mut(slice) }
407 }
408
409 #[inline]
410 fn index(self, slice: &str) -> &str {
411 crate::slice::index::into_slice_range(slice.len(), self).index(slice)
412 }
413
414 #[inline]
415 fn index_mut(self, slice: &mut str) -> &mut str {
416 crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice)
417 }
418}
419
420#[stable(feature = "str_checked_slicing", since = "1.20.0")]
436#[rustc_const_unstable(feature = "const_index", issue = "143775")]
437const unsafe impl SliceIndex<str> for ops::RangeTo<usize> {
438 type Output = str;
439 #[inline]
440 #[ferrocene::prevalidated]
441 fn get(self, slice: &str) -> Option<&Self::Output> {
442 if slice.is_char_boundary(self.end) {
443 Some(unsafe { &*self.get_unchecked(slice) })
446 } else {
447 None
448 }
449 }
450 #[inline]
451 #[ferrocene::prevalidated]
452 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
453 if slice.is_char_boundary(self.end) {
454 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
457 } else {
458 None
459 }
460 }
461 #[inline]
462 #[ferrocene::prevalidated]
463 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
464 unsafe { (0..self.end).get_unchecked(slice) }
466 }
467 #[inline]
468 #[ferrocene::prevalidated]
469 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
470 unsafe { (0..self.end).get_unchecked_mut(slice) }
472 }
473 #[inline]
474 #[ferrocene::prevalidated]
475 fn index(self, slice: &str) -> &Self::Output {
476 let end = self.end;
477 match self.get(slice) {
478 Some(s) => s,
479 None => super::slice_error_fail(slice, 0, end),
480 }
481 }
482 #[inline]
483 #[ferrocene::prevalidated]
484 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
485 if slice.is_char_boundary(self.end) {
486 unsafe { &mut *self.get_unchecked_mut(slice) }
489 } else {
490 super::slice_error_fail(slice, 0, self.end)
491 }
492 }
493}
494
495#[stable(feature = "str_checked_slicing", since = "1.20.0")]
511#[rustc_const_unstable(feature = "const_index", issue = "143775")]
512const unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
513 type Output = str;
514 #[inline]
515 #[ferrocene::prevalidated]
516 fn get(self, slice: &str) -> Option<&Self::Output> {
517 if slice.is_char_boundary(self.start) {
518 Some(unsafe { &*self.get_unchecked(slice) })
521 } else {
522 None
523 }
524 }
525 #[inline]
526 #[ferrocene::prevalidated]
527 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
528 if slice.is_char_boundary(self.start) {
529 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
532 } else {
533 None
534 }
535 }
536 #[inline]
537 #[ferrocene::prevalidated]
538 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
539 let len = (slice as *const [u8]).len();
540 unsafe { (self.start..len).get_unchecked(slice) }
542 }
543 #[inline]
544 #[ferrocene::prevalidated]
545 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
546 let len = (slice as *mut [u8]).len();
547 unsafe { (self.start..len).get_unchecked_mut(slice) }
549 }
550 #[inline]
551 #[ferrocene::prevalidated]
552 fn index(self, slice: &str) -> &Self::Output {
553 let (start, end) = (self.start, slice.len());
554 match self.get(slice) {
555 Some(s) => s,
556 None => super::slice_error_fail(slice, start, end),
557 }
558 }
559 #[inline]
560 #[ferrocene::prevalidated]
561 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
562 if slice.is_char_boundary(self.start) {
563 unsafe { &mut *self.get_unchecked_mut(slice) }
566 } else {
567 super::slice_error_fail(slice, self.start, slice.len())
568 }
569 }
570}
571
572#[stable(feature = "new_range_from_api", since = "1.96.0")]
573#[rustc_const_unstable(feature = "const_index", issue = "143775")]
574const unsafe impl SliceIndex<str> for range::RangeFrom<usize> {
575 type Output = str;
576 #[inline]
577 fn get(self, slice: &str) -> Option<&Self::Output> {
578 if slice.is_char_boundary(self.start) {
579 Some(unsafe { &*self.get_unchecked(slice) })
582 } else {
583 None
584 }
585 }
586 #[inline]
587 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
588 if slice.is_char_boundary(self.start) {
589 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
592 } else {
593 None
594 }
595 }
596 #[inline]
597 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
598 let len = (slice as *const [u8]).len();
599 unsafe { (self.start..len).get_unchecked(slice) }
601 }
602 #[inline]
603 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
604 let len = (slice as *mut [u8]).len();
605 unsafe { (self.start..len).get_unchecked_mut(slice) }
607 }
608 #[inline]
609 fn index(self, slice: &str) -> &Self::Output {
610 let (start, end) = (self.start, slice.len());
611 match self.get(slice) {
612 Some(s) => s,
613 None => super::slice_error_fail(slice, start, end),
614 }
615 }
616 #[inline]
617 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
618 if slice.is_char_boundary(self.start) {
619 unsafe { &mut *self.get_unchecked_mut(slice) }
622 } else {
623 super::slice_error_fail(slice, self.start, slice.len())
624 }
625 }
626}
627
628#[stable(feature = "inclusive_range", since = "1.26.0")]
645#[rustc_const_unstable(feature = "const_index", issue = "143775")]
646const unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
647 type Output = str;
648 #[inline]
649 fn get(self, slice: &str) -> Option<&Self::Output> {
650 if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) }
651 }
652 #[inline]
653 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
654 if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) }
655 }
656 #[inline]
657 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
658 unsafe { self.into_slice_range().get_unchecked(slice) }
660 }
661 #[inline]
662 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
663 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
665 }
666 #[inline]
667 fn index(self, slice: &str) -> &Self::Output {
668 let Self { mut start, mut end, exhausted } = self;
669 let len = slice.len();
670 if end < len {
671 end = end + 1;
672 start = if exhausted { end } else { start };
673 if start <= end && slice.is_char_boundary(start) && slice.is_char_boundary(end) {
674 unsafe { return &*(start..end).get_unchecked(slice) }
678 }
679 }
680
681 super::slice_error_fail(slice, start, end)
682 }
683 #[inline]
684 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
685 let Self { mut start, mut end, exhausted } = self;
686 let len = slice.len();
687 if end < len {
688 end = end + 1;
689 start = if exhausted { end } else { start };
690 if start <= end && slice.is_char_boundary(start) && slice.is_char_boundary(end) {
691 unsafe { return &mut *(start..end).get_unchecked_mut(slice) }
695 }
696 }
697
698 super::slice_error_fail(slice, start, end)
699 }
700}
701
702#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
703#[rustc_const_unstable(feature = "const_index", issue = "143775")]
704const unsafe impl SliceIndex<str> for range::RangeInclusive<usize> {
705 type Output = str;
706 #[inline]
707 fn get(self, slice: &str) -> Option<&Self::Output> {
708 ops::RangeInclusive::from(self).get(slice)
709 }
710 #[inline]
711 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
712 ops::RangeInclusive::from(self).get_mut(slice)
713 }
714 #[inline]
715 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
716 unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) }
718 }
719 #[inline]
720 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
721 unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) }
723 }
724 #[inline]
725 fn index(self, slice: &str) -> &Self::Output {
726 ops::RangeInclusive::from(self).index(slice)
727 }
728 #[inline]
729 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
730 ops::RangeInclusive::from(self).index_mut(slice)
731 }
732}
733
734#[stable(feature = "inclusive_range", since = "1.26.0")]
749#[rustc_const_unstable(feature = "const_index", issue = "143775")]
750const unsafe impl 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 = "new_range_to_inclusive_api", since = "1.96.0")]
795#[rustc_const_unstable(feature = "const_index", issue = "143775")]
796const unsafe impl SliceIndex<str> for range::RangeToInclusive<usize> {
797 type Output = str;
798 #[inline]
799 fn get(self, slice: &str) -> Option<&Self::Output> {
800 (0..=self.last).get(slice)
801 }
802 #[inline]
803 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
804 (0..=self.last).get_mut(slice)
805 }
806 #[inline]
807 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
808 unsafe { (0..=self.last).get_unchecked(slice) }
810 }
811 #[inline]
812 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
813 unsafe { (0..=self.last).get_unchecked_mut(slice) }
815 }
816 #[inline]
817 fn index(self, slice: &str) -> &Self::Output {
818 (0..=self.last).index(slice)
819 }
820 #[inline]
821 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
822 (0..=self.last).index_mut(slice)
823 }
824}
825
826#[stable(feature = "rust1", since = "1.0.0")]
896#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
897pub const trait FromStr: Sized {
898 #[stable(feature = "rust1", since = "1.0.0")]
900 type Err;
901
902 #[stable(feature = "rust1", since = "1.0.0")]
921 #[rustc_diagnostic_item = "from_str_method"]
922 fn from_str(s: &str) -> Result<Self, Self::Err>;
923}
924
925#[stable(feature = "rust1", since = "1.0.0")]
926impl FromStr for bool {
927 type Err = ParseBoolError;
928
929 #[inline]
952 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
953 match s {
954 "true" => Ok(true),
955 "false" => Ok(false),
956 _ => Err(ParseBoolError),
957 }
958 }
959}