Skip to content

Instantly share code, notes, and snippets.

@jonathanmarvens
Forked from jonhoo/strsplit.rs
Created May 23, 2020 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathanmarvens/e71e69a6d2d829e27b834b6b0c80f661 to your computer and use it in GitHub Desktop.
Save jonathanmarvens/e71e69a6d2d829e27b834b6b0c80f661 to your computer and use it in GitHub Desktop.
#![warn(rust_2018_idioms)]
#[derive(Debug)]
pub struct StrSplit<'haystack, D> {
remainder: Option<&'haystack str>,
delimiter: D,
}
impl<'haystack, D> StrSplit<'haystack, D> {
pub fn new(haystack: &'haystack str, delimiter: D) -> Self {
Self {
remainder: Some(haystack),
delimiter,
}
}
}
pub trait Delimiter {
fn find_next(&self, s: &str) -> Option<(usize, usize)>;
}
impl<'haystack, D> Iterator for StrSplit<'haystack, D>
where
D: Delimiter,
{
type Item = &'haystack str;
fn next(&mut self) -> Option<Self::Item> {
let remainder = self.remainder.as_mut()?;
if let Some((delim_start, delim_end)) = self.delimiter.find_next(remainder) {
let until_delimiter = &remainder[..delim_start];
*remainder = &remainder[delim_end..];
Some(until_delimiter)
} else {
self.remainder.take()
}
}
}
impl Delimiter for &str {
fn find_next(&self, s: &str) -> Option<(usize, usize)> {
s.find(self).map(|start| (start, start + self.len()))
}
}
impl Delimiter for char {
fn find_next(&self, s: &str) -> Option<(usize, usize)> {
s.char_indices()
.find(|(_, c)| c == self)
.map(|(start, _)| (start, start + self.len_utf8()))
}
}
pub fn until_char(s: &str, c: char) -> &'_ str {
StrSplit::new(s, c)
.next()
.expect("StrSplit always gives at least one result")
}
#[test]
fn until_char_test() {
assert_eq!(until_char("hello world", 'o'), "hell");
}
#[test]
fn it_works() {
let haystack = "a b c d e";
let letters: Vec<_> = StrSplit::new(haystack, " ").collect();
assert_eq!(letters, vec!["a", "b", "c", "d", "e"]);
}
#[test]
fn tail() {
let haystack = "a b c d ";
let letters: Vec<_> = StrSplit::new(haystack, " ").collect();
assert_eq!(letters, vec!["a", "b", "c", "d", ""]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment