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")]
18impl Ord for str {
19 #[inline]
20 fn cmp(&self, other: &str) -> Ordering {
21 self.as_bytes().cmp(other.as_bytes())
22 }
23}
24
25#[stable(feature = "rust1", since = "1.0.0")]
26#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
27const impl PartialEq for str {
28 #[inline]
29 #[ferrocene::prevalidated]
30 fn eq(&self, other: &str) -> bool {
31 self.as_bytes() == other.as_bytes()
32 }
33}
34
35#[stable(feature = "rust1", since = "1.0.0")]
36#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
37const impl Eq for str {}
38
39#[stable(feature = "rust1", since = "1.0.0")]
47impl PartialOrd for str {
48 #[inline]
49 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
50 Some(self.cmp(other))
51 }
52}
53
54#[stable(feature = "rust1", since = "1.0.0")]
55#[rustc_const_unstable(feature = "const_index", issue = "143775")]
56const impl<I> ops::Index<I> for str
57where
58 I: [const] SliceIndex<str>,
59{
60 type Output = I::Output;
61
62 #[inline]
63 #[ferrocene::prevalidated]
64 fn index(&self, index: I) -> &I::Output {
65 index.index(self)
66 }
67}
68
69#[stable(feature = "rust1", since = "1.0.0")]
70#[rustc_const_unstable(feature = "const_index", issue = "143775")]
71const impl<I> ops::IndexMut<I> for str
72where
73 I: [const] SliceIndex<str>,
74{
75 #[inline]
76 fn index_mut(&mut self, index: I) -> &mut I::Output {
77 index.index_mut(self)
78 }
79}
80
81#[stable(feature = "str_checked_slicing", since = "1.20.0")]
94#[rustc_const_unstable(feature = "const_index", issue = "143775")]
95const unsafe impl SliceIndex<str> for ops::RangeFull {
96 type Output = str;
97 #[inline]
98 fn get(self, slice: &str) -> Option<&Self::Output> {
99 Some(slice)
100 }
101 #[inline]
102 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
103 Some(slice)
104 }
105 #[inline]
106 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
107 slice
108 }
109 #[inline]
110 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
111 slice
112 }
113 #[inline]
114 fn index(self, slice: &str) -> &Self::Output {
115 slice
116 }
117 #[inline]
118 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
119 slice
120 }
121}
122
123#[ferrocene::prevalidated]
127#[inline(always)]
128const fn check_range(slice: &str, range: crate::range::Range<usize>) -> bool {
129 let crate::range::Range { start, end } = range;
130 let bytes = slice.as_bytes();
131
132 if start > end || end > slice.len() {
133 return false;
134 }
135
136 if start == slice.len() {
137 return true;
139 }
140
141 unsafe {
148 (start == 0 || bytes.as_ptr().add(start).read().is_utf8_char_boundary())
149 && (end == slice.len() || bytes.as_ptr().add(end).read().is_utf8_char_boundary())
150 }
151}
152
153#[stable(feature = "str_checked_slicing", since = "1.20.0")]
189#[rustc_const_unstable(feature = "const_index", issue = "143775")]
190const unsafe impl SliceIndex<str> for ops::Range<usize> {
191 type Output = str;
192 #[inline]
193 #[ferrocene::prevalidated]
194 fn get(self, slice: &str) -> Option<&Self::Output> {
195 range::Range::from(self).get(slice)
196 }
197 #[inline]
198 #[ferrocene::prevalidated]
199 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
200 range::Range::from(self).get_mut(slice)
201 }
202 #[inline]
203 #[track_caller]
204 #[ferrocene::prevalidated]
205 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
206 let slice = slice as *const [u8];
207
208 assert_unsafe_precondition!(
209 check_library_ub,
216 "str::get_unchecked requires that the range is within the string slice",
217 (
218 start: usize = self.start,
219 end: usize = self.end,
220 len: usize = slice.len()
221 ) => end >= start && end <= len,
222 );
223
224 unsafe {
227 let new_len = unchecked_sub(self.end, self.start);
228 slice.as_ptr().add(self.start).cast_slice(new_len) as *const str
229 }
230 }
231 #[inline]
232 #[track_caller]
233 #[ferrocene::prevalidated]
234 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
235 let slice = slice as *mut [u8];
236
237 assert_unsafe_precondition!(
238 check_library_ub,
239 "str::get_unchecked_mut requires that the range is within the string slice",
240 (
241 start: usize = self.start,
242 end: usize = self.end,
243 len: usize = slice.len()
244 ) => end >= start && end <= len,
245 );
246
247 unsafe {
249 let new_len = unchecked_sub(self.end, self.start);
250 slice.as_mut_ptr().add(self.start).cast_slice(new_len) as *mut str
251 }
252 }
253 #[inline]
254 #[ferrocene::prevalidated]
255 fn index(self, slice: &str) -> &Self::Output {
256 range::Range::from(self).index(slice)
257 }
258 #[inline]
259 #[ferrocene::prevalidated]
260 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
261 range::Range::from(self).index_mut(slice)
262 }
263}
264
265#[stable(feature = "new_range_api", since = "1.96.0")]
266#[rustc_const_unstable(feature = "const_index", issue = "143775")]
267const unsafe impl SliceIndex<str> for range::Range<usize> {
268 type Output = str;
269 #[ferrocene::prevalidated]
270 #[inline]
271 fn get(self, slice: &str) -> Option<&Self::Output> {
272 if check_range(slice, self) {
273 Some(unsafe { &*self.get_unchecked(slice) })
277 } else {
278 None
279 }
280 }
281 #[ferrocene::prevalidated]
282 #[inline]
283 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
284 if check_range(slice, self) {
285 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
288 } else {
289 None
290 }
291 }
292 #[ferrocene::prevalidated]
293 #[inline]
294 #[track_caller]
295 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
296 let slice = slice as *const [u8];
297
298 assert_unsafe_precondition!(
299 check_library_ub,
306 "str::get_unchecked requires that the range is within the string slice",
307 (
308 start: usize = self.start,
309 end: usize = self.end,
310 len: usize = slice.len()
311 ) => end >= start && end <= len,
312 );
313
314 unsafe {
317 let new_len = unchecked_sub(self.end, self.start);
318 slice.as_ptr().add(self.start).cast_slice(new_len) as *const str
319 }
320 }
321 #[ferrocene::prevalidated]
322 #[inline]
323 #[track_caller]
324 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
325 let slice = slice as *mut [u8];
326
327 assert_unsafe_precondition!(
328 check_library_ub,
329 "str::get_unchecked_mut requires that the range is within the string slice",
330 (
331 start: usize = self.start,
332 end: usize = self.end,
333 len: usize = slice.len()
334 ) => end >= start && end <= len,
335 );
336
337 unsafe {
339 let new_len = unchecked_sub(self.end, self.start);
340 slice.as_mut_ptr().add(self.start).cast_slice(new_len) as *mut str
341 }
342 }
343 #[ferrocene::prevalidated]
344 #[inline]
345 fn index(self, slice: &str) -> &Self::Output {
346 let (start, end) = (self.start, self.end);
347 match self.get(slice) {
348 Some(s) => s,
349 None => super::slice_error_fail(slice, start, end),
350 }
351 }
352 #[ferrocene::prevalidated]
353 #[inline]
354 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
355 if check_range(slice, self) {
357 unsafe { &mut *self.get_unchecked_mut(slice) }
360 } else {
361 super::slice_error_fail(slice, self.start, self.end)
362 }
363 }
364}
365
366#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")]
380unsafe impl SliceIndex<str> for (ops::Bound<usize>, ops::Bound<usize>) {
381 type Output = str;
382
383 #[inline]
384 fn get(self, slice: &str) -> Option<&str> {
385 crate::slice::index::try_into_slice_range(slice.len(), self)?.get(slice)
386 }
387
388 #[inline]
389 fn get_mut(self, slice: &mut str) -> Option<&mut str> {
390 crate::slice::index::try_into_slice_range(slice.len(), self)?.get_mut(slice)
391 }
392
393 #[inline]
394 unsafe fn get_unchecked(self, slice: *const str) -> *const str {
395 let len = (slice as *const [u8]).len();
396 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked(slice) }
398 }
399
400 #[inline]
401 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str {
402 let len = (slice as *mut [u8]).len();
403 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked_mut(slice) }
405 }
406
407 #[inline]
408 fn index(self, slice: &str) -> &str {
409 crate::slice::index::into_slice_range(slice.len(), self).index(slice)
410 }
411
412 #[inline]
413 fn index_mut(self, slice: &mut str) -> &mut str {
414 crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice)
415 }
416}
417
418#[stable(feature = "str_checked_slicing", since = "1.20.0")]
434#[rustc_const_unstable(feature = "const_index", issue = "143775")]
435const unsafe impl SliceIndex<str> for ops::RangeTo<usize> {
436 type Output = str;
437 #[inline]
438 #[ferrocene::prevalidated]
439 fn get(self, slice: &str) -> Option<&Self::Output> {
440 if slice.is_char_boundary(self.end) {
441 Some(unsafe { &*self.get_unchecked(slice) })
444 } else {
445 None
446 }
447 }
448 #[inline]
449 #[ferrocene::prevalidated]
450 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
451 if slice.is_char_boundary(self.end) {
452 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
455 } else {
456 None
457 }
458 }
459 #[inline]
460 #[ferrocene::prevalidated]
461 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
462 unsafe { (0..self.end).get_unchecked(slice) }
464 }
465 #[inline]
466 #[ferrocene::prevalidated]
467 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
468 unsafe { (0..self.end).get_unchecked_mut(slice) }
470 }
471 #[inline]
472 #[ferrocene::prevalidated]
473 fn index(self, slice: &str) -> &Self::Output {
474 let end = self.end;
475 match self.get(slice) {
476 Some(s) => s,
477 None => super::slice_error_fail(slice, 0, end),
478 }
479 }
480 #[inline]
481 #[ferrocene::prevalidated]
482 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
483 if slice.is_char_boundary(self.end) {
484 unsafe { &mut *self.get_unchecked_mut(slice) }
487 } else {
488 super::slice_error_fail(slice, 0, self.end)
489 }
490 }
491}
492
493#[stable(feature = "str_checked_slicing", since = "1.20.0")]
509#[rustc_const_unstable(feature = "const_index", issue = "143775")]
510const unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
511 type Output = str;
512 #[inline]
513 #[ferrocene::prevalidated]
514 fn get(self, slice: &str) -> Option<&Self::Output> {
515 if slice.is_char_boundary(self.start) {
516 Some(unsafe { &*self.get_unchecked(slice) })
519 } else {
520 None
521 }
522 }
523 #[inline]
524 #[ferrocene::prevalidated]
525 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
526 if slice.is_char_boundary(self.start) {
527 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
530 } else {
531 None
532 }
533 }
534 #[inline]
535 #[ferrocene::prevalidated]
536 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
537 let len = (slice as *const [u8]).len();
538 unsafe { (self.start..len).get_unchecked(slice) }
540 }
541 #[inline]
542 #[ferrocene::prevalidated]
543 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
544 let len = (slice as *mut [u8]).len();
545 unsafe { (self.start..len).get_unchecked_mut(slice) }
547 }
548 #[inline]
549 #[ferrocene::prevalidated]
550 fn index(self, slice: &str) -> &Self::Output {
551 let (start, end) = (self.start, slice.len());
552 match self.get(slice) {
553 Some(s) => s,
554 None => super::slice_error_fail(slice, start, end),
555 }
556 }
557 #[inline]
558 #[ferrocene::prevalidated]
559 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
560 if slice.is_char_boundary(self.start) {
561 unsafe { &mut *self.get_unchecked_mut(slice) }
564 } else {
565 super::slice_error_fail(slice, self.start, slice.len())
566 }
567 }
568}
569
570#[stable(feature = "new_range_from_api", since = "1.96.0")]
571#[rustc_const_unstable(feature = "const_index", issue = "143775")]
572const unsafe impl SliceIndex<str> for range::RangeFrom<usize> {
573 type Output = str;
574 #[inline]
575 fn get(self, slice: &str) -> Option<&Self::Output> {
576 if slice.is_char_boundary(self.start) {
577 Some(unsafe { &*self.get_unchecked(slice) })
580 } else {
581 None
582 }
583 }
584 #[inline]
585 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
586 if slice.is_char_boundary(self.start) {
587 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
590 } else {
591 None
592 }
593 }
594 #[inline]
595 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
596 let len = (slice as *const [u8]).len();
597 unsafe { (self.start..len).get_unchecked(slice) }
599 }
600 #[inline]
601 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
602 let len = (slice as *mut [u8]).len();
603 unsafe { (self.start..len).get_unchecked_mut(slice) }
605 }
606 #[inline]
607 fn index(self, slice: &str) -> &Self::Output {
608 let (start, end) = (self.start, slice.len());
609 match self.get(slice) {
610 Some(s) => s,
611 None => super::slice_error_fail(slice, start, end),
612 }
613 }
614 #[inline]
615 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
616 if slice.is_char_boundary(self.start) {
617 unsafe { &mut *self.get_unchecked_mut(slice) }
620 } else {
621 super::slice_error_fail(slice, self.start, slice.len())
622 }
623 }
624}
625
626#[stable(feature = "inclusive_range", since = "1.26.0")]
643#[rustc_const_unstable(feature = "const_index", issue = "143775")]
644const unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
645 type Output = str;
646 #[inline]
647 fn get(self, slice: &str) -> Option<&Self::Output> {
648 if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) }
649 }
650 #[inline]
651 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
652 if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) }
653 }
654 #[inline]
655 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
656 unsafe { self.into_slice_range().get_unchecked(slice) }
658 }
659 #[inline]
660 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
661 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
663 }
664 #[inline]
665 fn index(self, slice: &str) -> &Self::Output {
666 let Self { mut start, mut end, exhausted } = self;
667 let len = slice.len();
668 if end < len {
669 end = end + 1;
670 start = if exhausted { end } else { start };
671 if start <= end && slice.is_char_boundary(start) && slice.is_char_boundary(end) {
672 unsafe { return &*(start..end).get_unchecked(slice) }
676 }
677 }
678
679 super::slice_error_fail(slice, start, end)
680 }
681 #[inline]
682 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
683 let Self { mut start, mut end, exhausted } = self;
684 let len = slice.len();
685 if end < len {
686 end = end + 1;
687 start = if exhausted { end } else { start };
688 if start <= end && slice.is_char_boundary(start) && slice.is_char_boundary(end) {
689 unsafe { return &mut *(start..end).get_unchecked_mut(slice) }
693 }
694 }
695
696 super::slice_error_fail(slice, start, end)
697 }
698}
699
700#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
701#[rustc_const_unstable(feature = "const_index", issue = "143775")]
702const unsafe impl SliceIndex<str> for range::RangeInclusive<usize> {
703 type Output = str;
704 #[inline]
705 fn get(self, slice: &str) -> Option<&Self::Output> {
706 ops::RangeInclusive::from(self).get(slice)
707 }
708 #[inline]
709 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
710 ops::RangeInclusive::from(self).get_mut(slice)
711 }
712 #[inline]
713 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
714 unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) }
716 }
717 #[inline]
718 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
719 unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) }
721 }
722 #[inline]
723 fn index(self, slice: &str) -> &Self::Output {
724 ops::RangeInclusive::from(self).index(slice)
725 }
726 #[inline]
727 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
728 ops::RangeInclusive::from(self).index_mut(slice)
729 }
730}
731
732#[stable(feature = "inclusive_range", since = "1.26.0")]
747#[rustc_const_unstable(feature = "const_index", issue = "143775")]
748const unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> {
749 type Output = str;
750 #[inline]
751 fn get(self, slice: &str) -> Option<&Self::Output> {
752 (0..=self.end).get(slice)
753 }
754 #[inline]
755 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
756 (0..=self.end).get_mut(slice)
757 }
758 #[inline]
759 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
760 unsafe { (0..=self.end).get_unchecked(slice) }
762 }
763 #[inline]
764 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
765 unsafe { (0..=self.end).get_unchecked_mut(slice) }
767 }
768 #[inline]
769 fn index(self, slice: &str) -> &Self::Output {
770 (0..=self.end).index(slice)
771 }
772 #[inline]
773 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
774 (0..=self.end).index_mut(slice)
775 }
776}
777
778#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
793#[rustc_const_unstable(feature = "const_index", issue = "143775")]
794const unsafe impl SliceIndex<str> for range::RangeToInclusive<usize> {
795 type Output = str;
796 #[inline]
797 fn get(self, slice: &str) -> Option<&Self::Output> {
798 (0..=self.last).get(slice)
799 }
800 #[inline]
801 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
802 (0..=self.last).get_mut(slice)
803 }
804 #[inline]
805 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
806 unsafe { (0..=self.last).get_unchecked(slice) }
808 }
809 #[inline]
810 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
811 unsafe { (0..=self.last).get_unchecked_mut(slice) }
813 }
814 #[inline]
815 fn index(self, slice: &str) -> &Self::Output {
816 (0..=self.last).index(slice)
817 }
818 #[inline]
819 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
820 (0..=self.last).index_mut(slice)
821 }
822}
823
824#[stable(feature = "rust1", since = "1.0.0")]
894#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
895pub const trait FromStr: Sized {
896 #[stable(feature = "rust1", since = "1.0.0")]
898 type Err;
899
900 #[stable(feature = "rust1", since = "1.0.0")]
919 #[rustc_diagnostic_item = "from_str_method"]
920 fn from_str(s: &str) -> Result<Self, Self::Err>;
921}
922
923#[stable(feature = "rust1", since = "1.0.0")]
924impl FromStr for bool {
925 type Err = ParseBoolError;
926
927 #[inline]
950 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
951 match s {
952 "true" => Ok(true),
953 "false" => Ok(false),
954 _ => Err(ParseBoolError),
955 }
956 }
957}