Skip to content

Commit 5f6fa45

Browse files
Add PartialEq impls to the character case iterators
Allows easily checking whether a string is in a particular case
1 parent 8f27bdd commit 5f6fa45

File tree

2 files changed

+164
-8
lines changed

2 files changed

+164
-8
lines changed

library/core/src/char/methods.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,8 @@ impl char {
10761076
}
10771077

10781078
/// Returns an iterator that yields the lowercase mapping of this `char` as one or more
1079-
/// `char`s.
1079+
/// `char`s. The iterator also has implementations of [`Display`][core::fmt::Display]
1080+
/// and [`PartialEq`].
10801081
///
10811082
/// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
10821083
///
@@ -1134,6 +1135,13 @@ impl char {
11341135
/// // convert into themselves.
11351136
/// assert_eq!('山'.to_lowercase().to_string(), "山");
11361137
/// ```
1138+
///
1139+
/// Check if a string is in lowercase:
1140+
///
1141+
/// ```
1142+
/// let s = "abcde\u{0301} 山";
1143+
/// assert!(s.chars().all(|c| c.to_lowercase() == c));
1144+
/// ```
11371145
#[must_use = "this returns the lowercased character as a new iterator, \
11381146
without modifying the original"]
11391147
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1143,7 +1151,8 @@ impl char {
11431151
}
11441152

11451153
/// Returns an iterator that yields the titlecase mapping of this `char` as one or more
1146-
/// `char`s.
1154+
/// `char`s. The iterator also has implementations of [`Display`][core::fmt::Display]
1155+
/// and [`PartialEq`].
11471156
///
11481157
/// If this `char` does not have an titlecase mapping, the iterator yields the same `char`.
11491158
///
@@ -1206,6 +1215,21 @@ impl char {
12061215
/// assert_eq!('山'.to_titlecase().to_string(), "山");
12071216
/// ```
12081217
///
1218+
/// Check if a word is in titlecase:
1219+
///
1220+
/// ```
1221+
/// #![feature(titlecase)]
1222+
/// let word = "Dross";
1223+
/// let mut chars = word.chars();
1224+
/// let first_cased_char = chars.find(|c| c.is_cased());
1225+
/// let word_is_in_titlecase = if let Some(f) = first_cased_char {
1226+
/// f.to_titlecase() == f && chars.all(|c| c.to_lowercase() == c)
1227+
/// } else {
1228+
/// true
1229+
/// };
1230+
/// assert!(word_is_in_titlecase);
1231+
/// ```
1232+
///
12091233
/// # Note on locale
12101234
///
12111235
/// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
@@ -1241,7 +1265,8 @@ impl char {
12411265
}
12421266

12431267
/// Returns an iterator that yields the uppercase mapping of this `char` as one or more
1244-
/// `char`s.
1268+
/// `char`s. The iterator also has implementations of [`Display`][core::fmt::Display]
1269+
/// and [`PartialEq`].
12451270
///
12461271
/// If this `char` does not have an uppercase mapping, the iterator yields the same `char`.
12471272
///
@@ -1300,6 +1325,13 @@ impl char {
13001325
/// assert_eq!('山'.to_uppercase().to_string(), "山");
13011326
/// ```
13021327
///
1328+
/// Check if a string is in uppercase:
1329+
///
1330+
/// ```
1331+
/// let s = "ABCDE\u{0301} 山";
1332+
/// assert!(s.chars().all(|c| c.to_uppercase() == c));
1333+
/// ```
1334+
///
13031335
/// # Note on locale
13041336
///
13051337
/// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:

library/core/src/char/mod.rs

Lines changed: 129 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
140140
self::convert::from_digit(num, radix)
141141
}
142142

143-
/// Returns an iterator that yields the hexadecimal Unicode escape of a
143+
/// An iterator that yields the hexadecimal Unicode escape of a
144144
/// character, as `char`s.
145145
///
146146
/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
@@ -373,7 +373,9 @@ impl fmt::Display for EscapeDebug {
373373
}
374374
}
375375

376-
/// Returns an iterator that yields the lowercase equivalent of a `char`.
376+
/// An iterator that yields the lowercase equivalent of a `char`.
377+
/// Also implements [`Display`][`core::fmt::Display`], as well as
378+
/// [`PartialEq`] with itself, the other case iterators, and [`char`].
377379
///
378380
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
379381
/// its documentation for more.
@@ -414,7 +416,46 @@ impl fmt::Display for ToLowercase {
414416
}
415417
}
416418

