1#[cfg(not(feature = "ferrocene_subset"))]
4use super::ParseBoolError;
5#[cfg(not(feature = "ferrocene_subset"))]
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_subset"))]
11use crate::{ops, ptr, range};
12
13#[cfg(feature = "ferrocene_subset")]
15#[rustfmt::skip]
16use crate::{ops, ptr};
17
18#[stable(feature = "rust1", since = "1.0.0")]
26#[cfg(not(feature = "ferrocene_subset"))]
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")]
36impl const PartialEq for str {
37 #[inline]
38 fn eq(&self, other: &str) -> bool {
39 self.as_bytes() == other.as_bytes()
40 }
41}
42
43#[stable(feature = "rust1", since = "1.0.0")]
44#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
45impl const Eq for str {}
46
47#[stable(feature = "rust1", since = "1.0.0")]
55#[cfg(not(feature = "ferrocene_subset"))]
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")]
65impl<I> const ops::Index<I> for str
66where
67 I: [const] SliceIndex<str>,
68{
69 type Output = I::Output;
70
71 #[inline]
72 fn index(&self, index: I) -> &I::Output {
73 index.index(self)
74 }
75}
76
77#[stable(feature = "rust1", since = "1.0.0")]
78#[rustc_const_unstable(feature = "const_index", issue = "143775")]
79#[cfg(not(feature = "ferrocene_subset"))]
80impl<I> const ops::IndexMut<I> for str
81where
82 I: [const] SliceIndex<str>,
83{
84 #[inline]
85 fn index_mut(&mut self, index: I) -> &mut I::Output {
86 index.index_mut(self)
87 }
88}
89
90#[inline(never)]
91#[cold]
92#[track_caller]
93#[cfg(not(feature = "ferrocene_subset"))]
94const fn str_index_overflow_fail() -> ! {
95 panic!("attempted to index str up to maximum usize");
96}
97
98#[stable(feature = "str_checked_slicing", since = "1.20.0")]
111#[rustc_const_unstable(feature = "const_index", issue = "143775")]
112#[cfg(not(feature = "ferrocene_subset"))]
113unsafe impl const SliceIndex<str> for ops::RangeFull {
114 type Output = str;
115 #[inline]
116 fn get(self, slice: &str) -> Option<&Self::Output> {
117 Some(slice)
118 }
119 #[inline]
120 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
121 Some(slice)
122 }
123 #[inline]
124 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
125 slice
126 }
127 #[inline]
128 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
129 slice
130 }
131 #[inline]
132 fn index(self, slice: &str) -> &Self::Output {
133 slice
134 }
135 #[inline]
136 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
137 slice
138 }
139}
140
141#[stable(feature = "str_checked_slicing", since = "1.20.0")]
177#[rustc_const_unstable(feature = "const_index", issue = "143775")]
178unsafe impl const SliceIndex<str> for ops::Range<usize> {
179 type Output = str;
180 #[inline]
181 fn get(self, slice: &str) -> Option<&Self::Output> {
182 if self.start <= self.end
183 && slice.is_char_boundary(self.start)
184 && slice.is_char_boundary(self.end)
185 {
186 Some(unsafe { &*self.get_unchecked(slice) })
190 } else {
191 None
192 }
193 }
194 #[inline]
195 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
196 if self.start <= self.end
197 && slice.is_char_boundary(self.start)
198 && slice.is_char_boundary(self.end)
199 {
200 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
203 } else {
204 None
205 }
206 }
207 #[inline]
208 #[track_caller]
209 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
210 let slice = slice as *const [u8];
211
212 assert_unsafe_precondition!(
213 check_library_ub,
220 "str::get_unchecked requires that the range is within the string slice",
221 (
222 start: usize = self.start,
223 end: usize = self.end,
224 len: usize = slice.len()
225 ) => end >= start && end <= len,
226 );
227
228 unsafe {
231 let new_len = unchecked_sub(self.end, self.start);
232 ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
233 }
234 }
235 #[inline]
236 #[track_caller]
237 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
238 let slice = slice as *mut [u8];
239
240 assert_unsafe_precondition!(
241 check_library_ub,
242 "str::get_unchecked_mut requires that the range is within the string slice",
243 (
244 start: usize = self.start,
245 end: usize = self.end,
246 len: usize = slice.len()
247 ) => end >= start && end <= len,
248 );
249
250 unsafe {
252 let new_len = unchecked_sub(self.end, self.start);
253 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
254 }
255 }
256 #[inline]
257 fn index(self, slice: &str) -> &Self::Output {
258 let (start, end) = (self.start, self.end);
259 match self.get(slice) {
260 Some(s) => s,
261 None => super::slice_error_fail(slice, start, end),
262 }
263 }
264 #[inline]
265 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
266 if self.start <= self.end
269 && slice.is_char_boundary(self.start)
270 && slice.is_char_boundary(self.end)
271 {
272 unsafe { &mut *self.get_unchecked_mut(slice) }
275 } else {
276 super::slice_error_fail(slice, self.start, self.end)
277 }
278 }
279}
280
281#[unstable(feature = "new_range_api", issue = "125687")]
282#[rustc_const_unstable(feature = "const_index", issue = "143775")]
283#[cfg(not(feature = "ferrocene_subset"))]
284unsafe impl const SliceIndex<str> for range::Range<usize> {
285 type Output = str;
286 #[inline]
287 fn get(self, slice: &str) -> Option<&Self::Output> {
288 if self.start <= self.end
289 && slice.is_char_boundary(self.start)
290 && slice.is_char_boundary(self.end)
291 {
292 Some(unsafe { &*self.get_unchecked(slice) })
296 } else {
297 None
298 }
299 }
300 #[inline]
301 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
302 if self.start <= self.end
303 && slice.is_char_boundary(self.start)
304 && slice.is_char_boundary(self.end)
305 {
306 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
309 } else {
310 None
311 }
312 }
313 #[inline]
314 #[track_caller]
315 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
316 let slice = slice as *const [u8];
317
318 assert_unsafe_precondition!(
319 check_library_ub,
326 "str::get_unchecked requires that the range is within the string slice",
327 (
328 start: usize = self.start,
329 end: usize = self.end,
330 len: usize = slice.len()
331 ) => end >= start && end <= len,
332 );
333
334 unsafe {
337 let new_len = unchecked_sub(self.end, self.start);
338 ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
339 }
340 }
341 #[inline]
342 #[track_caller]
343 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
344 let slice = slice as *mut [u8];
345
346 assert_unsafe_precondition!(
347 check_library_ub,
348 "str::get_unchecked_mut requires that the range is within the string slice",
349 (
350 start: usize = self.start,
351 end: usize = self.end,
352 len: usize = slice.len()
353 ) => end >= start && end <= len,
354 );
355
356 unsafe {
358 let new_len = unchecked_sub(self.end, self.start);
359 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
360 }
361 }
362 #[inline]
363 fn index(self, slice: &str) -> &Self::Output {
364 let (start, end) = (self.start, self.end);
365 match self.get(slice) {
366 Some(s) => s,
367 None => super::slice_error_fail(slice, start, end),
368 }
369 }
370 #[inline]
371 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
372 if self.start <= self.end
375 && slice.is_char_boundary(self.start)
376 && slice.is_char_boundary(self.end)
377 {
378 unsafe { &mut *self.get_unchecked_mut(slice) }
381 } else {
382 super::slice_error_fail(slice, self.start, self.end)
383 }
384 }
385}
386
387#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")]
401#[cfg(not(feature = "ferrocene_subset"))]
402unsafe impl SliceIndex<str> for (ops::Bound<usize>, ops::Bound<usize>) {
403 type Output = str;
404
405 #[inline]
406 fn get(self, slice: &str) -> Option<&str> {
407 crate::slice::index::into_range(slice.len(), self)?.get(slice)
408 }
409
410 #[inline]
411 fn get_mut(self, slice: &mut str) -> Option<&mut str> {
412 crate::slice::index::into_range(slice.len(), self)?.get_mut(slice)
413 }
414
415 #[inline]
416 unsafe fn get_unchecked(self, slice: *const str) -> *const str {
417 let len = (slice as *const [u8]).len();
418 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked(slice) }
420 }
421
422 #[inline]
423 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str {
424 let len = (slice as *mut [u8]).len();
425 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked_mut(slice) }
427 }
428
429 #[inline]
430 fn index(self, slice: &str) -> &str {
431 crate::slice::index::into_slice_range(slice.len(), self).index(slice)
432 }
433
434 #[inline]
435 fn index_mut(self, slice: &mut str) -> &mut str {
436 crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice)
437 }
438}
439
440#[stable(feature = "str_checked_slicing", since = "1.20.0")]
456#[rustc_const_unstable(feature = "const_index", issue = "143775")]
457unsafe impl const SliceIndex<str> for ops::RangeTo<usize> {
458 type Output = str;
459 #[inline]
460 fn get(self, slice: &str) -> Option<&Self::Output> {
461 if slice.is_char_boundary(self.end) {
462 Some(unsafe { &*self.get_unchecked(slice) })
465 } else {
466 None
467 }
468 }
469 #[inline]
470 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
471 if slice.is_char_boundary(self.end) {
472 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
475 } else {
476 None
477 }
478 }
479 #[inline]
480 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
481 unsafe { (0..self.end).get_unchecked(slice) }
483 }
484 #[inline]
485 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
486 unsafe { (0..self.end).get_unchecked_mut(slice) }
488 }
489 #[inline]
490 fn index(self, slice: &str) -> &Self::Output {
491 let end = self.end;
492 match self.get(slice) {
493 Some(s) => s,
494 None => super::slice_error_fail(slice, 0, end),
495 }
496 }
497 #[inline]
498 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
499 if slice.is_char_boundary(self.end) {
500 unsafe { &mut *self.get_unchecked_mut(slice) }
503 } else {
504 super::slice_error_fail(slice, 0, self.end)
505 }
506 }
507}
508
509#[stable(feature = "str_checked_slicing", since = "1.20.0")]
525#[rustc_const_unstable(feature = "const_index", issue = "143775")]
526unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
527 type Output = str;
528 #[inline]
529 fn get(self, slice: &str) -> Option<&Self::Output> {
530 if slice.is_char_boundary(self.start) {
531 Some(unsafe { &*self.get_unchecked(slice) })
534 } else {
535 None
536 }
537 }
538 #[inline]
539 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
540 if slice.is_char_boundary(self.start) {
541 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
544 } else {
545 None
546 }
547 }
548 #[inline]
549 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
550 let len = (slice as *const [u8]).len();
551 unsafe { (self.start..len).get_unchecked(slice) }
553 }
554 #[inline]
555 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
556 let len = (slice as *mut [u8]).len();
557 unsafe { (self.start..len).get_unchecked_mut(slice) }
559 }
560 #[inline]
561 fn index(self, slice: &str) -> &Self::Output {
562 let (start, end) = (self.start, slice.len());
563 match self.get(slice) {
564 Some(s) => s,
565 None => super::slice_error_fail(slice, start, end),
566 }
567 }
568 #[inline]
569 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
570 if slice.is_char_boundary(self.start) {
571 unsafe { &mut *self.get_unchecked_mut(slice) }
574 } else {
575 super::slice_error_fail(slice, self.start, slice.len())
576 }
577 }
578}
579
580#[unstable(feature = "new_range_api", issue = "125687")]
581#[rustc_const_unstable(feature = "const_index", issue = "143775")]
582#[cfg(not(feature = "ferrocene_subset"))]
583unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
584 type Output = str;
585 #[inline]
586 fn get(self, slice: &str) -> Option<&Self::Output> {
587 if slice.is_char_boundary(self.start) {
588 Some(unsafe { &*self.get_unchecked(slice) })
591 } else {
592 None
593 }
594 }
595 #[inline]
596 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
597 if slice.is_char_boundary(self.start) {
598 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
601 } else {
602 None
603 }
604 }
605 #[inline]
606 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
607 let len = (slice as *const [u8]).len();
608 unsafe { (self.start..len).get_unchecked(slice) }
610 }
611 #[inline]
612 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
613 let len = (slice as *mut [u8]).len();
614 unsafe { (self.start..len).get_unchecked_mut(slice) }
616 }
617 #[inline]
618 fn index(self, slice: &str) -> &Self::Output {
619 let (start, end) = (self.start, slice.len());
620 match self.get(slice) {
621 Some(s) => s,
622 None => super::slice_error_fail(slice, start, end),
623 }
624 }
625 #[inline]
626 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
627 if slice.is_char_boundary(self.start) {
628 unsafe { &mut *self.get_unchecked_mut(slice) }
631 } else {
632 super::slice_error_fail(slice, self.start, slice.len())
633 }
634 }
635}
636
637#[stable(feature = "inclusive_range", since = "1.26.0")]
654#[rustc_const_unstable(feature = "const_index", issue = "143775")]
655#[cfg(not(feature = "ferrocene_subset"))]
656unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
657 type Output = str;
658 #[inline]
659 fn get(self, slice: &str) -> Option<&Self::Output> {
660 if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
661 }
662 #[inline]
663 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
664 if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
665 }
666 #[inline]
667 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
668 unsafe { self.into_slice_range().get_unchecked(slice) }
670 }
671 #[inline]
672 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
673 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
675 }
676 #[inline]
677 fn index(self, slice: &str) -> &Self::Output {
678 if *self.end() == usize::MAX {
679 str_index_overflow_fail();
680 }
681 self.into_slice_range().index(slice)
682 }
683 #[inline]
684 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
685 if *self.end() == usize::MAX {
686 str_index_overflow_fail();
687 }
688 self.into_slice_range().index_mut(slice)
689 }
690}
691
692#[unstable(feature = "new_range_api", issue = "125687")]
693#[rustc_const_unstable(feature = "const_index", issue = "143775")]
694#[cfg(not(feature = "ferrocene_subset"))]
695unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
696 type Output = str;
697 #[inline]
698 fn get(self, slice: &str) -> Option<&Self::Output> {
699 if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) }
700 }
701 #[inline]
702 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
703 if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
704 }
705 #[inline]
706 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
707 unsafe { self.into_slice_range().get_unchecked(slice) }
709 }
710 #[inline]
711 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
712 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
714 }
715 #[inline]
716 fn index(self, slice: &str) -> &Self::Output {
717 if self.last == usize::MAX {
718 str_index_overflow_fail();
719 }
720 self.into_slice_range().index(slice)
721 }
722 #[inline]
723 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
724 if self.last == usize::MAX {
725 str_index_overflow_fail();
726 }
727 self.into_slice_range().index_mut(slice)
728 }
729}
730
731#[stable(feature = "inclusive_range", since = "1.26.0")]
746#[rustc_const_unstable(feature = "const_index", issue = "143775")]
747#[cfg(not(feature = "ferrocene_subset"))]
748unsafe impl const 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 = "rust1", since = "1.0.0")]
848#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
849pub const trait FromStr: Sized {
850 #[stable(feature = "rust1", since = "1.0.0")]
852 type Err;
853
854 #[stable(feature = "rust1", since = "1.0.0")]
873 #[rustc_diagnostic_item = "from_str_method"]
874 fn from_str(s: &str) -> Result<Self, Self::Err>;
875}
876
877#[stable(feature = "rust1", since = "1.0.0")]
878#[cfg(not(feature = "ferrocene_subset"))]
879impl FromStr for bool {
880 type Err = ParseBoolError;
881
882 #[inline]
905 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
906 match s {
907 "true" => Ok(true),
908 "false" => Ok(false),
909 _ => Err(ParseBoolError),
910 }
911 }
912}