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