417-
/// Returns an iterator that yields the titlecase equivalent of a `char`.
419+
// No reflexive impl because it would break type inference
420+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
421+
impl PartialEq<char> for ToLowercase {
422+
#[inline]
423+
fn eq(&self, other: &char) -> bool {
424+
self.0 == *other
425+
}
426+
}
427+
428+
// Not `derive`d so as not to commit to `StructuralPartialEq`
429+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
430+
impl PartialEq for ToLowercase {
431+
#[inline]
432+
fn eq(&self, other: &Self) -> bool {
433+
self.0 == other.0
434+
}
435+
}
436+
437+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
438+
impl Eq for ToLowercase {}
439+
440+
#[unstable(feature = "titlecase", issue = "none")]
441+
impl PartialEq<ToTitlecase> for ToLowercase {
442+
#[inline]
443+
fn eq(&self, other: &ToTitlecase) -> bool {
444+
self.0 == other.0
445+
}
446+
}
447+
448+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
449+
impl PartialEq<ToUppercase> for ToLowercase {
450+
#[inline]
451+
fn eq(&self, other: &ToUppercase) -> bool {
452+
self.0 == other.0
453+
}
454+
}
455+
456+
/// An iterator that yields the titlecase equivalent of a `char`.
457+
/// Also implements [`Display`][`core::fmt::Display`], as well as
458+
/// [`PartialEq`] with itself, the other case iterators, and [`char`].
418459
///
419460
/// This `struct` is created by the [`to_titlecase`] method on [`char`]. See
420461
/// its documentation for more.
@@ -455,7 +496,46 @@ impl fmt::Display for ToTitlecase {
455496
}
456497
}
457498

458-
/// Returns an iterator that yields the uppercase equivalent of a `char`.
499+
// No reflexive impl because it would break type inference
500+
#[unstable(feature = "titlecase", issue = "none")]
501+
impl PartialEq<char> for ToTitlecase {
502+
#[inline]
503+
fn eq(&self, other: &char) -> bool {
504+
self.0 == *other
505+
}
506+
}
507+
508+
// Not `derive`d so as not to commit to `StructuralPartialEq`
509+
#[unstable(feature = "titlecase", issue = "none")]
510+
impl PartialEq for ToTitlecase {
511+
#[inline]
512+
fn eq(&self, other: &Self) -> bool {
513+
self.0 == other.0
514+
}
515+
}
516+
517+
#[unstable(feature = "titlecase", issue = "none")]
518+
impl Eq for ToTitlecase {}
519+
520+
#[unstable(feature = "titlecase", issue = "none")]
521+
impl PartialEq<ToLowercase> for ToTitlecase {
522+
#[inline]
523+
fn eq(&self, other: &ToLowercase) -> bool {
524+
self.0 == other.0
525+
}
526+
}
527+
528+
#[unstable(feature = "titlecase", issue = "none")]
529+
impl PartialEq<ToUppercase> for ToTitlecase {
530+
#[inline]
531+
fn eq(&self, other: &ToUppercase) -> bool {
532+
self.0 == other.0
533+
}
534+
}
535+
536+
/// An iterator that yields the uppercase equivalent of a `char`.
537+
/// Also implements [`Display`][`core::fmt::Display`], as well as
538+
/// [`PartialEq`] with itself, the other case iterators, and [`char`].
459539
///
460540
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
461541
/// its documentation for more.
@@ -496,7 +576,44 @@ impl fmt::Display for ToUppercase {
496576
}
497577
}
498578

499-
#[derive(Debug, Clone)]
579+
// No reflexive impl because it would break type inference
580+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
581+
impl PartialEq<char> for ToUppercase {
582+
#[inline]
583+
fn eq(&self, other: &char) -> bool {
584+
self.0 == *other
585+
}
586+
}
587+
588+
// Not `derive`d so as not to commit to `StructuralPartialEq`
589+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
590+
impl PartialEq for ToUppercase {
591+
#[inline]
592+
fn eq(&self, other: &Self) -> bool {
593+
self.0 == other.0
594+
}
595+
}
596+
597+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
598+
impl Eq for ToUppercase {}
599+
600+
#[stable(feature = "case_iter_partialeq", since = "CURRENT_RUSTC_VERSION")]
601+
impl PartialEq<ToLowercase> for ToUppercase {
602+
#[inline]
603+
fn eq(&self, other: &ToLowercase) -> bool {
604+
self.0 == other.0
605+
}
606+
}
607+
608+
#[unstable(feature = "titlecase", issue = "none")]
609+
impl PartialEq<ToTitlecase> for ToUppercase {
610+
#[inline]
611+
fn eq(&self, other: &ToTitlecase) -> bool {
612+
self.0 == other.0
613+
}
614+
}
615+
616+
#[derive(Clone, Debug, PartialEq, Eq)]
500617
enum CaseMappingIter {
501618
Three(char, char, char),
502619
Two(char, char),
@@ -587,6 +704,13 @@ impl fmt::Display for CaseMappingIter {
587704
}
588705
}
589706

707+
impl PartialEq<char> for CaseMappingIter {
708+
#[inline]
709+
fn eq(&self, other: &char) -> bool {
710+
if let CaseMappingIter::One(c) = self { *c == *other } else { false }
711+
}
712+
}
713+
590714
/// The error type returned when a checked char conversion fails.
591715
#[stable(feature = "u8_from_char", since = "1.59.0")]
592716
#[derive(Debug, Copy, Clone, PartialEq, Eq)]

0 commit comments

Comments
 (0)