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")]
45#[cfg(not(feature = "ferrocene_subset"))]
46impl const Eq for str {}
47
48#[stable(feature = "rust1", since = "1.0.0")]
56#[cfg(not(feature = "ferrocene_subset"))]
57impl PartialOrd for str {
58 #[inline]
59 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
60 Some(self.cmp(other))
61 }
62}
63
64#[stable(feature = "rust1", since = "1.0.0")]
65#[rustc_const_unstable(feature = "const_index", issue = "143775")]
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_subset"))]
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_subset"))]
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_subset"))]
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")]
179unsafe impl const SliceIndex<str> for ops::Range<usize> {
180 type Output = str;
181 #[inline]
182 fn get(self, slice: &str) -> Option<&Self::Output> {
183 if self.start <= self.end
184 && slice.is_char_boundary(self.start)
185 && slice.is_char_boundary(self.end)
186 {
187 Some(unsafe { &*self.get_unchecked(slice) })
191 } else {
192 None
193 }
194 }
195 #[inline]
196 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
197 if self.start <= self.end
198 && slice.is_char_boundary(self.start)
199 && slice.is_char_boundary(self.end)
200 {
201 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
204 } else {
205 None
206 }
207 }
208 #[inline]
209 #[track_caller]
210 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
211 let slice = slice as *const [u8];
212
213 assert_unsafe_precondition!(
214 check_library_ub,
221 "str::get_unchecked requires that the range is within the string slice",
222 (
223 start: usize = self.start,
224 end: usize = self.end,
225 len: usize = slice.len()
226 ) => end >= start && end <= len,
227 );
228
229 unsafe {
232 let new_len = unchecked_sub(self.end, self.start);
233 ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
234 }
235 }
236 #[inline]
237 #[track_caller]
238 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
239 let slice = slice as *mut [u8];
240
241 assert_unsafe_precondition!(
242 check_library_ub,
243 "str::get_unchecked_mut requires that the range is within the string slice",
244 (
245 start: usize = self.start,
246 end: usize = self.end,
247 len: usize = slice.len()
248 ) => end >= start && end <= len,
249 );
250
251 unsafe {
253 let new_len = unchecked_sub(self.end, self.start);
254 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
255 }
256 }
257 #[inline]
258 fn index(self, slice: &str) -> &Self::Output {
259 let (start, end) = (self.start, self.end);
260 match self.get(slice) {
261 Some(s) => s,
262 None => super::slice_error_fail(slice, start, end),
263 }
264 }
265 #[inline]
266 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
267 if self.start <= self.end
270 && slice.is_char_boundary(self.start)
271 && slice.is_char_boundary(self.end)
272 {
273 unsafe { &mut *self.get_unchecked_mut(slice) }
276 } else {
277 super::slice_error_fail(slice, self.start, self.end)
278 }
279 }
280}
281
282#[unstable(feature = "new_range_api", issue = "125687")]
283#[rustc_const_unstable(feature = "const_index", issue = "143775")]
284#[cfg(not(feature = "ferrocene_subset"))]
285unsafe impl const SliceIndex<str> for range::Range<usize> {
286 type Output = str;
287 #[inline]
288 fn get(self, slice: &str) -> Option<&Self::Output> {
289 if self.start <= self.end
290 && slice.is_char_boundary(self.start)
291 && slice.is_char_boundary(self.end)
292 {
293 Some(unsafe { &*self.get_unchecked(slice) })
297 } else {
298 None
299 }
300 }
301 #[inline]
302 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
303 if self.start <= self.end
304 && slice.is_char_boundary(self.start)
305 && slice.is_char_boundary(self.end)
306 {
307 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
310 } else {
311 None
312 }
313 }
314 #[inline]
315 #[track_caller]
316 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
317 let slice = slice as *const [u8];
318
319 assert_unsafe_precondition!(
320 check_library_ub,
327 "str::get_unchecked requires that the range is within the string slice",
328 (
329 start: usize = self.start,
330 end: usize = self.end,
331 len: usize = slice.len()
332 ) => end >= start && end <= len,
333 );
334
335 unsafe {
338 let new_len = unchecked_sub(self.end, self.start);
339 ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
340 }
341 }
342 #[inline]
343 #[track_caller]
344 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
345 let slice = slice as *mut [u8];
346
347 assert_unsafe_precondition!(
348 check_library_ub,
349 "str::get_unchecked_mut requires that the range is within the string slice",
350 (
351 start: usize = self.start,
352 end: usize = self.end,
353 len: usize = slice.len()
354 ) => end >= start && end <= len,
355 );
356
357 unsafe {
359 let new_len = unchecked_sub(self.end, self.start);
360 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
361 }
362 }
363 #[inline]
364 fn index(self, slice: &str) -> &Self::Output {
365 let (start, end) = (self.start, self.end);
366 match self.get(slice) {
367 Some(s) => s,
368 None => super::slice_error_fail(slice, start, end),
369 }
370 }
371 #[inline]
372 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
373 if self.start <= self.end
376 && slice.is_char_boundary(self.start)
377 && slice.is_char_boundary(self.end)
378 {
379 unsafe { &mut *self.get_unchecked_mut(slice) }
382 } else {
383 super::slice_error_fail(slice, self.start, self.end)
384 }
385 }
386}
387
388#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")]
402#[cfg(not(feature = "ferrocene_subset"))]
403unsafe impl SliceIndex<str> for (ops::Bound<usize>, ops::Bound<usize>) {
404 type Output = str;
405
406 #[inline]
407 fn get(self, slice: &str) -> Option<&str> {
408 crate::slice::index::into_range(slice.len(), self)?.get(slice)
409 }
410
411 #[inline]
412 fn get_mut(self, slice: &mut str) -> Option<&mut str> {
413 crate::slice::index::into_range(slice.len(), self)?.get_mut(slice)
414 }
415
416 #[inline]
417 unsafe fn get_unchecked(self, slice: *const str) -> *const str {
418 let len = (slice as *const [u8]).len();
419 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked(slice) }
421 }
422
423 #[inline]
424 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str {
425 let len = (slice as *mut [u8]).len();
426 unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked_mut(slice) }
428 }
429
430 #[inline]
431 fn index(self, slice: &str) -> &str {
432 crate::slice::index::into_slice_range(slice.len(), self).index(slice)
433 }
434
435 #[inline]
436 fn index_mut(self, slice: &mut str) -> &mut str {
437 crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice)
438 }
439}
440
441#[stable(feature = "str_checked_slicing", since = "1.20.0")]
457#[rustc_const_unstable(feature = "const_index", issue = "143775")]
458unsafe impl const SliceIndex<str> for ops::RangeTo<usize> {
459 type Output = str;
460 #[inline]
461 fn get(self, slice: &str) -> Option<&Self::Output> {
462 if slice.is_char_boundary(self.end) {
463 Some(unsafe { &*self.get_unchecked(slice) })
466 } else {
467 None
468 }
469 }
470 #[inline]
471 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
472 if slice.is_char_boundary(self.end) {
473 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
476 } else {
477 None
478 }
479 }
480 #[inline]
481 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
482 unsafe { (0..self.end).get_unchecked(slice) }
484 }
485 #[inline]
486 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
487 unsafe { (0..self.end).get_unchecked_mut(slice) }
489 }
490 #[inline]
491 fn index(self, slice: &str) -> &Self::Output {
492 let end = self.end;
493 match self.get(slice) {
494 Some(s) => s,
495 None => super::slice_error_fail(slice, 0, end),
496 }
497 }
498 #[inline]
499 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
500 if slice.is_char_boundary(self.end) {
501 unsafe { &mut *self.get_unchecked_mut(slice) }
504 } else {
505 super::slice_error_fail(slice, 0, self.end)
506 }
507 }
508}
509
510#[stable(feature = "str_checked_slicing", since = "1.20.0")]
526#[rustc_const_unstable(feature = "const_index", issue = "143775")]
527unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
528 type Output = str;
529 #[inline]
530 fn get(self, slice: &str) -> Option<&Self::Output> {
531 if slice.is_char_boundary(self.start) {
532 Some(unsafe { &*self.get_unchecked(slice) })
535 } else {
536 None
537 }
538 }
539 #[inline]
540 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
541 if slice.is_char_boundary(self.start) {
542 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
545 } else {
546 None
547 }
548 }
549 #[inline]
550 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
551 let len = (slice as *const [u8]).len();
552 unsafe { (self.start..len).get_unchecked(slice) }
554 }
555 #[inline]
556 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
557 let len = (slice as *mut [u8]).len();
558 unsafe { (self.start..len).get_unchecked_mut(slice) }
560 }
561 #[inline]
562 fn index(self, slice: &str) -> &Self::Output {
563 let (start, end) = (self.start, slice.len());
564 match self.get(slice) {
565 Some(s) => s,
566 None => super::slice_error_fail(slice, start, end),
567 }
568 }
569 #[inline]
570 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
571 if slice.is_char_boundary(self.start) {
572 unsafe { &mut *self.get_unchecked_mut(slice) }
575 } else {
576 super::slice_error_fail(slice, self.start, slice.len())
577 }
578 }
579}
580
581#[unstable(feature = "new_range_api", issue = "125687")]
582#[rustc_const_unstable(feature = "const_index", issue = "143775")]
583#[cfg(not(feature = "ferrocene_subset"))]
584unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
585 type Output = str;
586 #[inline]
587 fn get(self, slice: &str) -> Option<&Self::Output> {
588 if slice.is_char_boundary(self.start) {
589 Some(unsafe { &*self.get_unchecked(slice) })
592 } else {
593 None
594 }
595 }
596 #[inline]
597 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
598 if slice.is_char_boundary(self.start) {
599 Some(unsafe { &mut *self.get_unchecked_mut(slice) })
602 } else {
603 None
604 }
605 }
606 #[inline]
607 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
608 let len = (slice as *const [u8]).len();
609 unsafe { (self.start..len).get_unchecked(slice) }
611 }
612 #[inline]
613 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
614 let len = (slice as *mut [u8]).len();
615 unsafe { (self.start..len).get_unchecked_mut(slice) }
617 }
618 #[inline]
619 fn index(self, slice: &str) -> &Self::Output {
620 let (start, end) = (self.start, slice.len());
621 match self.get(slice) {
622 Some(s) => s,
623 None => super::slice_error_fail(slice, start, end),
624 }
625 }
626 #[inline]
627 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
628 if slice.is_char_boundary(self.start) {
629 unsafe { &mut *self.get_unchecked_mut(slice) }
632 } else {
633 super::slice_error_fail(slice, self.start, slice.len())
634 }
635 }
636}
637
638#[stable(feature = "inclusive_range", since = "1.26.0")]
655#[rustc_const_unstable(feature = "const_index", issue = "143775")]
656#[cfg(not(feature = "ferrocene_subset"))]
657unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
658 type Output = str;
659 #[inline]
660 fn get(self, slice: &str) -> Option<&Self::Output> {
661 if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
662 }
663 #[inline]
664 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
665 if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
666 }
667 #[inline]
668 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
669 unsafe { self.into_slice_range().get_unchecked(slice) }
671 }
672 #[inline]
673 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
674 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
676 }
677 #[inline]
678 fn index(self, slice: &str) -> &Self::Output {
679 if *self.end() == usize::MAX {
680 str_index_overflow_fail();
681 }
682 self.into_slice_range().index(slice)
683 }
684 #[inline]
685 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
686 if *self.end() == usize::MAX {
687 str_index_overflow_fail();
688 }
689 self.into_slice_range().index_mut(slice)
690 }
691}
692
693#[unstable(feature = "new_range_api", issue = "125687")]
694#[rustc_const_unstable(feature = "const_index", issue = "143775")]
695#[cfg(not(feature = "ferrocene_subset"))]
696unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
697 type Output = str;
698 #[inline]
699 fn get(self, slice: &str) -> Option<&Self::Output> {
700 if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) }
701 }
702 #[inline]
703 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
704 if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
705 }
706 #[inline]
707 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
708 unsafe { self.into_slice_range().get_unchecked(slice) }
710 }
711 #[inline]
712 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
713 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
715 }
716 #[inline]
717 fn index(self, slice: &str) -> &Self::Output {
718 if self.last == usize::MAX {
719 str_index_overflow_fail();
720 }
721 self.into_slice_range().index(slice)
722 }
723 #[inline]
724 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
725 if self.last == usize::MAX {
726 str_index_overflow_fail();
727 }
728 self.into_slice_range().index_mut(slice)
729 }
730}
731
732#[stable(feature = "inclusive_range", since = "1.26.0")]
747#[rustc_const_unstable(feature = "const_index", issue = "143775")]
748#[cfg(not(feature = "ferrocene_subset"))]
749unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
750 type Output = str;
751 #[inline]
752 fn get(self, slice: &str) -> Option<&Self::Output> {
753 (0..=self.end).get(slice)
754 }
755 #[inline]
756 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
757 (0..=self.end).get_mut(slice)
758 }
759 #[inline]
760 unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
761 unsafe { (0..=self.end).get_unchecked(slice) }
763 }
764 #[inline]
765 unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
766 unsafe { (0..=self.end).get_unchecked_mut(slice) }
768 }
769 #[inline]
770 fn index(self, slice: &str) -> &Self::Output {
771 (0..=self.end).index(slice)
772 }
773 #[inline]
774 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
775 (0..=self.end).index_mut(slice)
776 }
777}
778
779#[stable(feature = "rust1", since = "1.0.0")]
849#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
850pub const trait FromStr: Sized {
851 #[stable(feature = "rust1", since = "1.0.0")]
853 type Err;
854
855 #[stable(feature = "rust1", since = "1.0.0")]
874 #[rustc_diagnostic_item = "from_str_method"]
875 fn from_str(s: &str) -> Result<Self, Self::Err>;
876}
877
878#[stable(feature = "rust1", since = "1.0.0")]
879#[cfg(not(feature = "ferrocene_subset"))]
880impl FromStr for bool {
881 type Err = ParseBoolError;
882
883 #[inline]
906 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
907 match s {
908 "true" => Ok(true),
909 "false" => Ok(false),
910 _ => Err(ParseBoolError),
911 }
912 }
913}