Skip to content

Commit 2f1ab2c

Browse files
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…
1 parent 1c137b7 commit 2f1ab2c

File tree

1 file changed

+181
-128
lines changed

1 file changed

+181
-128
lines changed

library/core/src/char/mod.rs

+181-128
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use crate::ascii;
4242
use crate::error::Error;
4343
use crate::escape;
4444
use crate::fmt::{self, Write};
45-
use crate::iter::FusedIterator;
45+
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
4646
use crate::num::NonZero;
4747

4848
pub(crate) use self::methods::EscapeDebugExtArgs;
@@ -373,176 +373,229 @@ impl fmt::Display for EscapeDebug {
373373
}
374374
}
375375

376-
/// Returns an iterator that yields the lowercase equivalent of a `char`.
377-
///
378-
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
379-
/// its documentation for more.
380-
///
381-
/// [`to_lowercase`]: char::to_lowercase
382-
#[stable(feature = "rust1", since = "1.0.0")]
383-
#[derive(Debug, Clone)]
384-
pub struct ToLowercase(CaseMappingIter);
376+
macro_rules! casemappingiter_impls {
377+
($(#[$attr:meta])* $ITER_NAME:ident) => {
378+
$(#[$attr])*
379+
#[stable(feature = "rust1", since = "1.0.0")]
380+
#[derive(Debug, Clone)]
381+
pub struct $ITER_NAME(CaseMappingIter);
382+
383+
#[stable(feature = "rust1", since = "1.0.0")]
384+
impl Iterator for $ITER_NAME {
385+
type Item = char;
386+
fn next(&mut self) -> Option<char> {
387+
self.0.next()
388+
}
385389

386-
#[stable(feature = "rust1", since = "1.0.0")]
387-
impl Iterator for ToLowercase {
388-
type Item = char;
389-
fn next(&mut self) -> Option<char> {
390-
self.0.next()
391-
}
392-
fn size_hint(&self) -> (usize, Option<usize>) {
393-
self.0.size_hint()
394-
}
395-
}
390+
fn size_hint(&self) -> (usize, Option<usize>) {
391+
self.0.size_hint()
392+
}
396393

397-
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
398-
impl DoubleEndedIterator for ToLowercase {
399-
fn next_back(&mut self) -> Option<char> {
400-
self.0.next_back()
401-
}
402-
}
394+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
395+
where
396+
Fold: FnMut(Acc, Self::Item) -> Acc,
397+
{
398+
self.0.fold(init, fold)
399+
}
403400

404-
#[stable(feature = "fused", since = "1.26.0")]
405-
impl FusedIterator for ToLowercase {}
401+
fn count(self) -> usize {
402+
self.0.count()
403+
}
406404

407-
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
408-
impl ExactSizeIterator for ToLowercase {}
405+
fn last(self) -> Option<Self::Item> {
406+
self.0.last()
407+
}
409408

410-
/// Returns an iterator that yields the uppercase equivalent of a `char`.
411-
///
412-
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
413-
/// its documentation for more.
414-
///
415-
/// [`to_uppercase`]: char::to_uppercase
416-
#[stable(feature = "rust1", since = "1.0.0")]
417-
#[derive(Debug, Clone)]
418-
pub struct ToUppercase(CaseMappingIter);
409+
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
410+
self.0.advance_by(n)
411+
}
419412

420-
#[stable(feature = "rust1", since = "1.0.0")]
421-
impl Iterator for ToUppercase {
422-
type Item = char;
423-
fn next(&mut self) -> Option<char> {
424-
self.0.next()
425-
}
426-
fn size_hint(&self) -> (usize, Option<usize>) {
427-
self.0.size_hint()
428-
}
429-
}
413+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
414+
// SAFETY: just forwarding requirements to caller
415+
unsafe { self.0.__iterator_get_unchecked(idx) }
416+
}
417+
}
430418

431-
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
432-
impl DoubleEndedIterator for ToUppercase {
433-
fn next_back(&mut self) -> Option<char> {
434-
self.0.next_back()
419+
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
420+
impl DoubleEndedIterator for $ITER_NAME {
421+
fn next_back(&mut self) -> Option<char> {
422+
self.0.next_back()
423+
}
424+
425+
fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
426+
where
427+
Fold: FnMut(Acc, Self::Item) -> Acc,
428+
{
429+
self.0.rfold(init, rfold)
430+
}
431+
432+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
433+
self.0.advance_back_by(n)
434+
}
435+
}
436+
437+
#[stable(feature = "fused", since = "1.26.0")]
438+
impl FusedIterator for $ITER_NAME {}
439+
440+
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
441+
impl ExactSizeIterator for $ITER_NAME {
442+
fn len(&self) -> usize {
443+
self.0.len()
444+
}
445+
446+
fn is_empty(&self) -> bool {
447+
self.0.is_empty()
448+
}
449+
}
450+
451+
// SAFETY: forwards to inner `array::IntoIter`
452+
#[unstable(feature = "trusted_len", issue = "37572")]
453+
unsafe impl TrustedLen for $ITER_NAME {}
454+
455+
// SAFETY: forwards to inner `array::IntoIter`
456+
#[doc(hidden)]
457+
#[unstable(feature = "std_internals", issue = "none")]
458+
unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME {
459+
const MAY_HAVE_SIDE_EFFECT: bool = false;
460+
}
461+
462+
// SAFETY: this iter has no subtypes/supertypes
463+
#[doc(hidden)]
464+
#[unstable(feature = "std_internals", issue = "none")]
465+
unsafe impl TrustedRandomAccess for $ITER_NAME {}
466+
467+
#[stable(feature = "char_struct_display", since = "1.16.0")]
468+
impl fmt::Display for $ITER_NAME {
469+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
470+
fmt::Display::fmt(&self.0, f)
471+
}
472+
}
435473
}
436474
}
437475

