]> git.proxmox.com Git - rustc.git/blob - library/core/src/str/traits.rs
New upstream version 1.64.0+dfsg1
[rustc.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 /// use std::num::ParseIntError;
511 ///
512 /// #[derive(Debug, PartialEq)]
513 /// struct Point {
514 /// x: i32,
515 /// y: i32
516 /// }
517 ///
518 /// impl FromStr for Point {
519 /// type Err = ParseIntError;
520 ///
521 /// fn from_str(s: &str) -> Result<Self, Self::Err> {
522 /// let (x, y) = s
523 /// .strip_prefix('(')
524 /// .and_then(|s| s.strip_suffix(')'))
525 /// .and_then(|s| s.split_once(','))
526 /// .unwrap();
527 ///
528 /// let x_fromstr = x.parse::<i32>()?;
529 /// let y_fromstr = y.parse::<i32>()?;
530 ///
531 /// Ok(Point { x: x_fromstr, y: y_fromstr })
532 /// }
533 /// }
534 ///
535 /// let expected = Ok(Point { x: 1, y: 2 });
536 /// // Explicit call
537 /// assert_eq!(Point::from_str("(1,2)"), expected);
538 /// // Implicit calls, through parse
539 /// assert_eq!("(1,2)".parse(), expected);
540 /// assert_eq!("(1,2)".parse::<Point>(), expected);
541 /// ```
542 #[stable(feature = "rust1", since = "1.0.0")]
543 pub trait FromStr: Sized {
544 /// The associated error which can be returned from parsing.
545 #[stable(feature = "rust1", since = "1.0.0")]
546 type Err;
547
548 /// Parses a string `s` to return a value of this type.
549 ///
550 /// If parsing succeeds, return the value inside [`Ok`], otherwise
551 /// when the string is ill-formatted return an error specific to the
552 /// inside [`Err`]. The error type is specific to the implementation of the trait.
553 ///
554 /// # Examples
555 ///
556 /// Basic usage with [`i32`], a type that implements `FromStr`:
557 ///
558 /// ```
559 /// use std::str::FromStr;
560 ///
561 /// let s = "5";
562 /// let x = i32::from_str(s).unwrap();
563 ///
564 /// assert_eq!(5, x);
565 /// ```
566 #[stable(feature = "rust1", since = "1.0.0")]
567 fn from_str(s: &str) -> Result<Self, Self::Err>;
568 }
569
570 #[stable(feature = "rust1", since = "1.0.0")]
571 impl FromStr for bool {
572 type Err = ParseBoolError;
573
574 /// Parse a `bool` from a string.
575 ///
576 /// Yields a `Result<bool, ParseBoolError>`, because `s` may or may not
577 /// actually be parseable.
578 ///
579 /// # Examples
580 ///
581 /// ```
582 /// use std::str::FromStr;
583 ///
584 /// assert_eq!(FromStr::from_str("true"), Ok(true));
585 /// assert_eq!(FromStr::from_str("false"), Ok(false));
586 /// assert!(<bool as FromStr>::from_str("not even a boolean").is_err());
587 /// ```
588 ///
589 /// Note, in many cases, the `.parse()` method on `str` is more proper.
590 ///
591 /// ```
592 /// assert_eq!("true".parse(), Ok(true));
593 /// assert_eq!("false".parse(), Ok(false));
594 /// assert!("not even a boolean".parse::<bool>().is_err());
595 /// ```
596 #[inline]
597 fn from_str(s: &str) -> Result<bool, ParseBoolError> {
598 match s {
599 "true" => Ok(true),
600 "false" => Ok(false),
601 _ => Err(ParseBoolError),
602 }
603 }
604 }