Skip to content

Commit

Permalink
feat: Needle can now be a &str or a String.
Browse files Browse the repository at this point in the history
Using an AsRef<str> for needle.
  • Loading branch information
ishaan26 committed Oct 2, 2024
1 parent 48316f7 commit 77f1c70
Showing 1 changed file with 45 additions and 11 deletions.
56 changes: 45 additions & 11 deletions zung_mini/src/strsplit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,19 @@ where
/// let split: Vec<&str> = haystack.strsplit(" ").collect();
/// assert_eq!(split, vec!["this", "is", "an", "example"]);
/// ```
fn strsplit(&'a self, needle: &'b str) -> Strsplit;
fn strsplit<P>(&'a self, needle: P) -> Strsplit<'a, P>
where
P: 'b + AsRef<str>;
}

impl<'a, 'b> StrsplitExt<'a, 'b> for String
where
'b: 'a,
{
fn strsplit(&'a self, needle: &'b str) -> Strsplit<'a> {
fn strsplit<P>(&'a self, needle: P) -> Strsplit<'a, P>
where
P: 'b + AsRef<str>,
{
Strsplit::new(self, needle)
}

Check warning on line 80 in zung_mini/src/strsplit/mod.rs

View check run for this annotation

Codecov / codecov/patch

zung_mini/src/strsplit/mod.rs#L75-L80

Added lines #L75 - L80 were not covered by tests
}
Expand All @@ -79,7 +84,10 @@ impl<'a, 'b> StrsplitExt<'a, 'b> for &str
where
'b: 'a,
{
fn strsplit(&'a self, needle: &'b str) -> Strsplit<'a> {
fn strsplit<P>(&'a self, needle: P) -> Strsplit<'a, P>
where
P: 'b + AsRef<str>,
{
Strsplit::new(self, needle)
}
}
Expand All @@ -89,14 +97,17 @@ where
/// occurrences of the delimiter.
///
/// This type is constructed by the [`strsplit()`](StrsplitExt::strsplit()) method.
pub struct Strsplit<'a> {
pub struct Strsplit<'a, N> {
remainder: Option<&'a str>,
needle: &'a str,
needle: N,
}

impl<'a> Strsplit<'a> {
fn new(haystack: &'a str, needle: &'a str) -> Self {
assert!(!needle.is_empty(), "Empty needle is not allowed");
impl<'a, N> Strsplit<'a, N>
where
N: 'a + AsRef<str>,
{
fn new(haystack: &'a str, needle: N) -> Self {
assert!(!needle.as_ref().is_empty(), "Empty needle is not allowed");
Self {
remainder: Some(haystack),
needle,
Expand Down Expand Up @@ -125,13 +136,16 @@ impl<'a> Strsplit<'a> {
}
}

impl<'a> Iterator for Strsplit<'a> {
impl<'a, N> Iterator for Strsplit<'a, N>
where
N: 'a + AsRef<str>,
{
type Item = &'a str;

fn next(&mut self) -> Option<Self::Item> {
let remainder = self.remainder.as_mut()?;

if let Some((start, end)) = find_needle(self.needle, remainder) {
if let Some((start, end)) = find_needle(self.needle.as_ref(), remainder) {
let before_needle = &remainder[..start];
*remainder = &remainder[end..];
Some(before_needle)
Expand All @@ -147,10 +161,21 @@ fn find_needle(needle: &str, haystack: &str) -> Option<(usize, usize)> {
.map(|index| (index, index + needle.len()))
}

#[cfg(test)]
mod tests {
#[cfg(test)]
use super::*;

#[test]
fn test_new() {
let a = "a b c d e f".strsplit(" ");
let b = Strsplit {
remainder: Some("a b c d e f"),
needle: " ",
};
assert_eq!(a.remainder, b.remainder);
assert_eq!(a.needle, b.needle);
}

#[test]
fn strsplit_works() {
let a = "a b c d e f";
Expand All @@ -160,6 +185,15 @@ mod tests {
);
}

#[test]
fn strsplit_works_with_string() {
let a = "a b c d e f";
assert_eq!(
a.strsplit(String::from(" ")).into_vec(),
vec!["a", "b", "c", "d", "e", "f"]
);
}

#[test]
#[should_panic(expected = "Empty needle is not allowed")]
fn empty_needle() {
Expand Down

0 comments on commit 77f1c70

Please sign in to comment.