438-
#[stable(feature = "fused", since = "1.26.0")]
439-
impl FusedIterator for ToUppercase {}
476+
casemappingiter_impls! {
477+
/// Returns an iterator that yields the lowercase equivalent of a `char`.
478+
///
479+
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
480+
/// its documentation for more.
481+
///
482+
/// [`to_lowercase`]: char::to_lowercase
483+
ToLowercase
484+
}
440485

441-
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
442-
impl ExactSizeIterator for ToUppercase {}
486+
casemappingiter_impls! {
487+
/// Returns an iterator that yields the uppercase equivalent of a `char`.
488+
///
489+
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
490+
/// its documentation for more.
491+
///
492+
/// [`to_uppercase`]: char::to_uppercase
493+
ToUppercase
494+
}
443495

444496
#[derive(Debug, Clone)]
445-
enum CaseMappingIter {
446-
Zero,
447-
One(char),
448-
Two([char; 2]),
449-
Three([char; 3]),
450-
}
497+
struct CaseMappingIter(core::array::IntoIter<char, 3>);
451498

452499
impl CaseMappingIter {
500+
#[inline]
453501
fn new(chars: [char; 3]) -> CaseMappingIter {
502+
let mut iter = chars.into_iter();
454503
if chars[2] == '\0' {
504+
iter.next_back();
455505
if chars[1] == '\0' {
456-
CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0'
457-
} else {
458-
CaseMappingIter::Two([chars[0], chars[1]])
506+
iter.next_back();
507+
508+
// Deliberately don't check `chars[0]`,
509+
// as '\0' lowercases to itself
459510
}
460-
} else {
461-
CaseMappingIter::Three([chars[0], chars[1], chars[2]])
462511
}
512+
CaseMappingIter(iter)
463513
}
464514
}
465515

