diff options
Diffstat (limited to 'src/libcore/str/mod.rs')
| -rw-r--r-- | src/libcore/str/mod.rs | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index eefed517330..5a20e32a419 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -8,10 +8,13 @@ use self::pattern::Pattern; use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use char; -use fmt; +use fmt::{self, Write}; use iter::{Map, Cloned, FusedIterator, TrustedLen, TrustedRandomAccess, Filter}; +use iter::{Flatten, FlatMap, Chain}; use slice::{self, SliceIndex, Split as SliceSplit}; use mem; +use ops::Try; +use option; pub mod pattern; @@ -3945,6 +3948,56 @@ impl str { let me = unsafe { self.as_bytes_mut() }; me.make_ascii_lowercase() } + + /// Escapes each char in `s` with [`char::escape_debug`]. + /// + /// Note: only extended grapheme codepoints that begin the string will be + /// escaped. + /// + /// [`char::escape_debug`]: ../std/primitive.char.html#method.escape_debug + #[stable(feature = "str_escape", since = "1.34.0")] + pub fn escape_debug(&self) -> EscapeDebug { + let mut chars = self.chars(); + EscapeDebug { + inner: chars.next() + .map(|first| first.escape_debug_ext(true)) + .into_iter() + .flatten() + .chain(chars.flat_map(CharEscapeDebugContinue)) + } + } + + /// Escapes each char in `s` with [`char::escape_default`]. + /// + /// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default + #[stable(feature = "str_escape", since = "1.34.0")] + pub fn escape_default(&self) -> EscapeDefault { + EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) } + } + + /// Escapes each char in `s` with [`char::escape_unicode`]. + /// + /// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode + #[stable(feature = "str_escape", since = "1.34.0")] + pub fn escape_unicode(&self) -> EscapeUnicode { + EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) } + } +} + +impl_fn_for_zst! { + #[derive(Clone)] + struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug { + c.escape_debug_ext(false) + }; + + #[derive(Clone)] + struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode { + c.escape_unicode() + }; + #[derive(Clone)] + struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault { + c.escape_default() + }; } #[stable(feature = "rust1", since = "1.0.0")] @@ -4131,3 +4184,74 @@ impl<'a> Iterator for EncodeUtf16<'a> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EncodeUtf16<'_> {} + +/// The return type of [`str::escape_debug`]. +/// +/// [`str::escape_debug`]: ../../std/primitive.str.html#method.escape_debug +#[stable(feature = "str_escape", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct EscapeDebug<'a> { + inner: Chain< + Flatten<option::IntoIter<char::EscapeDebug>>, + FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue> + >, +} + +/// The return type of [`str::escape_default`]. +/// +/// [`str::escape_default`]: ../../std/primitive.str.html#method.escape_default +#[stable(feature = "str_escape", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct EscapeDefault<'a> { + inner: FlatMap<Chars<'a>, char::EscapeDefault, CharEscapeDefault>, +} + +/// The return type of [`str::escape_unicode`]. +/// +/// [`str::escape_unicode`]: ../../std/primitive.str.html#method.escape_unicode +#[stable(feature = "str_escape", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct EscapeUnicode<'a> { + inner: FlatMap<Chars<'a>, char::EscapeUnicode, CharEscapeUnicode>, +} + +macro_rules! escape_types_impls { + ($( $Name: ident ),+) => {$( + #[stable(feature = "str_escape", since = "1.34.0")] + impl<'a> fmt::Display for $Name<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.clone().try_for_each(|c| f.write_char(c)) + } + } + + #[stable(feature = "str_escape", since = "1.34.0")] + impl<'a> Iterator for $Name<'a> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option<char> { self.inner.next() } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> + { + self.inner.try_fold(init, fold) + } + + #[inline] + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + } + + #[stable(feature = "str_escape", since = "1.34.0")] + impl<'a> FusedIterator for $Name<'a> {} + )+} +} + +escape_types_impls!(EscapeDebug, EscapeDefault, EscapeUnicode); |
