Reimplement CaseMappingIter with core::array::IntoIter

Makes the iterator 2*usize larger, but I doubt that matters much.
In exchange, we save a lot on instruction count.

In the absence of delegation syntax,
we must forward all the specialized impls manually…
This commit is contained in:
Jules Bertholet 2024-03-18 23:07:28 -04:00
parent 1c137b7582
commit 2f1ab2ce09
No known key found for this signature in database
GPG Key ID: 32034DAFC38C1BFC

View File

@ -42,7 +42,7 @@
use crate::error::Error; use crate::error::Error;
use crate::escape; use crate::escape;
use crate::fmt::{self, Write}; use crate::fmt::{self, Write};
use crate::iter::FusedIterator; use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::num::NonZero; use crate::num::NonZero;
pub(crate) use self::methods::EscapeDebugExtArgs; pub(crate) use self::methods::EscapeDebugExtArgs;
@ -373,176 +373,229 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
} }
} }
/// Returns an iterator that yields the lowercase equivalent of a `char`. macro_rules! casemappingiter_impls {
/// ($(#[$attr:meta])* $ITER_NAME:ident) => {
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See $(#[$attr])*
/// its documentation for more. #[stable(feature = "rust1", since = "1.0.0")]
/// #[derive(Debug, Clone)]
/// [`to_lowercase`]: char::to_lowercase pub struct $ITER_NAME(CaseMappingIter);
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone)]
pub struct ToLowercase(CaseMappingIter);
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for ToLowercase { impl Iterator for $ITER_NAME {
type Item = char; type Item = char;
fn next(&mut self) -> Option<char> { fn next(&mut self) -> Option<char> {
self.0.next() self.0.next()
} }
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint() fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.0.fold(init, fold)
}
fn count(self) -> usize {
self.0.count()
}
fn last(self) -> Option<Self::Item> {
self.0.last()
}
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.0.advance_by(n)
}
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// SAFETY: just forwarding requirements to caller
unsafe { self.0.__iterator_get_unchecked(idx) }
}
}
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
impl DoubleEndedIterator for $ITER_NAME {
fn next_back(&mut self) -> Option<char> {
self.0.next_back()
}
fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.0.rfold(init, rfold)
}
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.0.advance_back_by(n)
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for $ITER_NAME {}
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
impl ExactSizeIterator for $ITER_NAME {
fn len(&self) -> usize {
self.0.len()
}
fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
// SAFETY: forwards to inner `array::IntoIter`
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl TrustedLen for $ITER_NAME {}
// SAFETY: forwards to inner `array::IntoIter`
#[doc(hidden)]
#[unstable(feature = "std_internals", issue = "none")]
unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
// SAFETY: this iter has no subtypes/supertypes
#[doc(hidden)]
#[unstable(feature = "std_internals", issue = "none")]
unsafe impl TrustedRandomAccess for $ITER_NAME {}
#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for $ITER_NAME {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
} }
} }
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")] casemappingiter_impls! {
impl DoubleEndedIterator for ToLowercase { /// Returns an iterator that yields the lowercase equivalent of a `char`.
fn next_back(&mut self) -> Option<char> { ///
self.0.next_back() /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
} /// its documentation for more.
///
/// [`to_lowercase`]: char::to_lowercase
ToLowercase
} }
#[stable(feature = "fused", since = "1.26.0")] casemappingiter_impls! {
impl FusedIterator for ToLowercase {} /// Returns an iterator that yields the uppercase equivalent of a `char`.
///
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")] /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
impl ExactSizeIterator for ToLowercase {} /// its documentation for more.
///
/// Returns an iterator that yields the uppercase equivalent of a `char`. /// [`to_uppercase`]: char::to_uppercase
/// ToUppercase
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
/// its documentation for more.
///
/// [`to_uppercase`]: char::to_uppercase
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone)]
pub struct ToUppercase(CaseMappingIter);
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for ToUppercase {
type Item = char;
fn next(&mut self) -> Option<char> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
} }
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
impl DoubleEndedIterator for ToUppercase {
fn next_back(&mut self) -> Option<char> {
self.0.next_back()
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for ToUppercase {}
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
impl ExactSizeIterator for ToUppercase {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum CaseMappingIter { struct CaseMappingIter(core::array::IntoIter<char, 3>);
Zero,
One(char),
Two([char; 2]),
Three([char; 3]),
}
impl CaseMappingIter { impl CaseMappingIter {
#[inline]
fn new(chars: [char; 3]) -> CaseMappingIter { fn new(chars: [char; 3]) -> CaseMappingIter {
let mut iter = chars.into_iter();
if chars[2] == '\0' { if chars[2] == '\0' {
iter.next_back();
if chars[1] == '\0' { if chars[1] == '\0' {
CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0' iter.next_back();
} else {
CaseMappingIter::Two([chars[0], chars[1]]) // Deliberately don't check `chars[0]`,
// as '\0' lowercases to itself
} }
} else {
CaseMappingIter::Three([chars[0], chars[1], chars[2]])
} }
CaseMappingIter(iter)
} }
} }
impl Iterator for CaseMappingIter { impl Iterator for CaseMappingIter {
type Item = char; type Item = char;
fn next(&mut self) -> Option<char> { fn next(&mut self) -> Option<char> {
match *self { self.0.next()
CaseMappingIter::Zero => None,
CaseMappingIter::One(c) => {
*self = CaseMappingIter::Zero;
Some(c)
}
CaseMappingIter::Two([b, c]) => {
*self = CaseMappingIter::One(c);
Some(b)
}
CaseMappingIter::Three([a, b, c]) => {
*self = CaseMappingIter::Two([b, c]);
Some(a)
}
}
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
let size = match self { self.0.size_hint()
CaseMappingIter::Zero => 0, }
CaseMappingIter::One(_) => 1,
CaseMappingIter::Two(..) => 2, fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
CaseMappingIter::Three(..) => 3, where
}; Fold: FnMut(Acc, Self::Item) -> Acc,
(size, Some(size)) {
self.0.fold(init, fold)
}
fn count(self) -> usize {
self.0.count()
}
fn last(self) -> Option<Self::Item> {
self.0.last()
}
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.0.advance_by(n)
}
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// SAFETY: just forwarding requirements to caller
unsafe { self.0.__iterator_get_unchecked(idx) }
} }
} }
impl DoubleEndedIterator for CaseMappingIter { impl DoubleEndedIterator for CaseMappingIter {
fn next_back(&mut self) -> Option<char> { fn next_back(&mut self) -> Option<char> {
match *self { self.0.next_back()
CaseMappingIter::Zero => None, }
CaseMappingIter::One(c) => {
*self = CaseMappingIter::Zero; fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
Some(c) where
} Fold: FnMut(Acc, Self::Item) -> Acc,
CaseMappingIter::Two([b, c]) => { {
*self = CaseMappingIter::One(b); self.0.rfold(init, rfold)
Some(c) }
}
CaseMappingIter::Three([a, b, c]) => { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
*self = CaseMappingIter::Two([a, b]); self.0.advance_back_by(n)
Some(c)
}
}
} }
} }
impl ExactSizeIterator for CaseMappingIter {
fn len(&self) -> usize {
self.0.len()
}
fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl FusedIterator for CaseMappingIter {}
// SAFETY: forwards to inner `array::IntoIter`
unsafe impl TrustedLen for CaseMappingIter {}
// SAFETY: forwards to inner `array::IntoIter`
unsafe impl TrustedRandomAccessNoCoerce for CaseMappingIter {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
// SAFETY: `CaseMappingIter` has no subtypes/supertypes
unsafe impl TrustedRandomAccess for CaseMappingIter {}
impl fmt::Display for CaseMappingIter { impl fmt::Display for CaseMappingIter {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self { for c in self.0.clone() {
CaseMappingIter::Zero => Ok(()), f.write_char(c)?;
CaseMappingIter::One(c) => f.write_char(c),
CaseMappingIter::Two([b, c]) => {
f.write_char(b)?;
f.write_char(c)
}
CaseMappingIter::Three([a, b, c]) => {
f.write_char(a)?;
f.write_char(b)?;
f.write_char(c)
}
} }
} Ok(())
}
#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for ToLowercase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
#[stable(feature = "char_struct_display", since = "1.16.0")]
impl fmt::Display for ToUppercase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
} }
} }