diff options
Diffstat (limited to 'src/libcore/str')
| -rw-r--r-- | src/libcore/str/mod.rs | 142 |
1 files changed, 98 insertions, 44 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 37f643db54e..92c5de937cc 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -20,8 +20,10 @@ use self::Searcher::{Naive, TwoWay, TwoWayLong}; use cmp::{self, Eq}; use default::Default; -use iter::range; +use error::Error; +use fmt; use iter::ExactSizeIterator; +use iter::range; use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator}; use marker::Sized; use mem; @@ -247,6 +249,30 @@ impl<'a> CharEq for &'a [char] { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for Utf8Error { + fn description(&self) -> &str { + match *self { + Utf8Error::TooShort => "invalid utf-8: not enough bytes", + Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Utf8Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Utf8Error::InvalidByte(n) => { + write!(f, "invalid utf-8: invalid byte at index {}", n) + } + Utf8Error::TooShort => { + write!(f, "invalid utf-8: byte slice too short") + } + } + } +} + /* Section: Iterators */ @@ -907,13 +933,13 @@ impl<'a> Iterator for SplitStr<'a> { match self.it.next() { Some((from, to)) => { - let ret = Some(self.it.haystack.slice(self.last_end, from)); + let ret = Some(&self.it.haystack[self.last_end .. from]); self.last_end = to; ret } None => { self.finished = true; - Some(self.it.haystack.slice(self.last_end, self.it.haystack.len())) + Some(&self.it.haystack[self.last_end .. self.it.haystack.len()]) } } } @@ -1121,27 +1147,90 @@ mod traits { } } + /// Returns a slice of the given string from the byte range + /// [`begin`..`end`). + /// + /// This operation is `O(1)`. + /// + /// Panics when `begin` and `end` do not point to valid characters + /// or point beyond the last character of the string. + /// + /// # Example + /// + /// ```rust + /// let s = "Löwe 老虎 Léopard"; + /// assert_eq!(&s[0 .. 1], "L"); + /// + /// assert_eq!(&s[1 .. 9], "öwe 老"); + /// + /// // these will panic: + /// // byte 2 lies within `ö`: + /// // &s[2 ..3]; + /// + /// // byte 8 lies within `老` + /// // &s[1 .. 8]; + /// + /// // byte 100 is outside the string + /// // &s[3 .. 100]; + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index<ops::Range<uint>> for str { type Output = str; #[inline] fn index(&self, index: &ops::Range<uint>) -> &str { - self.slice(index.start, index.end) + // is_char_boundary checks that the index is in [0, .len()] + if index.start <= index.end && + self.is_char_boundary(index.start) && + self.is_char_boundary(index.end) { + unsafe { self.slice_unchecked(index.start, index.end) } + } else { + super::slice_error_fail(self, index.start, index.end) + } } } + + /// Returns a slice of the string from the beginning to byte + /// `end`. + /// + /// Equivalent to `self[0 .. end]`. + /// + /// Panics when `end` does not point to a valid character, or is + /// out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index<ops::RangeTo<uint>> for str { type Output = str; #[inline] fn index(&self, index: &ops::RangeTo<uint>) -> &str { - self.slice_to(index.end) + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(index.end) { + unsafe { self.slice_unchecked(0, index.end) } + } else { + super::slice_error_fail(self, 0, index.end) + } } } + + /// Returns a slice of the string from `begin` to its end. + /// + /// Equivalent to `self[begin .. self.len()]`. + /// + /// Panics when `begin` does not point to a valid character, or is + /// out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index<ops::RangeFrom<uint>> for str { type Output = str; #[inline] fn index(&self, index: &ops::RangeFrom<uint>) -> &str { - self.slice_from(index.start) + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(index.start) { + unsafe { self.slice_unchecked(index.start, self.len()) } + } else { + super::slice_error_fail(self, index.start, self.len()) + } } } + + #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index<ops::FullRange> for str { type Output = str; #[inline] @@ -1154,7 +1243,7 @@ mod traits { /// Any string that can be represented as a slice #[unstable(feature = "core", reason = "Instead of taking this bound generically, this trait will be \ - replaced with one of slicing syntax, deref coercions, or \ + replaced with one of slicing syntax (&foo[]), deref coercions, or \ a more generic conversion trait")] pub trait Str { /// Work with `self` as a slice. @@ -1216,9 +1305,6 @@ pub trait StrExt { fn lines<'a>(&'a self) -> Lines<'a>; fn lines_any<'a>(&'a self) -> LinesAny<'a>; fn char_len(&self) -> uint; - fn slice<'a>(&'a self, begin: uint, end: uint) -> &'a str; - fn slice_from<'a>(&'a self, begin: uint) -> &'a str; - fn slice_to<'a>(&'a self, end: uint) -> &'a str; fn slice_chars<'a>(&'a self, begin: uint, end: uint) -> &'a str; unsafe fn slice_unchecked<'a>(&'a self, begin: uint, end: uint) -> &'a str; fn starts_with(&self, pat: &str) -> bool; @@ -1340,7 +1426,7 @@ impl StrExt for str { fn lines_any(&self) -> LinesAny { fn f(line: &str) -> &str { let l = line.len(); - if l > 0 && line.as_bytes()[l - 1] == b'\r' { line.slice(0, l - 1) } + if l > 0 && line.as_bytes()[l - 1] == b'\r' { &line[0 .. l - 1] } else { line } } @@ -1351,38 +1437,6 @@ impl StrExt for str { #[inline] fn char_len(&self) -> uint { self.chars().count() } - #[inline] - fn slice(&self, begin: uint, end: uint) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if begin <= end && - self.is_char_boundary(begin) && - self.is_char_boundary(end) { - unsafe { self.slice_unchecked(begin, end) } - } else { - slice_error_fail(self, begin, end) - } - } - - #[inline] - fn slice_from(&self, begin: uint) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(begin) { - unsafe { self.slice_unchecked(begin, self.len()) } - } else { - slice_error_fail(self, begin, self.len()) - } - } - - #[inline] - fn slice_to(&self, end: uint) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(end) { - unsafe { self.slice_unchecked(0, end) } - } else { - slice_error_fail(self, 0, end) - } - } - fn slice_chars(&self, begin: uint, end: uint) -> &str { assert!(begin <= end); let mut count = 0; @@ -1423,7 +1477,7 @@ impl StrExt for str { #[inline] fn ends_with(&self, needle: &str) -> bool { let (m, n) = (self.len(), needle.len()); - m >= n && needle.as_bytes() == &self.as_bytes()[(m-n)..] + m >= n && needle.as_bytes() == &self.as_bytes()[m-n..] } #[inline] |