466516
impl Iterator for CaseMappingIter {
467517
type Item = char;
518+
468519
fn next(&mut self) -> Option<char> {
469-
match *self {
470-
CaseMappingIter::Zero => None,
471-
CaseMappingIter::One(c) => {
472-
*self = CaseMappingIter::Zero;
473-
Some(c)
474-
}
475-
CaseMappingIter::Two([b, c]) => {
476-
*self = CaseMappingIter::One(c);
477-
Some(b)
478-
}
479-
CaseMappingIter::Three([a, b, c]) => {
480-
*self = CaseMappingIter::Two([b, c]);
481-
Some(a)
482-
}
483-
}
520+
self.0.next()
484521
}
485522

486523
fn size_hint(&self) -> (usize, Option<usize>) {
487-
let size = match self {
488-
CaseMappingIter::Zero => 0,
489-
CaseMappingIter::One(_) => 1,
490-
CaseMappingIter::Two(..) => 2,
491-
CaseMappingIter::Three(..) => 3,
492-
};
493-
(size, Some(size))
524+
self.0.size_hint()
525+
}
526+
527+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
528+
where
529+
Fold: FnMut(Acc, Self::Item) -> Acc,
530+
{
531+
self.0.fold(init, fold)
532+
}
533+
534+
fn count(self) -> usize {
535+
self.0.count()
536+
}
537+
538+
fn last(self) -> Option<Self::Item> {
539+
self.0.last()
540+
}
541+
542+
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
543+
self.0.advance_by(n)
544+
}
545+
546+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
547+
// SAFETY: just forwarding requirements to caller
548+
unsafe { self.0.__iterator_get_unchecked(idx) }
494549
}
495550
}
496551

497552
impl DoubleEndedIterator for CaseMappingIter {
498553
fn next_back(&mut self) -> Option<char> {
499-
match *self {
500-
CaseMappingIter::Zero => None,
501-
CaseMappingIter::One(c) => {
502-
*self = CaseMappingIter::Zero;
503-
Some(c)
504-
}
505-
CaseMappingIter::Two([b, c]) => {
506-
*self = CaseMappingIter::One(b);
507-
Some(c)
508-
}
509-
CaseMappingIter::Three([a, b, c]) => {
510-
*self = CaseMappingIter::Two([a, b]);
511-
Some(c)
512-
}
513-
}
554+
self.0.next_back()
514555
}
515-
}
516556

517-
impl fmt::Display for CaseMappingIter {
518-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519-
match *self {
520-
CaseMappingIter::Zero => Ok(()),
521-
CaseMappingIter::One(c) => f.write_char(c),
522-
CaseMappingIter::Two([b, c]) => {
523-
f.write_char(b)?;
524-
f.write_char(c)
525-
}
526-
CaseMappingIter::Three([a, b, c]) => {
527-
f.write_char(a)?;
528-
f.write_char(b)?;
529-
f.write_char(c)
530-
}
531-
}
557+
fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
558+
where
559+
Fold: FnMut(Acc, Self::Item) -> Acc,
560+
{
561+
self.0.rfold(init, rfold)
562+
}
563+
564+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
565+
self.0.advance_back_by(n)
532566
}
533567
}
534568

535-
#[stable(feature = "char_struct_display", since = "1.16.0")]
536-
impl fmt::Display for ToLowercase {
537-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
538-
fmt::Display::fmt(&self.0, f)
569+
impl ExactSizeIterator for CaseMappingIter {
570+
fn len(&self) -> usize {
571+
self.0.len()
572+
}
573+
574+
fn is_empty(&self) -> bool {
575+
self.0.is_empty()
539576
}
540577
}
541578

542-
#[stable(feature = "char_struct_display", since = "1.16.0")]
543-
impl fmt::Display for ToUppercase {
579+
impl FusedIterator for CaseMappingIter {}
580+
581+
// SAFETY: forwards to inner `array::IntoIter`
582+
unsafe impl TrustedLen for CaseMappingIter {}
583+
584+
// SAFETY: forwards to inner `array::IntoIter`
585+
unsafe impl TrustedRandomAccessNoCoerce for CaseMappingIter {
586+
const MAY_HAVE_SIDE_EFFECT: bool = false;
587+
}
588+
589+
// SAFETY: `CaseMappingIter` has no subtypes/supertypes
590+
unsafe impl TrustedRandomAccess for CaseMappingIter {}
591+
592+
impl fmt::Display for CaseMappingIter {
593+
#[inline]
544594
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545-
fmt::Display::fmt(&self.0, f)
595+
for c in self.0.clone() {
596+
f.write_char(c)?;
597+
}
598+
Ok(())
546599
}
547600
}
548601

0 commit comments

Comments
 (0)