strings: take IntoCharIter instead of wstr

Change the input of some functions to take `impl IntoCharIter`, allowing
them to accept more input. Implementing this efficiently means that no
owned types should be passed into these functions, because their
`IntoCharIter` implementation would require unnecessary allocations.
Instead, convert the uses which previously passed `WString` by prefixing
an `&`, so the borrowed `&WString` is passed instead.

To allow for wider use of the modified functions, `IntoCharIter`
implementations are added for `&String`, `&Cow<str>`, and `&Cow<wstr>`.

Closes #12207
This commit is contained in:
Daniel Rainer
2025-10-31 00:33:31 +01:00
committed by danielrainer
parent daa554123f
commit 107cbaddf0
54 changed files with 408 additions and 368 deletions

View File

@@ -113,6 +113,9 @@ fn to_wstring(&self) -> WString {
pub trait IntoCharIter {
type Iter: DoubleEndedIterator<Item = char> + Clone;
fn chars(self) -> Self::Iter;
fn extend_wstring(&self, _out: &mut WString) -> bool {
false
}
}
impl IntoCharIter for char {
@@ -129,12 +132,23 @@ fn chars(self) -> Self::Iter {
}
}
impl<'a> IntoCharIter for &'a String {
type Iter = std::str::Chars<'a>;
fn chars(self) -> Self::Iter {
str::chars(self)
}
}
impl<'a> IntoCharIter for &'a [char] {
type Iter = iter::Copied<slice::Iter<'a, char>>;
fn chars(self) -> Self::Iter {
self.iter().copied()
}
fn extend_wstring(&self, out: &mut WString) -> bool {
out.push_utfstr(wstr::from_char_slice(self));
true
}
}
impl<'a> IntoCharIter for &'a wstr {
@@ -142,6 +156,9 @@ impl<'a> IntoCharIter for &'a wstr {
fn chars(self) -> Self::Iter {
wstr::chars(self)
}
fn extend_wstring(&self, out: &mut WString) -> bool {
self.as_char_slice().extend_wstring(out)
}
}
impl<'a> IntoCharIter for &'a WString {
@@ -149,6 +166,9 @@ impl<'a> IntoCharIter for &'a WString {
fn chars(self) -> Self::Iter {
wstr::chars(self)
}
fn extend_wstring(&self, out: &mut WString) -> bool {
self.as_char_slice().extend_wstring(out)
}
}
// Also support `str.chars()` itself.
@@ -167,6 +187,23 @@ fn chars(self) -> Self::Iter {
}
}
impl<'a: 'b, 'b> IntoCharIter for &'b std::borrow::Cow<'a, str> {
type Iter = std::str::Chars<'b>;
fn chars(self) -> Self::Iter {
str::chars(self)
}
}
impl<'a: 'b, 'b> IntoCharIter for &'b std::borrow::Cow<'a, wstr> {
type Iter = CharsUtf32<'b>;
fn chars(self) -> Self::Iter {
wstr::chars(self)
}
fn extend_wstring(&self, out: &mut WString) -> bool {
self.as_char_slice().extend_wstring(out)
}
}
/// Return true if `prefix` is a prefix of `contents`.
fn iter_prefixes_iter<Prefix, Contents>(prefix: Prefix, mut contents: Contents) -> bool
where