1
Fork 0

change return type of slice_shift_char

`slice_shift_char` splits a `str` into it's leading `char` and the remainder
of the `str`. Currently, it returns a `(Option<char>, &str)` such that:

    "bar".slice_shift_char() => (Some('b'), "ar")
    "ar".slice_shift_char()  => (Some('a'), "r")
    "r".slice_shift_char()   => (Some('r'), "")
    "".slice_shift_char()    => (None,      "")

This is a little odd. Either a `str` can be split into both a head and a
tail or it cannot. So the return type should be `Option<(char, &str)>`.
With the current behaviour, in the case of the empty string, the `str`
returned is meaningless - it is always the empty string.

This commit changes slice_shift_char so that:

    "bar".slice_shift_char() => Some(('b', "ar"))
    "ar".slice_shift_char()  => Some(('a', "r"))
    "r".slice_shift_char()   => Some(('r', ""))
    "".slice_shift_char()    => None

[breaking-change]
This commit is contained in:
Andrew Cann 2014-11-17 17:35:18 +08:00
parent 803aacd5ae
commit 197a0ac481
5 changed files with 25 additions and 25 deletions

View file

@ -1254,13 +1254,13 @@ mod tests {
#[test] #[test]
fn test_slice_shift_char() { fn test_slice_shift_char() {
let data = "ประเทศไทย中"; let data = "ประเทศไทย中";
assert_eq!(data.slice_shift_char(), (Some('ป'), "ระเทศไทย中")); assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中")));
} }
#[test] #[test]
fn test_slice_shift_char_2() { fn test_slice_shift_char_2() {
let empty = ""; let empty = "";
assert_eq!(empty.slice_shift_char(), (None, "")); assert_eq!(empty.slice_shift_char(), None);
} }
#[test] #[test]

View file

@ -1455,10 +1455,10 @@ macro_rules! from_str_radix_float_impl {
} }
let (is_positive, src) = match src.slice_shift_char() { let (is_positive, src) = match src.slice_shift_char() {
(None, _) => return None, None => return None,
(Some('-'), "") => return None, Some(('-', "")) => return None,
(Some('-'), src) => (false, src), Some(('-', src)) => (false, src),
(Some(_), _) => (true, src), Some((_, _)) => (true, src),
}; };
// The significand to accumulate // The significand to accumulate
@ -1561,10 +1561,10 @@ macro_rules! from_str_radix_float_impl {
// Parse the exponent as decimal integer // Parse the exponent as decimal integer
let src = src[offset..]; let src = src[offset..];
let (is_positive, exp) = match src.slice_shift_char() { let (is_positive, exp) = match src.slice_shift_char() {
(Some('-'), src) => (false, from_str::<uint>(src)), Some(('-', src)) => (false, from_str::<uint>(src)),
(Some('+'), src) => (true, from_str::<uint>(src)), Some(('+', src)) => (true, from_str::<uint>(src)),
(Some(_), _) => (true, from_str::<uint>(src)), Some((_, _)) => (true, from_str::<uint>(src)),
(None, _) => return None, None => return None,
}; };
match (is_positive, exp) { match (is_positive, exp) {
@ -1604,7 +1604,7 @@ macro_rules! from_str_radix_int_impl {
let is_signed_ty = (0 as $T) > Int::min_value(); let is_signed_ty = (0 as $T) > Int::min_value();
match src.slice_shift_char() { match src.slice_shift_char() {
(Some('-'), src) if is_signed_ty => { Some(('-', src)) if is_signed_ty => {
// The number is negative // The number is negative
let mut result = 0; let mut result = 0;
for c in src.chars() { for c in src.chars() {
@ -1623,7 +1623,7 @@ macro_rules! from_str_radix_int_impl {
} }
Some(result) Some(result)
}, },
(Some(_), _) => { Some((_, _)) => {
// The number is signed // The number is signed
let mut result = 0; let mut result = 0;
for c in src.chars() { for c in src.chars() {
@ -1642,7 +1642,7 @@ macro_rules! from_str_radix_int_impl {
} }
Some(result) Some(result)
}, },
(None, _) => None, None => None,
} }
} }
} }

View file

@ -1808,21 +1808,21 @@ pub trait StrPrelude for Sized? {
/// it. This does not allocate a new string; instead, it returns a /// it. This does not allocate a new string; instead, it returns a
/// slice that point one character beyond the character that was /// slice that point one character beyond the character that was
/// shifted. If the string does not contain any characters, /// shifted. If the string does not contain any characters,
/// a tuple of None and an empty string is returned instead. /// None is returned instead.
/// ///
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// let s = "Löwe 老虎 Léopard"; /// let s = "Löwe 老虎 Léopard";
/// let (c, s1) = s.slice_shift_char(); /// let (c, s1) = s.slice_shift_char().unwrap();
/// assert_eq!(c, Some('L')); /// assert_eq!(c, 'L');
/// assert_eq!(s1, "öwe 老虎 Léopard"); /// assert_eq!(s1, "öwe 老虎 Léopard");
/// ///
/// let (c, s2) = s1.slice_shift_char(); /// let (c, s2) = s1.slice_shift_char().unwrap();
/// assert_eq!(c, Some('ö')); /// assert_eq!(c, 'ö');
/// assert_eq!(s2, "we 老虎 Léopard"); /// assert_eq!(s2, "we 老虎 Léopard");
/// ``` /// ```
fn slice_shift_char<'a>(&'a self) -> (Option<char>, &'a str); fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
/// Returns the byte offset of an inner slice relative to an enclosing outer slice. /// Returns the byte offset of an inner slice relative to an enclosing outer slice.
/// ///
@ -2194,13 +2194,13 @@ impl StrPrelude for str {
} }
#[inline] #[inline]
fn slice_shift_char(&self) -> (Option<char>, &str) { fn slice_shift_char(&self) -> Option<(char, &str)> {
if self.is_empty() { if self.is_empty() {
return (None, self); None
} else { } else {
let CharRange {ch, next} = self.char_range_at(0u); let CharRange {ch, next} = self.char_range_at(0u);
let next_s = unsafe { raw::slice_bytes(self, next, self.len()) }; let next_s = unsafe { raw::slice_bytes(self, next, self.len()) };
return (Some(ch), next_s); Some((ch, next_s))
} }
} }

View file

@ -96,8 +96,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
// cannot be shared with any other operand (usually when // cannot be shared with any other operand (usually when
// a register is clobbered early.) // a register is clobbered early.)
let output = match constraint.get().slice_shift_char() { let output = match constraint.get().slice_shift_char() {
(Some('='), _) => None, Some(('=', _)) => None,
(Some('+'), operand) => { Some(('+', operand)) => {
Some(token::intern_and_get_ident(format!( Some(token::intern_and_get_ident(format!(
"={}", "={}",
operand).as_slice())) operand).as_slice()))

View file

@ -1853,7 +1853,7 @@ impl<'a> State<'a> {
try!(self.commasep(Inconsistent, a.outputs.as_slice(), try!(self.commasep(Inconsistent, a.outputs.as_slice(),
|s, &(ref co, ref o, is_rw)| { |s, &(ref co, ref o, is_rw)| {
match co.get().slice_shift_char() { match co.get().slice_shift_char() {
(Some('='), operand) if is_rw => { Some(('=', operand)) if is_rw => {
try!(s.print_string(format!("+{}", operand).as_slice(), try!(s.print_string(format!("+{}", operand).as_slice(),
ast::CookedStr)) ast::CookedStr))
} }