]> git.lizzy.rs Git - rust.git/blob - library/core/src/str/traits.rs
Rollup merge of #88858 - spektom:to_lower_upper_rev, r=dtolnay
[rust.git] / library / core / src / str / traits.rs
1 //! Trait implementations for `str`.
2
3 use crate::cmp::Ordering;
4 use crate::ops;
5 use crate::ptr;
6 use crate::slice::SliceIndex;
7
8 use super::ParseBoolError;
9
10 /// Implements ordering of strings.
11 ///
12 /// Strings are ordered  [lexicographically](Ord#lexicographical-comparison) by their byte values. This orders Unicode code
13 /// points based on their positions in the code charts. This is not necessarily the same as
14 /// "alphabetical" order, which varies by language and locale. Sorting strings according to
15 /// culturally-accepted standards requires locale-specific data that is outside the scope of
16 /// the `str` type.
17 #[stable(feature = "rust1", since = "1.0.0")]
18 impl 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 impl PartialEq for str {
27     #[inline]
28     fn eq(&self, other: &str) -> bool {
29         self.as_bytes() == other.as_bytes()
30     }
31     #[inline]
32     fn ne(&self, other: &str) -> bool {
33         !(*self).eq(other)
34     }
35 }
36
37 #[stable(feature = "rust1", since = "1.0.0")]
38 impl Eq for str {}
39
40 /// Implements comparison operations on strings.
41 ///
42 /// Strings are compared [lexicographically](Ord#lexicographical-comparison) by their byte values. This compares Unicode code
43 /// points based on their positions in the code charts. This is not necessarily the same as
44 /// "alphabetical" order, which varies by language and locale. Comparing strings according to
45 /// culturally-accepted standards requires locale-specific data that is outside the scope of
46 /// the `str` type.
47 #[stable(feature = "rust1", since = "1.0.0")]
48 impl PartialOrd for str {
49     #[inline]
50     fn partial_cmp(&self, other: &str) -> Option<Ordering> {
51         Some(self.cmp(other))
52     }
53 }
54
55 #[stable(feature = "rust1", since = "1.0.0")]
56 impl<I> ops::Index<I> for str
57 where
58     I: SliceIndex<str>,
59 {
60     type Output = I::Output;
61
62     #[inline]
63     fn index(&self, index: I) -> &I::Output {
64         index.index(self)
65     }
66 }
67
68 #[stable(feature = "rust1", since = "1.0.0")]
69 impl<I> ops::IndexMut<I> for str
70 where
71     I: SliceIndex<str>,
72 {
73     #[inline]
74     fn index_mut(&mut self, index: I) -> &mut I::Output {
75         index.index_mut(self)
76     }
77 }
78
79 #[inline(never)]
80 #[cold]
81 #[track_caller]
82 fn str_index_overflow_fail() -> ! {
83     panic!("attempted to index str up to maximum usize");
84 }
85
86 /// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`.
87 ///
88 /// Returns a slice of the whole string, i.e., returns `&self` or `&mut
89 /// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike
90 /// other indexing operations, this can never panic.
91 ///
92 /// This operation is *O*(1).
93 ///
94 /// Prior to 1.20.0, these indexing operations were still supported by
95 /// direct implementation of `Index` and `IndexMut`.
96 ///
97 /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`.
98 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
99 unsafe impl SliceIndex<str> for ops::RangeFull {
100     type Output = str;
101     #[inline]
102     fn get(self, slice: &str) -> Option<&Self::Output> {
103         Some(slice)
104     }
105     #[inline]
106     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
107         Some(slice)
108     }
109     #[inline]
110     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
111         slice
112     }
113     #[inline]
114     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
115         slice
116     }
117     #[inline]
118     fn index(self, slice: &str) -> &Self::Output {
119         slice
120     }
121     #[inline]
122     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
123         slice
124     }
125 }
126
127 /// Implements substring slicing with syntax `&self[begin .. end]` or `&mut
128 /// self[begin .. end]`.
129 ///
130 /// Returns a slice of the given string from the byte range
131 /// [`begin`, `end`).
132 ///
133 /// This operation is *O*(1).
134 ///
135 /// Prior to 1.20.0, these indexing operations were still supported by
136 /// direct implementation of `Index` and `IndexMut`.
137 ///
138 /// # Panics
139 ///
140 /// Panics if `begin` or `end` does not point to the starting byte offset of
141 /// a character (as defined by `is_char_boundary`), if `begin > end`, or if
142 /// `end > len`.
143 ///
144 /// # Examples
145 ///
146 /// ```
147 /// let s = "Löwe 老虎 Léopard";
148 /// assert_eq!(&s[0 .. 1], "L");
149 ///
150 /// assert_eq!(&s[1 .. 9], "öwe 老");
151 ///
152 /// // these will panic:
153 /// // byte 2 lies within `ö`:
154 /// // &s[2 ..3];
155 ///
156 /// // byte 8 lies within `老`
157 /// // &s[1 .. 8];
158 ///
159 /// // byte 100 is outside the string
160 /// // &s[3 .. 100];
161 /// ```
162 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
163 unsafe impl SliceIndex<str> for ops::Range<usize> {
164     type Output = str;
165     #[inline]
166     fn get(self, slice: &str) -> Option<&Self::Output> {
167         if self.start <= self.end
168             && slice.is_char_boundary(self.start)
169             && slice.is_char_boundary(self.end)
170         {
171             // SAFETY: just checked that `start` and `end` are on a char boundary,
172             // and we are passing in a safe reference, so the return value will also be one.
173             // We also checked char boundaries, so this is valid UTF-8.
174             Some(unsafe { &*self.get_unchecked(slice) })
175         } else {
176             None
177         }
178     }
179     #[inline]
180     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
181         if self.start <= self.end
182             && slice.is_char_boundary(self.start)
183             && slice.is_char_boundary(self.end)
184         {
185             // SAFETY: just checked that `start` and `end` are on a char boundary.
186             // We know the pointer is unique because we got it from `slice`.
187             Some(unsafe { &mut *self.get_unchecked_mut(slice) })
188         } else {
189             None
190         }
191     }
192     #[inline]
193     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
194         let slice = slice as *const [u8];
195         // SAFETY: the caller guarantees that `self` is in bounds of `slice`
196         // which satisfies all the conditions for `add`.
197         let ptr = unsafe { slice.as_ptr().add(self.start) };
198         let len = self.end - self.start;
199         ptr::slice_from_raw_parts(ptr, len) as *const str
200     }
201     #[inline]
202     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
203         let slice = slice as *mut [u8];
204         // SAFETY: see comments for `get_unchecked`.
205         let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
206         let len = self.end - self.start;
207         ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
208     }
209     #[inline]
210     fn index(self, slice: &str) -> &Self::Output {
211         let (start, end) = (self.start, self.end);
212         match self.get(slice) {
213             Some(s) => s,
214             None => super::slice_error_fail(slice, start, end),
215         }
216     }
217     #[inline]
218     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
219         // is_char_boundary checks that the index is in [0, .len()]
220         // cannot reuse `get` as above, because of NLL trouble
221         if self.start <= self.end
222             && slice.is_char_boundary(self.start)
223             && slice.is_char_boundary(self.end)
224         {
225             // SAFETY: just checked that `start` and `end` are on a char boundary,
226             // and we are passing in a safe reference, so the return value will also be one.
227             unsafe { &mut *self.get_unchecked_mut(slice) }
228         } else {
229             super::slice_error_fail(slice, self.start, self.end)
230         }
231     }
232 }
233
234 /// Implements substring slicing with syntax `&self[.. end]` or `&mut
235 /// self[.. end]`.
236 ///
237 /// Returns a slice of the given string from the byte range \[0, `end`).
238 /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
239 ///
240 /// This operation is *O*(1).
241 ///
242 /// Prior to 1.20.0, these indexing operations were still supported by
243 /// direct implementation of `Index` and `IndexMut`.
244 ///
245 /// # Panics
246 ///
247 /// Panics if `end` does not point to the starting byte offset of a
248 /// character (as defined by `is_char_boundary`), or if `end > len`.
249 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
250 unsafe impl SliceIndex<str> for ops::RangeTo<usize> {
251     type Output = str;
252     #[inline]
253     fn get(self, slice: &str) -> Option<&Self::Output> {
254         if slice.is_char_boundary(self.end) {
255             // SAFETY: just checked that `end` is on a char boundary,
256             // and we are passing in a safe reference, so the return value will also be one.
257             Some(unsafe { &*self.get_unchecked(slice) })
258         } else {
259             None
260         }
261     }
262     #[inline]
263     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
264         if slice.is_char_boundary(self.end) {
265             // SAFETY: just checked that `end` is on a char boundary,
266             // and we are passing in a safe reference, so the return value will also be one.
267             Some(unsafe { &mut *self.get_unchecked_mut(slice) })
268         } else {
269             None
270         }
271     }
272     #[inline]
273     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
274         let slice = slice as *const [u8];
275         let ptr = slice.as_ptr();
276         ptr::slice_from_raw_parts(ptr, self.end) as *const str
277     }
278     #[inline]
279     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
280         let slice = slice as *mut [u8];
281         let ptr = slice.as_mut_ptr();
282         ptr::slice_from_raw_parts_mut(ptr, self.end) as *mut str
283     }
284     #[inline]
285     fn index(self, slice: &str) -> &Self::Output {
286         let end = self.end;
287         match self.get(slice) {
288             Some(s) => s,
289             None => super::slice_error_fail(slice, 0, end),
290         }
291     }
292     #[inline]
293     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
294         if slice.is_char_boundary(self.end) {
295             // SAFETY: just checked that `end` is on a char boundary,
296             // and we are passing in a safe reference, so the return value will also be one.
297             unsafe { &mut *self.get_unchecked_mut(slice) }
298         } else {
299             super::slice_error_fail(slice, 0, self.end)
300         }
301     }
302 }
303
304 /// Implements substring slicing with syntax `&self[begin ..]` or `&mut
305 /// self[begin ..]`.
306 ///
307 /// Returns a slice of the given string from the byte range \[`begin`, `len`).
308 /// Equivalent to `&self[begin .. len]` or `&mut self[begin .. len]`.
309 ///
310 /// This operation is *O*(1).
311 ///
312 /// Prior to 1.20.0, these indexing operations were still supported by
313 /// direct implementation of `Index` and `IndexMut`.
314 ///
315 /// # Panics
316 ///
317 /// Panics if `begin` does not point to the starting byte offset of
318 /// a character (as defined by `is_char_boundary`), or if `begin > len`.
319 #[stable(feature = "str_checked_slicing", since = "1.20.0")]
320 unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
321     type Output = str;
322     #[inline]
323     fn get(self, slice: &str) -> Option<&Self::Output> {
324         if slice.is_char_boundary(self.start) {
325             // SAFETY: just checked that `start` is on a char boundary,
326             // and we are passing in a safe reference, so the return value will also be one.
327             Some(unsafe { &*self.get_unchecked(slice) })
328         } else {
329             None
330         }
331     }
332     #[inline]
333     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
334         if slice.is_char_boundary(self.start) {
335             // SAFETY: just checked that `start` is on a char boundary,
336             // and we are passing in a safe reference, so the return value will also be one.
337             Some(unsafe { &mut *self.get_unchecked_mut(slice) })
338         } else {
339             None
340         }
341     }
342     #[inline]
343     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
344         let slice = slice as *const [u8];
345         // SAFETY: the caller guarantees that `self` is in bounds of `slice`
346         // which satisfies all the conditions for `add`.
347         let ptr = unsafe { slice.as_ptr().add(self.start) };
348         let len = slice.len() - self.start;
349         ptr::slice_from_raw_parts(ptr, len) as *const str
350     }
351     #[inline]
352     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
353         let slice = slice as *mut [u8];
354         // SAFETY: identical to `get_unchecked`.
355         let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
356         let len = slice.len() - self.start;
357         ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
358     }
359     #[inline]
360     fn index(self, slice: &str) -> &Self::Output {
361         let (start, end) = (self.start, slice.len());
362         match self.get(slice) {
363             Some(s) => s,
364             None => super::slice_error_fail(slice, start, end),
365         }
366     }
367     #[inline]
368     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
369         if slice.is_char_boundary(self.start) {
370             // SAFETY: just checked that `start` is on a char boundary,
371             // and we are passing in a safe reference, so the return value will also be one.
372             unsafe { &mut *self.get_unchecked_mut(slice) }
373         } else {
374             super::slice_error_fail(slice, self.start, slice.len())
375         }
376     }
377 }
378
379 /// Implements substring slicing with syntax `&self[begin ..= end]` or `&mut
380 /// self[begin ..= end]`.
381 ///
382 /// Returns a slice of the given string from the byte range
383 /// [`begin`, `end`]. Equivalent to `&self [begin .. end + 1]` or `&mut
384 /// self[begin .. end + 1]`, except if `end` has the maximum value for
385 /// `usize`.
386 ///
387 /// This operation is *O*(1).
388 ///
389 /// # Panics
390 ///
391 /// Panics if `begin` does not point to the starting byte offset of
392 /// a character (as defined by `is_char_boundary`), if `end` does not point
393 /// to the ending byte offset of a character (`end + 1` is either a starting
394 /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`.
395 #[stable(feature = "inclusive_range", since = "1.26.0")]
396 unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
397     type Output = str;
398     #[inline]
399     fn get(self, slice: &str) -> Option<&Self::Output> {
400         if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
401     }
402     #[inline]
403     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
404         if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
405     }
406     #[inline]
407     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
408         // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
409         unsafe { self.into_slice_range().get_unchecked(slice) }
410     }
411     #[inline]
412     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
413         // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
414         unsafe { self.into_slice_range().get_unchecked_mut(slice) }
415     }
416     #[inline]
417     fn index(self, slice: &str) -> &Self::Output {
418         if *self.end() == usize::MAX {
419             str_index_overflow_fail();
420         }
421         self.into_slice_range().index(slice)
422     }
423     #[inline]
424     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
425         if *self.end() == usize::MAX {
426             str_index_overflow_fail();
427         }
428         self.into_slice_range().index_mut(slice)
429     }
430 }
431
432 /// Implements substring slicing with syntax `&self[..= end]` or `&mut
433 /// self[..= end]`.
434 ///
435 /// Returns a slice of the given string from the byte range \[0, `end`\].
436 /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
437 /// value for `usize`.
438 ///
439 /// This operation is *O*(1).
440 ///
441 /// # Panics
442 ///
443 /// Panics if `end` does not point to the ending byte offset of a character
444 /// (`end + 1` is either a starting byte offset as defined by
445 /// `is_char_boundary`, or equal to `len`), or if `end >= len`.
446 #[stable(feature = "inclusive_range", since = "1.26.0")]
447 unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> {
448     type Output = str;
449     #[inline]
450     fn get(self, slice: &str) -> Option<&Self::Output> {
451         if self.end == usize::MAX { None } else { (..self.end + 1).get(slice) }
452     }
453     #[inline]
454     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
455         if self.end == usize::MAX { None } else { (..self.end + 1).get_mut(slice) }
456     }
457     #[inline]
458     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
459         // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
460         unsafe { (..self.end + 1).get_unchecked(slice) }
461     }
462     #[inline]
463     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
464         // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
465         unsafe { (..self.end + 1).get_unchecked_mut(slice) }
466     }
467     #[inline]
468     fn index(self, slice: &str) -> &Self::Output {
469         if self.end == usize::MAX {
470             str_index_overflow_fail();
471         }
472         (..self.end + 1).index(slice)
473     }
474     #[inline]
475     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
476         if self.end == usize::MAX {
477             str_index_overflow_fail();
478         }
479         (..self.end + 1).index_mut(slice)
480     }
481 }
482
483 /// Parse a value from a string
484 ///
485 /// `FromStr`'s [`from_str`] method is often used implicitly, through
486 /// [`str`]'s [`parse`] method. See [`parse`]'s documentation for examples.
487 ///
488 /// [`from_str`]: FromStr::from_str
489 /// [`parse`]: str::parse
490 ///
491 /// `FromStr` does not have a lifetime parameter, and so you can only parse types
492 /// that do not contain a lifetime parameter themselves. In other words, you can
493 /// parse an `i32` with `FromStr`, but not a `&i32`. You can parse a struct that
494 /// contains an `i32`, but not one that contains an `&i32`.
495 ///
496 /// # Examples
497 ///
498 /// Basic implementation of `FromStr` on an example `Point` type:
499 ///
500 /// ```
501 /// use std::str::FromStr;
502 /// use std::num::ParseIntError;
503 ///
504 /// #[derive(Debug, PartialEq)]
505 /// struct Point {
506 ///     x: i32,
507 ///     y: i32
508 /// }
509 ///
510 /// impl FromStr for Point {
511 ///     type Err = ParseIntError;
512 ///
513 ///     fn from_str(s: &str) -> Result<Self, Self::Err> {
514 ///         let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' )
515 ///                                  .split(',')
516 ///                                  .collect();
517 ///
518 ///         let x_fromstr = coords[0].parse::<i32>()?;
519 ///         let y_fromstr = coords[1].parse::<i32>()?;
520 ///
521 ///         Ok(Point { x: x_fromstr, y: y_fromstr })
522 ///     }
523 /// }
524 ///
525 /// let p = Point::from_str("(1,2)");
526 /// assert_eq!(p.unwrap(), Point{ x: 1, y: 2} )
527 /// ```
528 #[stable(feature = "rust1", since = "1.0.0")]
529 pub trait FromStr: Sized {
530     /// The associated error which can be returned from parsing.
531     #[stable(feature = "rust1", since = "1.0.0")]
532     type Err;
533
534     /// Parses a string `s` to return a value of this type.
535     ///
536     /// If parsing succeeds, return the value inside [`Ok`], otherwise
537     /// when the string is ill-formatted return an error specific to the
538     /// inside [`Err`]. The error type is specific to the implementation of the trait.
539     ///
540     /// # Examples
541     ///
542     /// Basic usage with [`i32`], a type that implements `FromStr`:
543     ///
544     /// ```
545     /// use std::str::FromStr;
546     ///
547     /// let s = "5";
548     /// let x = i32::from_str(s).unwrap();
549     ///
550     /// assert_eq!(5, x);
551     /// ```
552     #[stable(feature = "rust1", since = "1.0.0")]
553     fn from_str(s: &str) -> Result<Self, Self::Err>;
554 }
555
556 #[stable(feature = "rust1", since = "1.0.0")]
557 impl FromStr for bool {
558     type Err = ParseBoolError;
559
560     /// Parse a `bool` from a string.
561     ///
562     /// Yields a `Result<bool, ParseBoolError>`, because `s` may or may not
563     /// actually be parseable.
564     ///
565     /// # Examples
566     ///
567     /// ```
568     /// use std::str::FromStr;
569     ///
570     /// assert_eq!(FromStr::from_str("true"), Ok(true));
571     /// assert_eq!(FromStr::from_str("false"), Ok(false));
572     /// assert!(<bool as FromStr>::from_str("not even a boolean").is_err());
573     /// ```
574     ///
575     /// Note, in many cases, the `.parse()` method on `str` is more proper.
576     ///
577     /// ```
578     /// assert_eq!("true".parse(), Ok(true));
579     /// assert_eq!("false".parse(), Ok(false));
580     /// assert!("not even a boolean".parse::<bool>().is_err());
581     /// ```
582     #[inline]
583     fn from_str(s: &str) -> Result<bool, ParseBoolError> {
584         match s {
585             "true" => Ok(true),
586             "false" => Ok(false),
587             _ => Err(ParseBoolError),
588         }
589     }
590 }