Skip to content

Commit 47f4516

Browse files
committed
regex: add Regex::split_once method
Convenience function that works like `str::split_once` in the standard library.
1 parent 839d16b commit 47f4516

2 files changed

Lines changed: 170 additions & 0 deletions

File tree

src/regex/bytes.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,91 @@ impl Regex {
642642
SplitN { haystack, it: self.meta.splitn(haystack, limit) }
643643
}
644644

645+
/// Searches for the first match of this regex in the haystack given, and if
646+
/// found, returns a tuple with the substring preceding the match and the
647+
/// substring following it. If no match is found, then `None` is returned.
648+
///
649+
/// The matched substring itself is not returned as part of either
650+
/// substring in the returned tuple.
651+
///
652+
/// # Example
653+
///
654+
/// To split off the first string delimited by arbitrary amounts of spaces
655+
/// or tabs:
656+
///
657+
/// ```
658+
/// use regex::Regex;
659+
///
660+
/// let re = Regex::new(r"[ \t]+").unwrap();
661+
/// let hay = "a b \t c\td e";
662+
/// let got = re.split_once(hay);
663+
/// assert_eq!(got, Some(("a", "b \t c\td e")));
664+
/// ```
665+
///
666+
/// # Example: more cases
667+
///
668+
/// Basic usage:
669+
///
670+
/// ```
671+
/// use regex::Regex;
672+
///
673+
/// let re = Regex::new(r" ").unwrap();
674+
/// let hay = "Mary had a little lamb";
675+
/// let got = re.split_once(hay);
676+
/// assert_eq!(got, Some(("Mary", "had a little lamb")));
677+
///
678+
/// let re = Regex::new(r"X").unwrap();
679+
/// let hay = "";
680+
/// let got = re.split_once(hay);
681+
/// assert_eq!(got, None);
682+
///
683+
/// let re = Regex::new(r"X").unwrap();
684+
/// let hay = "lionXXtigerXleopard";
685+
/// let got = re.split_once(hay);
686+
/// assert_eq!(got, Some(("lion", "XtigerXleopard")));
687+
///
688+
/// let re = Regex::new(r"::").unwrap();
689+
/// let hay = "lion::tiger::leopard";
690+
/// let got = re.split_once(hay);
691+
/// assert_eq!(got, Some(("lion", "tiger::leopard")));
692+
/// ```
693+
///
694+
/// If the first match is at the start or end of a haystack, the
695+
/// corresponding substring is empty.
696+
///
697+
/// ```
698+
/// use regex::Regex;
699+
///
700+
/// let re = Regex::new(r"0").unwrap();
701+
/// let hay = "01";
702+
/// let got = re.split_once(hay);
703+
/// assert_eq!(got, Some(("", "1")));
704+
///
705+
/// let re = Regex::new(r"0").unwrap();
706+
/// let hay = "10";
707+
/// let got = re.split_once(hay);
708+
/// assert_eq!(got, Some(("1", "")));
709+
/// ```
710+
///
711+
/// When the empty string is used as a regex, the resulting tuple consists
712+
/// of the empty string followed by the complete haystack:
713+
///
714+
/// ```
715+
/// use regex::Regex;
716+
///
717+
/// let re = Regex::new(r"").unwrap();
718+
/// let hay = "rust";
719+
/// let got = re.split_once(hay);
720+
/// assert_eq!(got, Some(("", "rust")));
721+
/// ```
722+
#[inline]
723+
pub fn split_once<'h>(&self, haystack: &'h [u8]) -> Option<(&'h [u8], &'h [u8])> {
724+
let m = self.find(haystack)?;
725+
let preceding = &haystack[..m.start()];
726+
let succeeding = &haystack[m.end()..];
727+
Some((preceding, succeeding))
728+
}
729+
645730
/// Replaces the leftmost-first match in the given haystack with the
646731
/// replacement provided. The replacement can be a regular string (where
647732
/// `$N` and `$name` are expanded to match capture groups) or a function

src/regex/string.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,91 @@ impl Regex {
633633
SplitN { haystack, it: self.meta.splitn(haystack, limit) }
634634
}
635635

636+
/// Searches for the first match of this regex in the haystack given, and if
637+
/// found, returns a tuple with the substring preceding the match and the
638+
/// substring following it. If no match is found, then `None` is returned.
639+
///
640+
/// The matched substring itself is not returned as part of either
641+
/// substring in the returned tuple.
642+
///
643+
/// # Example
644+
///
645+
/// To split off the first string delimited by arbitrary amounts of spaces
646+
/// or tabs:
647+
///
648+
/// ```
649+
/// use regex::Regex;
650+
///
651+
/// let re = Regex::new(r"[ \t]+").unwrap();
652+
/// let hay = "a b \t c\td e";
653+
/// let got = re.split_once(hay);
654+
/// assert_eq!(got, Some(("a", "b \t c\td e")));
655+
/// ```
656+
///
657+
/// # Example: more cases
658+
///
659+
/// Basic usage:
660+
///
661+
/// ```
662+
/// use regex::Regex;
663+
///
664+
/// let re = Regex::new(r" ").unwrap();
665+
/// let hay = "Mary had a little lamb";
666+
/// let got = re.split_once(hay);
667+
/// assert_eq!(got, Some(("Mary", "had a little lamb")));
668+
///
669+
/// let re = Regex::new(r"X").unwrap();
670+
/// let hay = "";
671+
/// let got = re.split_once(hay);
672+
/// assert_eq!(got, None);
673+
///
674+
/// let re = Regex::new(r"X").unwrap();
675+
/// let hay = "lionXXtigerXleopard";
676+
/// let got = re.split_once(hay);
677+
/// assert_eq!(got, Some(("lion", "XtigerXleopard")));
678+
///
679+
/// let re = Regex::new(r"::").unwrap();
680+
/// let hay = "lion::tiger::leopard";
681+
/// let got = re.split_once(hay);
682+
/// assert_eq!(got, Some(("lion", "tiger::leopard")));
683+
/// ```
684+
///
685+
/// If the first match is at the start or end of a haystack, the
686+
/// corresponding substring is empty.
687+
///
688+
/// ```
689+
/// use regex::Regex;
690+
///
691+
/// let re = Regex::new(r"0").unwrap();
692+
/// let hay = "01";
693+
/// let got = re.split_once(hay);
694+
/// assert_eq!(got, Some(("", "1")));
695+
///
696+
/// let re = Regex::new(r"0").unwrap();
697+
/// let hay = "10";
698+
/// let got = re.split_once(hay);
699+
/// assert_eq!(got, Some(("1", "")));
700+
/// ```
701+
///
702+
/// When the empty string is used as a regex, the resulting tuple consists
703+
/// of the empty string followed by the complete haystack:
704+
///
705+
/// ```
706+
/// use regex::Regex;
707+
///
708+
/// let re = Regex::new(r"").unwrap();
709+
/// let hay = "rust";
710+
/// let got = re.split_once(hay);
711+
/// assert_eq!(got, Some(("", "rust")));
712+
/// ```
713+
#[inline]
714+
pub fn split_once<'h>(&self, haystack: &'h str) -> Option<(&'h str, &'h str)> {
715+
let m = self.find(haystack)?;
716+
let preceding = &haystack[..m.start()];
717+
let succeeding = &haystack[m.end()..];
718+
Some((preceding, succeeding))
719+
}
720+
636721
/// Replaces the leftmost-first match in the given haystack with the
637722
/// replacement provided. The replacement can be a regular string (where
638723
/// `$N` and `$name` are expanded to match capture groups) or a function

0 commit comments

Comments
 (0)