From 6e9dc7d9ff806eb3a0b99ffd10892dac8e6f9739 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 24 Jul 2020 09:39:09 +0200 Subject: [PATCH] Add str::[r]split_once This is useful for quick&dirty parsing of key: value config pairs --- library/alloc/tests/lib.rs | 1 + library/alloc/tests/str.rs | 24 ++++++++++++++++++++++ library/core/src/str/mod.rs | 41 +++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index e2dc816b01526..fa20a46671591 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -6,6 +6,7 @@ #![feature(map_first_last)] #![feature(new_uninit)] #![feature(pattern)] +#![feature(str_split_once)] #![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index eee98d4534042..b20cf076aca3c 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1318,6 +1318,30 @@ fn test_rsplitn() { assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]); } +#[test] +fn test_split_once() { + assert_eq!("".split_once("->"), None); + assert_eq!("-".split_once("->"), None); + assert_eq!("->".split_once("->"), Some(("", ""))); + assert_eq!("a->".split_once("->"), Some(("a", ""))); + assert_eq!("->b".split_once("->"), Some(("", "b"))); + assert_eq!("a->b".split_once("->"), Some(("a", "b"))); + assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c"))); + assert_eq!("---".split_once("--"), Some(("", "-"))); +} + +#[test] +fn test_rsplit_once() { + assert_eq!("".rsplit_once("->"), None); + assert_eq!("-".rsplit_once("->"), None); + assert_eq!("->".rsplit_once("->"), Some(("", ""))); + assert_eq!("a->".rsplit_once("->"), Some(("a", ""))); + assert_eq!("->b".rsplit_once("->"), Some(("", "b"))); + assert_eq!("a->b".rsplit_once("->"), Some(("a", "b"))); + assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c"))); + assert_eq!("---".rsplit_once("--"), Some(("-", ""))); +} + #[test] fn test_split_whitespace() { let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 790ec4bd24f8d..9d7e38d0e1831 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -3610,6 +3610,47 @@ impl str { RSplitN(self.splitn(n, pat).0) } + /// Splits the string on the first occurrence of the specified delimiter and + /// returns prefix before delimiter and suffix after delimiter. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_once)] + /// + /// assert_eq!("cfg".split_once('='), None); + /// assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo"))); + /// assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar"))); + /// ``` + #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")] + #[inline] + pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> { + let (start, end) = delimiter.into_searcher(self).next_match()?; + Some((&self[..start], &self[end..])) + } + + /// Splits the string on the last occurrence of the specified delimiter and + /// returns prefix before delimiter and suffix after delimiter. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_once)] + /// + /// assert_eq!("cfg".rsplit_once('='), None); + /// assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo"))); + /// assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar"))); + /// ``` + #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")] + #[inline] + pub fn rsplit_once<'a, P>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, + { + let (start, end) = delimiter.into_searcher(self).next_match_back()?; + Some((&self[..start], &self[end..])) + } + /// An iterator over the disjoint matches of a pattern within the given string /// slice. ///