impl<'a> Chars<'a> {
fn remaining(&self) -> 'a &str { self.string }
}
This is quite useful when scanning strings, especially when more flexibility is needed. For example, the following example uses slice_from which is not always safe as it uses byte offsets (but using char offsets would be O(n) and I want to avoid it!).
// This code basically parses a markdown horizontal rule.
let item: char = '*';
// Counts the number of items
let mut cnt: uint = 0;
// Counts the consumed spaces (and the final NL)
let mut spc: uint = 0;
for ch in string.chars() {
if ch == item { cnt += 1; }
else if ch == '\n' { spc += 1; break; }
else if ch == ' ' { spc += 1; }
else { return None; }
}
if cnt >= 3 {
// return sucess and the remaining string to continue parsing!
Some(string.slice_from(cnt + spc))
} else {
None
}
Instead when something like remaining() would exist, the code could be rewritten as:
let item = '*';
// Counts the number of items
let mut cnt: uint = 0;
let iter = string.chars();
for ch in iter {
if ch == item { cnt += 1; }
else if ch == '\n' { break; }
else if ch == ' ' {}
else { return None; }
}
if cnt >= 3 {
Some(iter.remaining())
} else {
None
}
This comes in very useful and is also more efficient! Iterators are not always enough, so that's why I do not want to pass iterators around and instead work on string slices.
This is quite useful when scanning strings, especially when more flexibility is needed. For example, the following example uses
slice_fromwhich is not always safe as it uses byte offsets (but using char offsets would be O(n) and I want to avoid it!).Instead when something like
remaining()would exist, the code could be rewritten as:This comes in very useful and is also more efficient! Iterators are not always enough, so that's why I do not want to pass iterators around and instead work on string slices.