core/char/methods.rs
1//! impl char {}
2
3#![expect(clippy::manual_is_ascii_check, reason = "this module implements various is_ascii checks")]
4
5use super::*;
6use crate::panic::const_panic;
7use crate::slice;
8use crate::str::from_utf8_unchecked_mut;
9use crate::ub_checks::assert_unsafe_precondition;
10use crate::unicode::{self, conversions};
11
12impl char {
13 /// The lowest valid code point a `char` can have, `'\0'`.
14 ///
15 /// Unlike integer types, `char` actually has a gap in the middle,
16 /// meaning that the range of possible `char`s is smaller than you
17 /// might expect. Ranges of `char` will automatically hop this gap
18 /// for you:
19 ///
20 /// ```
21 /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
22 /// let size = (char::MIN..=char::MAX).count() as u32;
23 /// assert!(size < dist);
24 /// ```
25 ///
26 /// Despite this gap, the `MIN` and [`MAX`] values can be used as bounds for
27 /// all `char` values.
28 ///
29 /// [`MAX`]: char::MAX
30 ///
31 /// # Examples
32 ///
33 /// ```
34 /// # fn something_which_returns_char() -> char { 'a' }
35 /// let c: char = something_which_returns_char();
36 /// assert!(char::MIN <= c);
37 ///
38 /// let value_at_min = u32::from(char::MIN);
39 /// assert_eq!(char::from_u32(value_at_min), Some('\0'));
40 /// ```
41 #[stable(feature = "char_min", since = "1.83.0")]
42 pub const MIN: char = '\0';
43
44 /// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
45 ///
46 /// Unlike integer types, `char` actually has a gap in the middle,
47 /// meaning that the range of possible `char`s is smaller than you
48 /// might expect. Ranges of `char` will automatically hop this gap
49 /// for you:
50 ///
51 /// ```
52 /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
53 /// let size = (char::MIN..=char::MAX).count() as u32;
54 /// assert!(size < dist);
55 /// ```
56 ///
57 /// Despite this gap, the [`MIN`] and `MAX` values can be used as bounds for
58 /// all `char` values.
59 ///
60 /// [`MIN`]: char::MIN
61 ///
62 /// # Examples
63 ///
64 /// ```
65 /// # fn something_which_returns_char() -> char { 'a' }
66 /// let c: char = something_which_returns_char();
67 /// assert!(c <= char::MAX);
68 ///
69 /// let value_at_max = u32::from(char::MAX);
70 /// assert_eq!(char::from_u32(value_at_max), Some('\u{10FFFF}'));
71 /// assert_eq!(char::from_u32(value_at_max + 1), None);
72 /// ```
73 #[stable(feature = "assoc_char_consts", since = "1.52.0")]
74 pub const MAX: char = '\u{10FFFF}';
75
76 /// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
77 /// UTF-8 encoding.
78 #[stable(feature = "char_max_len_assoc", since = "1.93.0")]
79 pub const MAX_LEN_UTF8: usize = 4;
80
81 /// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
82 /// to UTF-16 encoding.
83 #[stable(feature = "char_max_len_assoc", since = "1.93.0")]
84 pub const MAX_LEN_UTF16: usize = 2;
85
86 /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
87 /// decoding error.
88 ///
89 /// It can occur, for example, when giving ill-formed UTF-8 bytes to
90 /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy).
91 #[stable(feature = "assoc_char_consts", since = "1.52.0")]
92 pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
93
94 /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
95 /// `char` and `str` methods are based on.
96 ///
97 /// New versions of Unicode are released regularly, and subsequently all methods
98 /// in the standard library depending on Unicode are updated. Therefore, the
99 /// behavior of some `char` and `str` methods, and the value of this constant,
100 /// change over time (within the boundaries of Unicode's [stability policies]).
101 /// This is *not* considered to be a breaking change.
102 ///
103 /// [stability policies]: https://www.unicode.org/policies/stability_policy.html
104 ///
105 /// The version numbering scheme is explained in
106 /// [Section 3.1 (Version Numbering)] of the Unicode Standard.
107 ///
108 /// [Section 3.1 (Version Numbering)]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G49512
109 #[stable(feature = "assoc_char_consts", since = "1.52.0")]
110 pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION;
111
112 /// Creates an iterator over the native endian UTF-16 encoded code points in `iter`,
113 /// returning unpaired surrogates as `Err`s.
114 ///
115 /// # Examples
116 ///
117 /// Basic usage:
118 ///
119 /// ```
120 /// // 𝄞mus<invalid>ic<invalid>
121 /// let v = [
122 /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
123 /// ];
124 ///
125 /// assert_eq!(
126 /// char::decode_utf16(v)
127 /// .map(|r| r.map_err(|e| e.unpaired_surrogate()))
128 /// .collect::<Vec<_>>(),
129 /// vec![
130 /// Ok('𝄞'),
131 /// Ok('m'), Ok('u'), Ok('s'),
132 /// Err(0xDD1E),
133 /// Ok('i'), Ok('c'),
134 /// Err(0xD834)
135 /// ]
136 /// );
137 /// ```
138 ///
139 /// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
140 ///
141 /// ```
142 /// // 𝄞mus<invalid>ic<invalid>
143 /// let v = [
144 /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
145 /// ];
146 ///
147 /// assert_eq!(
148 /// char::decode_utf16(v)
149 /// .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
150 /// .collect::<String>(),
151 /// "𝄞mus�ic�"
152 /// );
153 /// ```
154 #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
155 #[inline]
156 #[ferrocene::prevalidated]
157 pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
158 super::decode::decode_utf16(iter)
159 }
160
161 /// Converts a `u32` to a `char`.
162 ///
163 /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
164 /// [`as`](../std/keyword.as.html):
165 ///
166 /// ```
167 /// let c = '💯';
168 /// let i = c as u32;
169 ///
170 /// assert_eq!(128175, i);
171 /// ```
172 ///
173 /// However, the reverse is not true: not all valid [`u32`]s are valid
174 /// `char`s. `from_u32()` will return `None` if the input is not a valid value
175 /// for a `char`.
176 ///
177 /// For an unsafe version of this function which ignores these checks, see
178 /// [`from_u32_unchecked`].
179 ///
180 /// [`from_u32_unchecked`]: #method.from_u32_unchecked
181 ///
182 /// # Examples
183 ///
184 /// Basic usage:
185 ///
186 /// ```
187 /// let c = char::from_u32(0x2764);
188 ///
189 /// assert_eq!(Some('❤'), c);
190 /// ```
191 ///
192 /// Returning `None` when the input is not a valid `char`:
193 ///
194 /// ```
195 /// let c = char::from_u32(0x110000);
196 ///
197 /// assert_eq!(None, c);
198 /// ```
199 #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
200 #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
201 #[must_use]
202 #[inline]
203 pub const fn from_u32(i: u32) -> Option<char> {
204 super::convert::from_u32(i)
205 }
206
207 /// Converts a `u32` to a `char`, ignoring validity.
208 ///
209 /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
210 /// `as`:
211 ///
212 /// ```
213 /// let c = '💯';
214 /// let i = c as u32;
215 ///
216 /// assert_eq!(128175, i);
217 /// ```
218 ///
219 /// However, the reverse is not true: not all valid [`u32`]s are valid
220 /// `char`s. `from_u32_unchecked()` will ignore this, and blindly cast to
221 /// `char`, possibly creating an invalid one.
222 ///
223 /// # Safety
224 ///
225 /// This function is unsafe, as it may construct invalid `char` values.
226 ///
227 /// For a safe version of this function, see the [`from_u32`] function.
228 ///
229 /// [`from_u32`]: #method.from_u32
230 ///
231 /// # Examples
232 ///
233 /// Basic usage:
234 ///
235 /// ```
236 /// let c = unsafe { char::from_u32_unchecked(0x2764) };
237 ///
238 /// assert_eq!('❤', c);
239 /// ```
240 #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
241 #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
242 #[must_use]
243 #[inline]
244 #[ferrocene::prevalidated]
245 pub const unsafe fn from_u32_unchecked(i: u32) -> char {
246 // SAFETY: the safety contract must be upheld by the caller.
247 unsafe { super::convert::from_u32_unchecked(i) }
248 }
249
250 /// Converts a digit in the given radix to a `char`.
251 ///
252 /// A 'radix' here is sometimes also called a 'base'. A radix of two
253 /// indicates a binary number, a radix of ten, decimal, and a radix of
254 /// sixteen, hexadecimal, to give some common values. Arbitrary
255 /// radices are supported.
256 ///
257 /// `from_digit()` will return `None` if the input is not a digit in
258 /// the given radix.
259 ///
260 /// # Panics
261 ///
262 /// Panics if given a radix larger than 36.
263 ///
264 /// # Examples
265 ///
266 /// Basic usage:
267 ///
268 /// ```
269 /// let c = char::from_digit(4, 10);
270 ///
271 /// assert_eq!(Some('4'), c);
272 ///
273 /// // Decimal 11 is a single digit in base 16
274 /// let c = char::from_digit(11, 16);
275 ///
276 /// assert_eq!(Some('b'), c);
277 /// ```
278 ///
279 /// Returning `None` when the input is not a digit:
280 ///
281 /// ```
282 /// let c = char::from_digit(20, 10);
283 ///
284 /// assert_eq!(None, c);
285 /// ```
286 ///
287 /// Passing a large radix, causing a panic:
288 ///
289 /// ```should_panic
290 /// // this panics
291 /// let _c = char::from_digit(1, 37);
292 /// ```
293 #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
294 #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
295 #[must_use]
296 #[inline]
297 pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
298 super::convert::from_digit(num, radix)
299 }
300
301 /// Checks if a `char` is a digit in the given radix.
302 ///
303 /// A 'radix' here is sometimes also called a 'base'. A radix of two
304 /// indicates a binary number, a radix of ten, decimal, and a radix of
305 /// sixteen, hexadecimal, to give some common values. Arbitrary
306 /// radices are supported.
307 ///
308 /// Compared to [`is_numeric()`], this function only recognizes the characters
309 /// `0-9`, `a-z` and `A-Z`.
310 ///
311 /// 'Digit' is defined to be only the following characters:
312 ///
313 /// * `0-9`
314 /// * `a-z`
315 /// * `A-Z`
316 ///
317 /// For a more comprehensive understanding of 'digit', see [`is_numeric()`].
318 ///
319 /// [`is_numeric()`]: #method.is_numeric
320 ///
321 /// # Panics
322 ///
323 /// Panics if given a radix smaller than 2 or larger than 36.
324 ///
325 /// # Examples
326 ///
327 /// Basic usage:
328 ///
329 /// ```
330 /// assert!('1'.is_digit(10));
331 /// assert!('f'.is_digit(16));
332 /// assert!(!'f'.is_digit(10));
333 /// ```
334 ///
335 /// Passing a large radix, causing a panic:
336 ///
337 /// ```should_panic
338 /// // this panics
339 /// '1'.is_digit(37);
340 /// ```
341 ///
342 /// Passing a small radix, causing a panic:
343 ///
344 /// ```should_panic
345 /// // this panics
346 /// '1'.is_digit(1);
347 /// ```
348 #[stable(feature = "rust1", since = "1.0.0")]
349 #[rustc_const_stable(feature = "const_char_classify", since = "1.87.0")]
350 #[expect(clippy::to_digit_is_some, reason = "implements is_digit")]
351 #[inline]
352 pub const fn is_digit(self, radix: u32) -> bool {
353 self.to_digit(radix).is_some()
354 }
355
356 /// Converts a `char` to a digit in the given radix.
357 ///
358 /// A 'radix' here is sometimes also called a 'base'. A radix of two
359 /// indicates a binary number, a radix of ten, decimal, and a radix of
360 /// sixteen, hexadecimal, to give some common values. Arbitrary
361 /// radices are supported.
362 ///
363 /// 'Digit' is defined to be only the following characters:
364 ///
365 /// * `0-9`
366 /// * `a-z`
367 /// * `A-Z`
368 ///
369 /// # Errors
370 ///
371 /// Returns `None` if the `char` does not refer to a digit in the given radix.
372 ///
373 /// # Panics
374 ///
375 /// Panics if given a radix smaller than 2 or larger than 36.
376 ///
377 /// # Examples
378 ///
379 /// Basic usage:
380 ///
381 /// ```
382 /// assert_eq!('1'.to_digit(10), Some(1));
383 /// assert_eq!('f'.to_digit(16), Some(15));
384 /// ```
385 ///
386 /// Passing a non-digit results in failure:
387 ///
388 /// ```
389 /// assert_eq!('f'.to_digit(10), None);
390 /// assert_eq!('z'.to_digit(16), None);
391 /// ```
392 ///
393 /// Passing a large radix, causing a panic:
394 ///
395 /// ```should_panic
396 /// // this panics
397 /// let _ = '1'.to_digit(37);
398 /// ```
399 /// Passing a small radix, causing a panic:
400 ///
401 /// ```should_panic
402 /// // this panics
403 /// let _ = '1'.to_digit(1);
404 /// ```
405 #[stable(feature = "rust1", since = "1.0.0")]
406 #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
407 #[rustc_diagnostic_item = "char_to_digit"]
408 #[must_use = "this returns the result of the operation, \
409 without modifying the original"]
410 #[inline]
411 #[ferrocene::prevalidated]
412 pub const fn to_digit(self, radix: u32) -> Option<u32> {
413 assert!(
414 radix >= 2 && radix <= 36,
415 "to_digit: invalid radix -- radix must be in the range 2 to 36 inclusive"
416 );
417 // check radix to remove letter handling code when radix is a known constant
418 let value = if self > '9' && radix > 10 {
419 // mask to convert ASCII letters to uppercase
420 const TO_UPPERCASE_MASK: u32 = !0b0010_0000;
421 // Converts an ASCII letter to its corresponding integer value:
422 // A-Z => 10-35, a-z => 10-35. Other characters produce values >= 36.
423 //
424 // Add Overflow Safety:
425 // By applying the mask after the subtraction, the first addendum is
426 // constrained such that it never exceeds u32::MAX - 0x20.
427 ((self as u32).wrapping_sub('A' as u32) & TO_UPPERCASE_MASK) + 10
428 } else {
429 // convert digit to value, non-digits wrap to values > 36
430 (self as u32).wrapping_sub('0' as u32)
431 };
432 // FIXME(const-hack): once then_some is const fn, use it here
433 if value < radix { Some(value) } else { None }
434 }
435
436 /// Returns an iterator that yields the hexadecimal Unicode escape of a
437 /// character as `char`s.
438 ///
439 /// This will escape characters with the Rust syntax of the form
440 /// `\u{NNNNNN}` where `NNNNNN` is a hexadecimal representation.
441 ///
442 /// # Examples
443 ///
444 /// As an iterator:
445 ///
446 /// ```
447 /// for c in '❤'.escape_unicode() {
448 /// print!("{c}");
449 /// }
450 /// println!();
451 /// ```
452 ///
453 /// Using `println!` directly:
454 ///
455 /// ```
456 /// println!("{}", '❤'.escape_unicode());
457 /// ```
458 ///
459 /// Both are equivalent to:
460 ///
461 /// ```
462 /// println!("\\u{{2764}}");
463 /// ```
464 ///
465 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
466 ///
467 /// ```
468 /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
469 /// ```
470 #[must_use = "this returns the escaped char as an iterator, \
471 without modifying the original"]
472 #[stable(feature = "rust1", since = "1.0.0")]
473 #[inline]
474 #[ferrocene::prevalidated]
475 pub fn escape_unicode(self) -> EscapeUnicode {
476 EscapeUnicode::new(self)
477 }
478
479 /// An extended version of `escape_debug` that optionally permits escaping
480 /// single quotes and double quotes. This allows escaping single quotes in
481 /// characters, and double quotes in strings.
482 #[inline]
483 #[ferrocene::prevalidated]
484 pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
485 match self {
486 // Special escapes
487 '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
488 '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
489 '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus),
490 '\n' => EscapeDebug::backslash(ascii::Char::SmallN),
491 '\t' => EscapeDebug::backslash(ascii::Char::SmallT),
492 '\r' => EscapeDebug::backslash(ascii::Char::SmallR),
493 '\0' => EscapeDebug::backslash(ascii::Char::Digit0),
494
495 // ASCII fast path,
496 // plus U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK
497 // and U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
498 // which should not be escaped despite being grapheme extenders.
499 '\x20'..='\x7E' | '\u{FF9E}' | '\u{FF9F}' => EscapeDebug::printable(self),
500
501 _ if self.is_control()
502 || self.is_private_use()
503 || self.is_whitespace()
504 || self.is_grapheme_extender()
505 || self.is_default_ignorable()
506 || self.is_format_control()
507 || !self.is_assigned() =>
508 {
509 EscapeDebug::unicode(self)
510 }
511
512 _ => EscapeDebug::printable(self),
513 }
514 }
515
516 /// Returns an iterator that yields the literal escape code of a character
517 /// as `char`s.
518 ///
519 /// This will escape the characters similar to the [`Debug`](core::fmt::Debug) implementations
520 /// of `str` or `char`.
521 ///
522 /// # Examples
523 ///
524 /// As an iterator:
525 ///
526 /// ```
527 /// for c in '\n'.escape_debug() {
528 /// print!("{c}");
529 /// }
530 /// println!();
531 /// ```
532 ///
533 /// Using `println!` directly:
534 ///
535 /// ```
536 /// println!("{}", '\n'.escape_debug());
537 /// ```
538 ///
539 /// Both are equivalent to:
540 ///
541 /// ```
542 /// println!("\\n");
543 /// ```
544 ///
545 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
546 ///
547 /// ```
548 /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
549 /// ```
550 #[must_use = "this returns the escaped char as an iterator, \
551 without modifying the original"]
552 #[stable(feature = "char_escape_debug", since = "1.20.0")]
553 #[inline]
554 #[ferrocene::prevalidated]
555 pub fn escape_debug(self) -> EscapeDebug {
556 self.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)
557 }
558
559 /// Returns an iterator that yields the literal escape code of a character
560 /// as `char`s.
561 ///
562 /// The default is chosen with a bias toward producing literals that are
563 /// legal in a variety of languages, including C++11 and similar C-family
564 /// languages. The exact rules are:
565 ///
566 /// * Tab is escaped as `\t`.
567 /// * Carriage return is escaped as `\r`.
568 /// * Line feed is escaped as `\n`.
569 /// * Single quote is escaped as `\'`.
570 /// * Double quote is escaped as `\"`.
571 /// * Backslash is escaped as `\\`.
572 /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
573 /// inclusive is not escaped.
574 /// * All other characters are given hexadecimal Unicode escapes; see
575 /// [`escape_unicode`].
576 ///
577 /// [`escape_unicode`]: #method.escape_unicode
578 ///
579 /// # Examples
580 ///
581 /// As an iterator:
582 ///
583 /// ```
584 /// for c in '"'.escape_default() {
585 /// print!("{c}");
586 /// }
587 /// println!();
588 /// ```
589 ///
590 /// Using `println!` directly:
591 ///
592 /// ```
593 /// println!("{}", '"'.escape_default());
594 /// ```
595 ///
596 /// Both are equivalent to:
597 ///
598 /// ```
599 /// println!("\\\"");
600 /// ```
601 ///
602 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
603 ///
604 /// ```
605 /// assert_eq!('"'.escape_default().to_string(), "\\\"");
606 /// ```
607 #[must_use = "this returns the escaped char as an iterator, \
608 without modifying the original"]
609 #[stable(feature = "rust1", since = "1.0.0")]
610 #[inline]
611 #[ferrocene::prevalidated]
612 pub fn escape_default(self) -> EscapeDefault {
613 match self {
614 '\t' => EscapeDefault::backslash(ascii::Char::SmallT),
615 '\r' => EscapeDefault::backslash(ascii::Char::SmallR),
616 '\n' => EscapeDefault::backslash(ascii::Char::SmallN),
617 '\\' | '\'' | '\"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
618 '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
619 _ => EscapeDefault::unicode(self),
620 }
621 }
622
623 /// Returns the number of bytes this `char` would need if encoded in UTF-8.
624 ///
625 /// That number of bytes is always between 1 and 4, inclusive.
626 ///
627 /// # Examples
628 ///
629 /// Basic usage:
630 ///
631 /// ```
632 /// let len = 'A'.len_utf8();
633 /// assert_eq!(len, 1);
634 ///
635 /// let len = 'ß'.len_utf8();
636 /// assert_eq!(len, 2);
637 ///
638 /// let len = 'ℝ'.len_utf8();
639 /// assert_eq!(len, 3);
640 ///
641 /// let len = '💣'.len_utf8();
642 /// assert_eq!(len, 4);
643 /// ```
644 ///
645 /// The `&str` type guarantees that its contents are UTF-8, and so we can compare the length it
646 /// would take if each code point was represented as a `char` vs in the `&str` itself:
647 ///
648 /// ```
649 /// // as chars
650 /// let eastern = '東';
651 /// let capital = '京';
652 ///
653 /// // both can be represented as three bytes
654 /// assert_eq!(3, eastern.len_utf8());
655 /// assert_eq!(3, capital.len_utf8());
656 ///
657 /// // as a &str, these two are encoded in UTF-8
658 /// let tokyo = "東京";
659 ///
660 /// let len = eastern.len_utf8() + capital.len_utf8();
661 ///
662 /// // we can see that they take six bytes total...
663 /// assert_eq!(6, tokyo.len());
664 ///
665 /// // ... just like the &str
666 /// assert_eq!(len, tokyo.len());
667 /// ```
668 #[stable(feature = "rust1", since = "1.0.0")]
669 #[rustc_const_stable(feature = "const_char_len_utf", since = "1.52.0")]
670 #[inline]
671 #[must_use]
672 #[ferrocene::prevalidated]
673 pub const fn len_utf8(self) -> usize {
674 len_utf8(self as u32)
675 }
676
677 /// Returns the number of 16-bit code units this `char` would need if
678 /// encoded in UTF-16.
679 ///
680 /// That number of code units is always either 1 or 2, for unicode scalar values in
681 /// the [basic multilingual plane] or [supplementary planes] respectively.
682 ///
683 /// See the documentation for [`len_utf8()`] for more explanation of this
684 /// concept. This function is a mirror, but for UTF-16 instead of UTF-8.
685 ///
686 /// [basic multilingual plane]: http://www.unicode.org/glossary/#basic_multilingual_plane
687 /// [supplementary planes]: http://www.unicode.org/glossary/#supplementary_planes
688 /// [`len_utf8()`]: #method.len_utf8
689 ///
690 /// # Examples
691 ///
692 /// Basic usage:
693 ///
694 /// ```
695 /// let n = 'ß'.len_utf16();
696 /// assert_eq!(n, 1);
697 ///
698 /// let len = '💣'.len_utf16();
699 /// assert_eq!(len, 2);
700 /// ```
701 #[stable(feature = "rust1", since = "1.0.0")]
702 #[rustc_const_stable(feature = "const_char_len_utf", since = "1.52.0")]
703 #[inline]
704 #[must_use]
705 pub const fn len_utf16(self) -> usize {
706 len_utf16(self as u32)
707 }
708
709 /// Encodes this character as UTF-8 into the provided byte buffer,
710 /// and then returns the subslice of the buffer that contains the encoded character.
711 ///
712 /// # Panics
713 ///
714 /// Panics if the buffer is not large enough.
715 /// A buffer of length four is large enough to encode any `char`.
716 ///
717 /// # Examples
718 ///
719 /// In both of these examples, 'ß' takes two bytes to encode.
720 ///
721 /// ```
722 /// let mut b = [0; 2];
723 ///
724 /// let result = 'ß'.encode_utf8(&mut b);
725 ///
726 /// assert_eq!(result, "ß");
727 ///
728 /// assert_eq!(result.len(), 2);
729 /// ```
730 ///
731 /// A buffer that's too small:
732 ///
733 /// ```should_panic
734 /// let mut b = [0; 1];
735 ///
736 /// // this panics
737 /// 'ß'.encode_utf8(&mut b);
738 /// ```
739 #[stable(feature = "unicode_encode_char", since = "1.15.0")]
740 #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")]
741 #[inline]
742 #[ferrocene::prevalidated]
743 pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
744 // SAFETY: `char` is not a surrogate, so this is valid UTF-8.
745 unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) }
746 }
747
748 /// Encodes this character as native endian UTF-16 into the provided `u16` buffer,
749 /// and then returns the subslice of the buffer that contains the encoded character.
750 ///
751 /// # Panics
752 ///
753 /// Panics if the buffer is not large enough.
754 /// A buffer of length 2 is large enough to encode any `char`.
755 ///
756 /// # Examples
757 ///
758 /// In both of these examples, '𝕊' takes two `u16`s to encode.
759 ///
760 /// ```
761 /// let mut b = [0; 2];
762 ///
763 /// let result = '𝕊'.encode_utf16(&mut b);
764 ///
765 /// assert_eq!(result.len(), 2);
766 /// ```
767 ///
768 /// A buffer that's too small:
769 ///
770 /// ```should_panic
771 /// let mut b = [0; 1];
772 ///
773 /// // this panics
774 /// '𝕊'.encode_utf16(&mut b);
775 /// ```
776 #[stable(feature = "unicode_encode_char", since = "1.15.0")]
777 #[rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0")]
778 #[inline]
779 pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
780 encode_utf16_raw(self as u32, dst)
781 }
782
783 /// Returns `true` if this `char` has the `Alphabetic` property.
784 ///
785 /// `Alphabetic` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and
786 /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
787 ///
788 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G32524
789 /// [specified]: https://www.unicode.org/reports/tr44/#Alphabetic
790 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
791 ///
792 /// # Examples
793 ///
794 /// Basic usage:
795 ///
796 /// ```
797 /// assert!('a'.is_alphabetic());
798 /// assert!('京'.is_alphabetic());
799 ///
800 /// let c = '💝';
801 /// // love is many things, but it is not alphabetic
802 /// assert!(!c.is_alphabetic());
803 /// ```
804 #[must_use]
805 #[stable(feature = "rust1", since = "1.0.0")]
806 #[inline]
807 pub fn is_alphabetic(self) -> bool {
808 match self {
809 'a'..='z' | 'A'..='Z' => true,
810 '\0'..='\u{A9}' => false,
811 _ => unicode::Alphabetic(self),
812 }
813 }
814
815 /// Returns `true` if this `char` has the `Cased` property.
816 /// A character is cased if and only if it is uppercase, lowercase, or titlecase.
817 ///
818 /// `Cased` is [described] in Chapter 3 (Character Properties) of the Unicode Standard and
819 /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
820 ///
821 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G44595
822 /// [specified]: https://www.unicode.org/reports/tr44/#Cased
823 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
824 ///
825 /// # Examples
826 ///
827 /// Basic usage:
828 ///
829 /// ```
830 /// #![feature(titlecase)]
831 /// assert!('A'.is_cased());
832 /// assert!('a'.is_cased());
833 /// assert!(!'京'.is_cased());
834 /// ```
835 #[must_use]
836 #[unstable(feature = "titlecase", issue = "153892")]
837 #[inline]
838 pub fn is_cased(self) -> bool {
839 match self {
840 'a'..='z' | 'A'..='Z' => true,
841 '\0'..='\u{A9}' => false,
842 _ => unicode::Lowercase(self) || unicode::Uppercase(self) || unicode::Lt(self),
843 }
844 }
845
846 /// Returns the case of this character:
847 /// [`Some(CharCase::Upper)`][`CharCase::Upper`] if [`self.is_uppercase()`][`char::is_uppercase`],
848 /// [`Some(CharCase::Lower)`][`CharCase::Lower`] if [`self.is_lowercase()`][`char::is_lowercase`],
849 /// [`Some(CharCase::Title)`][`CharCase::Title`] if [`self.is_titlecase()`][`char::is_titlecase`], and
850 /// `None` if [`!self.is_cased()`][`char::is_cased`].
851 ///
852 /// # Examples
853 ///
854 /// ```
855 /// #![feature(titlecase)]
856 /// use core::char::CharCase;
857 /// assert_eq!('a'.case(), Some(CharCase::Lower));
858 /// assert_eq!('δ'.case(), Some(CharCase::Lower));
859 /// assert_eq!('A'.case(), Some(CharCase::Upper));
860 /// assert_eq!('Δ'.case(), Some(CharCase::Upper));
861 /// assert_eq!('Dž'.case(), Some(CharCase::Title));
862 /// assert_eq!('中'.case(), None);
863 /// ```
864 #[must_use]
865 #[unstable(feature = "titlecase", issue = "153892")]
866 #[inline]
867 pub fn case(self) -> Option<CharCase> {
868 match self {
869 'a'..='z' => Some(CharCase::Lower),
870 'A'..='Z' => Some(CharCase::Upper),
871 '\0'..='\u{A9}' => None,
872 _ if unicode::Lowercase(self) => Some(CharCase::Lower),
873 _ if unicode::Uppercase(self) => Some(CharCase::Upper),
874 _ if unicode::Lt(self) => Some(CharCase::Title),
875 _ => None,
876 }
877 }
878
879 /// Returns `true` if this `char` has the `Lowercase` property.
880 ///
881 /// `Lowercase` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and
882 /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
883 ///
884 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G136255
885 /// [specified]: https://www.unicode.org/reports/tr44/#Lowercase
886 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
887 ///
888 /// # Examples
889 ///
890 /// Basic usage:
891 ///
892 /// ```
893 /// assert!('a'.is_lowercase());
894 /// assert!('δ'.is_lowercase());
895 /// assert!(!'A'.is_lowercase());
896 /// assert!(!'Δ'.is_lowercase());
897 ///
898 /// // The various Chinese scripts and punctuation do not have case, and so:
899 /// assert!(!'中'.is_lowercase());
900 /// assert!(!' '.is_lowercase());
901 /// ```
902 ///
903 /// In a const context:
904 ///
905 /// ```
906 /// const CAPITAL_DELTA_IS_LOWERCASE: bool = 'Δ'.is_lowercase();
907 /// assert!(!CAPITAL_DELTA_IS_LOWERCASE);
908 /// ```
909 #[must_use]
910 #[stable(feature = "rust1", since = "1.0.0")]
911 #[rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0")]
912 #[inline]
913 pub const fn is_lowercase(self) -> bool {
914 match self {
915 'a'..='z' => true,
916 '\0'..='\u{A9}' => false,
917 _ => unicode::Lowercase(self),
918 }
919 }
920
921 /// Returns `true` if this `char` is in the general category for titlecase letters.
922 /// Conceptually, these characters consist of an uppercase portion followed by a lowercase portion.
923 ///
924 /// Titlecase letters (code points with the general category of `Lt`) are [described] in Chapter 4
925 /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character
926 /// Database [`UnicodeData.txt`].
927 ///
928 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G124722
929 /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
930 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
931 ///
932 /// # Examples
933 ///
934 /// Basic usage:
935 ///
936 /// ```
937 /// #![feature(titlecase)]
938 /// assert!('Dž'.is_titlecase());
939 /// assert!('ῼ'.is_titlecase());
940 /// assert!(!'D'.is_titlecase());
941 /// assert!(!'z'.is_titlecase());
942 /// assert!(!'中'.is_titlecase());
943 /// assert!(!' '.is_titlecase());
944 /// ```
945 #[must_use]
946 #[unstable(feature = "titlecase", issue = "153892")]
947 #[inline]
948 pub fn is_titlecase(self) -> bool {
949 match self {
950 '\0'..='\u{01C4}' => false,
951 _ => unicode::Lt(self),
952 }
953 }
954
955 /// Returns `true` if this `char` has the `Uppercase` property.
956 ///
957 /// `Uppercase` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and
958 /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
959 ///
960 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G136255
961 /// [specified]: https://www.unicode.org/reports/tr44/#Uppercase
962 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
963 ///
964 /// # Examples
965 ///
966 /// Basic usage:
967 ///
968 /// ```
969 /// assert!(!'a'.is_uppercase());
970 /// assert!(!'δ'.is_uppercase());
971 /// assert!('A'.is_uppercase());
972 /// assert!('Δ'.is_uppercase());
973 ///
974 /// // The various Chinese scripts and punctuation do not have case, and so:
975 /// assert!(!'中'.is_uppercase());
976 /// assert!(!' '.is_uppercase());
977 /// ```
978 ///
979 /// In a const context:
980 ///
981 /// ```
982 /// const CAPITAL_DELTA_IS_UPPERCASE: bool = 'Δ'.is_uppercase();
983 /// assert!(CAPITAL_DELTA_IS_UPPERCASE);
984 /// ```
985 #[must_use]
986 #[stable(feature = "rust1", since = "1.0.0")]
987 #[rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0")]
988 #[inline]
989 pub const fn is_uppercase(self) -> bool {
990 match self {
991 'A'..='Z' => true,
992 '\0'..='\u{BF}' => false,
993 _ => unicode::Uppercase(self),
994 }
995 }
996
997 /// Returns `true` if this `char` has one of the general categories for numbers.
998 ///
999 /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
1000 /// characters, and `No` for other numeric characters) are [specified] in the Unicode Character
1001 /// Database [`UnicodeData.txt`].
1002 ///
1003 /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'.
1004 /// If you want everything including characters with overlapping purposes, then you might want to use
1005 /// a Unicode or language-processing library that exposes the appropriate character properties
1006 /// (e.g. [`Numeric_Type`]) instead of looking at the Unicode categories.
1007 ///
1008 /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use
1009 /// `is_ascii_digit` or `is_digit` instead.
1010 ///
1011 /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1012 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1013 /// [`Numeric_Type`]: https://www.unicode.org/reports/tr44/#Numeric_Type
1014 ///
1015 /// # Examples
1016 ///
1017 /// Basic usage:
1018 ///
1019 /// ```
1020 /// assert!('٣'.is_numeric());
1021 /// assert!('7'.is_numeric());
1022 /// assert!('৬'.is_numeric());
1023 /// assert!('¾'.is_numeric());
1024 /// assert!('①'.is_numeric());
1025 /// assert!(!'K'.is_numeric());
1026 /// assert!(!'و'.is_numeric());
1027 /// assert!(!'藏'.is_numeric());
1028 /// assert!(!'三'.is_numeric());
1029 /// ```
1030 #[must_use]
1031 #[stable(feature = "rust1", since = "1.0.0")]
1032 #[inline]
1033 pub fn is_numeric(self) -> bool {
1034 match self {
1035 '0'..='9' => true,
1036 '\0'..='\u{B1}' => false,
1037 _ => unicode::N(self),
1038 }
1039 }
1040
1041 /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`].
1042 ///
1043 /// [`is_alphabetic()`]: Self::is_alphabetic
1044 /// [`is_numeric()`]: Self::is_numeric
1045 ///
1046 /// # Examples
1047 ///
1048 /// Basic usage:
1049 ///
1050 /// ```
1051 /// assert!('٣'.is_alphanumeric());
1052 /// assert!('7'.is_alphanumeric());
1053 /// assert!('৬'.is_alphanumeric());
1054 /// assert!('¾'.is_alphanumeric());
1055 /// assert!('①'.is_alphanumeric());
1056 /// assert!('K'.is_alphanumeric());
1057 /// assert!('و'.is_alphanumeric());
1058 /// assert!('藏'.is_alphanumeric());
1059 /// ```
1060 #[must_use]
1061 #[stable(feature = "rust1", since = "1.0.0")]
1062 #[inline]
1063 pub fn is_alphanumeric(self) -> bool {
1064 match self {
1065 'a'..='z' | 'A'..='Z' | '0'..='9' => true,
1066 '\0'..='\u{A9}' => false,
1067 _ => unicode::Alphabetic(self) || unicode::N(self),
1068 }
1069 }
1070
1071 /// Returns `true` if this `char` has the `White_Space` property.
1072 ///
1073 /// `White_Space` is [specified] in the Unicode Character Database [`PropList.txt`].
1074 ///
1075 /// [specified]: https://www.unicode.org/reports/tr44/#White_Space
1076 /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
1077 ///
1078 /// # Examples
1079 ///
1080 /// Basic usage:
1081 ///
1082 /// ```
1083 /// assert!(' '.is_whitespace());
1084 ///
1085 /// // line break
1086 /// assert!('\n'.is_whitespace());
1087 ///
1088 /// // a non-breaking space
1089 /// assert!('\u{A0}'.is_whitespace());
1090 ///
1091 /// assert!(!'越'.is_whitespace());
1092 /// ```
1093 #[must_use]
1094 #[stable(feature = "rust1", since = "1.0.0")]
1095 #[rustc_const_stable(feature = "const_char_classify", since = "1.87.0")]
1096 #[inline]
1097 #[ferrocene::prevalidated]
1098 pub const fn is_whitespace(self) -> bool {
1099 match self {
1100 ' ' | '\x09'..='\x0d' => true,
1101 '\0'..='\u{84}' => false,
1102 _ => unicode::White_Space(self),
1103 }
1104 }
1105
1106 /// Returns `true` if this `char` has the general category for control codes.
1107 ///
1108 /// Control codes (code points with the general category of `Cc`) are [described] in Chapter 23
1109 /// (Special Areas and Format Characters) of the Unicode Standard, and [specified] in the Unicode Character
1110 /// Database [`UnicodeData.txt`]. The full set of Unicode control codes is
1111 /// `'\0'..='\x1f' | '\x7f'..='\u{9f}'`, and will never change.
1112 ///
1113 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G20365
1114 /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1115 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1116 ///
1117 /// # Examples
1118 ///
1119 /// Basic usage:
1120 ///
1121 /// ```
1122 /// assert!('\t'.is_control());
1123 /// assert!('\n'.is_control());
1124 /// assert!('\u{9C}'.is_control()); // STRING TERMINATOR
1125 /// assert!(!'q'.is_control());
1126 /// ```
1127 #[ferrocene::prevalidated]
1128 #[must_use]
1129 #[stable(feature = "rust1", since = "1.0.0")]
1130 #[rustc_const_stable(feature = "const_is_control", since = "1.97.0")]
1131 #[inline]
1132 pub const fn is_control(self) -> bool {
1133 // According to
1134 // https://www.unicode.org/policies/stability_policy.html#Property_Value,
1135 // the set of codepoints in `Cc` will never change.
1136 // So we can just hard-code the patterns to match against instead of using a table.
1137 matches!(self, '\0'..='\x1f' | '\x7f'..='\u{9f}')
1138 }
1139
1140 /// Returns `true` if this `char` has the general category for [private-use characters].
1141 /// These characters do not have an interpretation specified by Unicode; individual programs
1142 /// and users are free to assign them whatever meaning they like.
1143 ///
1144 /// [private-use characters]: https://www.unicode.org/faq/private_use#private_use
1145 ///
1146 /// Private-use characters (code points with the general category of `Co`) are [described] in Chapter 23
1147 /// (Special Areas and Format Characters) of the Unicode Standard, and [specified] in the
1148 /// Unicode Character Database [`UnicodeData.txt`]. The full set of private-use characters is
1149 /// `'\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}'`,
1150 /// and will never change.
1151 ///
1152 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G19184
1153 /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1154 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1155 ///
1156 #[ferrocene::prevalidated]
1157 #[must_use]
1158 #[unstable(feature = "char_unassigned_private_use", issue = "158322")]
1159 #[inline]
1160 pub const fn is_private_use(self) -> bool {
1161 // According to
1162 // https://www.unicode.org/policies/stability_policy.html#Property_Value,
1163 // the set of codepoints in `Co` will never change.
1164 // So we can just hard-code the patterns to match against instead of using a table.
1165 matches!(self, '\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}')
1166 }
1167
1168 /// Returns `true` if this `char` has the general category for format control characters.
1169 ///
1170 /// Format controls (code points with the general category of `Cf`) are [described] in Chapter 4
1171 /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character
1172 /// Database [`UnicodeData.txt`].
1173 ///
1174 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
1175 /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1176 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1177 ///
1178 /// # Examples
1179 ///
1180 /// Basic usage:
1181 ///
1182 /// ```ignore(private)
1183 /// assert!('\u{AD}'.is_format_control()); // SOFT HYPHEN
1184 /// assert!('\u{200B}'.is_format_control()); // ZERO WIDTH SPACE
1185 /// assert!('\u{E0041}'.is_format_control()); // TAG LATIN CAPITAL LETTER A
1186 /// assert!(''.is_format_control()); // ARABIC END OF AYAH
1187 /// assert!(''.is_format_control()); // EGYPTIAN HIEROGLYPH INSERT AT TOP START
1188 /// assert!(!'q'.is_format_control());
1189 /// ```
1190 #[ferrocene::prevalidated]
1191 #[must_use]
1192 #[inline]
1193 fn is_format_control(self) -> bool {
1194 self > '\u{AC}' && unicode::Cf(self)
1195 }
1196
1197 /// Returns `true` if this `char` has been assigned a meaning by Unicode, as of
1198 /// [`UNICODE_VERSION`].
1199 ///
1200 /// [`UNICODE_VERSION`]: Self::UNICODE_VERSION
1201 ///
1202 /// Many of Unicode's [stability policies] apply only to assigned characters.
1203 ///
1204 /// [stability policies]: https://www.unicode.org/policies/stability_policy.html
1205 ///
1206 /// Currently unassigned characters (characters for which this method returns `false`)
1207 /// may have a meaning assigned in a future version of Unicode,
1208 /// except for the 66 [noncharacters] which will never be assigned a meaning.
1209 ///
1210 /// [noncharacters]: https://www.unicode.org/faq/private_use.html#noncharacters
1211 ///
1212 /// A character is considered assigned if it is present in [`UnicodeData.txt`].
1213 /// Unassigned characters have general category `Cn`, as [described] in Chapter 4
1214 /// (Character Properties) of the Unicode Standard.
1215 ///
1216 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1217 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
1218 ///
1219 /// # Examples
1220 ///
1221 /// Basic usage:
1222 ///
1223 /// ```
1224 /// #![feature(char_unassigned_private_use)]
1225 /// assert!('γ'.is_assigned()); // once a character is assigned, it stays assigned forever
1226 /// assert!(!'\u{FFFE}'.is_assigned()); // noncharacter, will never be assigned
1227 ///
1228 /// // Not currently assigned, but may be in the future,
1229 /// // so we shouldn't rely on the current status
1230 /// /* assert!(!'\u{7AAAA}'.is_assigned()); */
1231 /// ```
1232 #[ferrocene::prevalidated]
1233 #[must_use]
1234 #[unstable(feature = "char_unassigned_private_use", issue = "158322")]
1235 #[inline]
1236 pub fn is_assigned(self) -> bool {
1237 match self {
1238 '\0'..='\u{377}' => true,
1239 '\u{378}'..='\u{3FFFD}' => !unicode::Cn_planes_0_3(self),
1240 // Assigned character ranges in planes 4 and above.
1241 // `src/tools/unicode-table-generator/src/main.rs` asserts that this is correct
1242 '\u{E0001}'
1243 | '\u{E0020}'..='\u{E007F}'
1244 | '\u{E0100}'..='\u{E01EF}'
1245 | '\u{F0000}'..='\u{FFFFD}'
1246 | '\u{100000}'..='\u{10FFFD}' => true,
1247 _ => false,
1248 }
1249 }
1250
1251 /// Returns `true` if this `char` has the `Default_Ignorable_Code_Point` property.
1252 /// These characters [should be displayed as invisible in fallback rendering](https://www.unicode.org/faq/unsup_char#3).
1253 ///
1254 /// `Default_Ignorable_Code_Point` is [described] in Chapter 5 (Implementation Guidelines) of the Unicode Standard,
1255 /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
1256 ///
1257 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-5/#G40120
1258 /// [specified]: https://www.unicode.org/reports/tr44/#Default_Ignorable_Code_Point
1259 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1260 ///
1261 /// # Examples
1262 ///
1263 /// Basic usage:
1264 ///
1265 /// ```
1266 /// #![feature(default_ignorable)]
1267 /// assert!('\u{AD}'.is_default_ignorable()); // SOFT HYPHEN
1268 /// assert!('\u{115F}'.is_default_ignorable()); // HANGUL CHOSEONG FILLER
1269 /// assert!('\u{200B}'.is_default_ignorable()); // ZERO WIDTH SPACE
1270 /// assert!('\u{E0041}'.is_default_ignorable()); // TAG LATIN CAPITAL LETTER A
1271 /// assert!(!''.is_default_ignorable()); // ARABIC END OF AYAH
1272 /// assert!(!''.is_default_ignorable()); // EGYPTIAN HIEROGLYPH INSERT AT TOP START
1273 /// assert!(!' '.is_default_ignorable());
1274 /// assert!(!'\n'.is_default_ignorable());
1275 /// assert!(!'\0'.is_default_ignorable());
1276 /// assert!(!'q'.is_default_ignorable());
1277 /// ```
1278 #[ferrocene::prevalidated]
1279 #[must_use]
1280 #[unstable(feature = "default_ignorable", issue = "160583")]
1281 #[inline]
1282 pub fn is_default_ignorable(self) -> bool {
1283 self > '\u{AC}' && unicode::Default_Ignorable_Code_Point(self)
1284 }
1285
1286 /// Returns `true` if this `char` has the `Grapheme_Extend` property.
1287 ///
1288 /// `Grapheme_Extend` is [described] in Chapter 3 (Conformance) of the Unicode Standard,
1289 /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
1290 ///
1291 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G41165
1292 /// [specified]: https://www.unicode.org/reports/tr44/#Grapheme_Extend
1293 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1294 #[ferrocene::prevalidated]
1295 #[must_use]
1296 #[inline]
1297 fn is_grapheme_extender(self) -> bool {
1298 self > '\u{02FF}' && unicode::Grapheme_Extend(self)
1299 }
1300
1301 /// Returns `true` if this `char` has the `Case_Ignorable` property. This narrow-use property
1302 /// is used to implement context-dependent casing for the Greek letter sigma (uppercase 'Σ'),
1303 /// which has two lowercase forms.
1304 ///
1305 /// `Case_Ignorable` is [described] in Chapter 3 (Conformance) of the Unicode Core Specification,
1306 /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
1307 /// See those resources, as well as [`to_lowercase()`]'s documentation, for more information.
1308 ///
1309 /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G63116
1310 /// [specified]: https://www.unicode.org/reports/tr44/#Case_Ignorable
1311 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1312 /// [`to_lowercase()`]: Self::to_lowercase()
1313 #[must_use]
1314 #[inline]
1315 #[unstable(feature = "case_ignorable", issue = "154848")]
1316 pub fn is_case_ignorable(self) -> bool {
1317 if self.is_ascii() {
1318 matches!(self, '\'' | '.' | ':' | '^' | '`')
1319 } else {
1320 unicode::Case_Ignorable(self)
1321 }
1322 }
1323
1324 /// Returns an iterator that yields the lowercase mapping of this `char` as one or more
1325 /// `char`s.
1326 ///
1327 /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
1328 ///
1329 /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character
1330 /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1331 ///
1332 /// [ucd]: https://www.unicode.org/reports/tr44/
1333 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1334 ///
1335 /// If this `char` expands to multiple `char`s, the iterator yields the `char`s given by
1336 /// [`SpecialCasing.txt`]. The maximum number of `char`s in a case mapping is 3.
1337 ///
1338 /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1339 /// is independent of context and language. See [below](#notes-on-context-and-locale)
1340 /// for more information.
1341 ///
1342 /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1343 /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1344 ///
1345 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1346 ///
1347 /// # Examples
1348 ///
1349 /// As an iterator:
1350 ///
1351 /// ```
1352 /// for c in 'İ'.to_lowercase() {
1353 /// print!("{c}");
1354 /// }
1355 /// println!();
1356 /// ```
1357 ///
1358 /// Using `println!` directly:
1359 ///
1360 /// ```
1361 /// println!("{}", 'İ'.to_lowercase());
1362 /// ```
1363 ///
1364 /// Both are equivalent to:
1365 ///
1366 /// ```
1367 /// println!("i\u{307}");
1368 /// ```
1369 ///
1370 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1371 ///
1372 /// ```
1373 /// assert_eq!('C'.to_lowercase().to_string(), "c");
1374 ///
1375 /// // Sometimes the result is more than one character:
1376 /// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}");
1377 ///
1378 /// // Characters that do not have both uppercase and lowercase
1379 /// // convert into themselves.
1380 /// assert_eq!('山'.to_lowercase().to_string(), "山");
1381 /// ```
1382 /// # Notes on context and locale
1383 ///
1384 /// As stated earlier, this method does not take into account language or context.
1385 /// Below is a non-exhaustive list of situations where this can be relevant.
1386 /// If you need to handle locale-depedendent casing in your code, consider using
1387 /// an external crate, like [`icu_casemap`](https://crates.io/crates/icu_casemap)
1388 /// which is developed by Unicode.
1389 ///
1390 /// ## Greek sigma
1391 ///
1392 /// In Greek, the letter simga (uppercase 'Σ') has two lowercase forms:
1393 /// 'σ' which is used in most situations, and 'ς' which appears only
1394 /// at the end of a word. [`char::to_lowercase()`] always uses the first form:
1395 ///
1396 /// ```
1397 /// assert_eq!('Σ'.to_lowercase().to_string(), "σ");
1398 /// ```
1399 ///
1400 /// `str::to_lowercase()` (only available with the `alloc` crate)
1401 /// *does* properly handle this contextual mapping,
1402 /// so prefer using that method if you can. Alternatively, you can use
1403 /// [`is_cased()`] and [`is_case_ignorable()`] to implement it yourself.
1404 /// See `Final_Sigma` in [Table 3.17] of the Unicode Standard,
1405 /// along with [`SpecialCasing.txt`], for more details.
1406 ///
1407 /// [`is_cased()`]: Self::is_cased()
1408 /// [`is_case_ignorable()`]: Self::is_case_ignorable()
1409 /// [Table 3.17]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G54277
1410 ///
1411 /// ## Turkish and Azeri I/ı/İ/i
1412 ///
1413 /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1414 ///
1415 /// * 'Dotless': I / ı, sometimes written ï
1416 /// * 'Dotted': İ / i
1417 ///
1418 /// Note that the uppercase undotted 'I' is the same codepoint as the Latin. Therefore:
1419 ///
1420 /// ```
1421 /// let lower_i = 'I'.to_lowercase().to_string();
1422 /// ```
1423 ///
1424 /// `'I'`'s correct lowercase relies on the language of the text: if we're
1425 /// in `en-US`, it should be `"i"`, but if we're in `tr-TR` or `az-AZ`, it should
1426 /// be `"ı"`. `to_lowercase()` does not take this into account, and so:
1427 ///
1428 /// ```
1429 /// let lower_i = 'I'.to_lowercase().to_string();
1430 ///
1431 /// assert_eq!(lower_i, "i");
1432 /// ```
1433 ///
1434 /// holds across languages.
1435 ///
1436 /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1437 #[must_use = "this returns the lowercased character as a new iterator, \
1438 without modifying the original"]
1439 #[stable(feature = "rust1", since = "1.0.0")]
1440 #[inline]
1441 pub fn to_lowercase(self) -> ToLowercase {
1442 ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
1443 }
1444
1445 /// Returns an iterator that yields the titlecase mapping of this `char` as one or more
1446 /// `char`s.
1447 ///
1448 /// This is usually, but not always, equivalent to the uppercase mapping
1449 /// returned by [`to_uppercase()`]. Prefer this method when seeking to capitalize
1450 /// Only The First Letter of a word, but use [`to_uppercase()`] for ALL CAPS.
1451 /// See [below](#difference-from-uppercase) for a thorough explanation
1452 /// of the difference between the two methods.
1453 ///
1454 /// If this `char` does not have a titlecase mapping, the iterator yields the same `char`.
1455 ///
1456 /// If this `char` has a one-to-one titlecase mapping given by the [Unicode Character
1457 /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1458 ///
1459 /// [ucd]: https://www.unicode.org/reports/tr44/
1460 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1461 ///
1462 /// If this `char` expands to multiple `char`s, the iterator yields the `char`s given by
1463 /// [`SpecialCasing.txt`]. The maximum number of `char`s in a case mapping is 3.
1464 ///
1465 /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1466 ///
1467 /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1468 /// is independent of context and language. See [below](#note-on-locale)
1469 /// for more information.
1470 ///
1471 /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1472 /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1473 ///
1474 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1475 ///
1476 /// # Examples
1477 ///
1478 /// As an iterator:
1479 ///
1480 /// ```
1481 /// #![feature(titlecase)]
1482 /// for c in 'ß'.to_titlecase() {
1483 /// print!("{c}");
1484 /// }
1485 /// println!();
1486 /// ```
1487 ///
1488 /// Using `println!` directly:
1489 ///
1490 /// ```
1491 /// #![feature(titlecase)]
1492 /// println!("{}", 'ß'.to_titlecase());
1493 /// ```
1494 ///
1495 /// Both are equivalent to:
1496 ///
1497 /// ```
1498 /// println!("Ss");
1499 /// ```
1500 ///
1501 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1502 ///
1503 /// ```
1504 /// #![feature(titlecase)]
1505 /// assert_eq!('c'.to_titlecase().to_string(), "C");
1506 /// assert_eq!('ა'.to_titlecase().to_string(), "ა");
1507 /// assert_eq!('dž'.to_titlecase().to_string(), "Dž");
1508 /// assert_eq!('ᾨ'.to_titlecase().to_string(), "ᾨ");
1509 ///
1510 /// // Sometimes the result is more than one character:
1511 /// assert_eq!('ß'.to_titlecase().to_string(), "Ss");
1512 ///
1513 /// // Characters that do not have separate cased forms
1514 /// // convert into themselves.
1515 /// assert_eq!('山'.to_titlecase().to_string(), "山");
1516 /// ```
1517 ///
1518 /// # Difference from uppercase
1519 ///
1520 /// Currently, there are three classes of characters where [`to_uppercase()`]
1521 /// and `to_titlecase()` give different results:
1522 ///
1523 /// ## Georgian script
1524 ///
1525 /// Each letter in the modern Georgian alphabet can be written in one of two forms:
1526 /// the typical lowercase-like "mkhedruli" form, and a variant uppercase-like "mtavruli"
1527 /// form. However, unlike uppercase in most cased scripts, mtavruli is not typically used
1528 /// to start sentences, denote proper nouns, or for any other purpose
1529 /// in running text. It is instead confined to titles and headings, which are written entirely
1530 /// in mtavruli. For this reason, [`to_uppercase()`] applied to a Georgian letter
1531 /// will return the mtavruli form, but `to_titlecase()` will return the mkhedruli form.
1532 ///
1533 /// ```
1534 /// #![feature(titlecase)]
1535 /// let ani = 'ა'; // First letter of the Georgian alphabet, in mkhedruli form
1536 ///
1537 /// // Titlecasing mkhedruli maps it to itself...
1538 /// assert_eq!(ani.to_titlecase().to_string(), ani.to_string());
1539 ///
1540 /// // but uppercasing it maps it to mtavruli
1541 /// assert_eq!(ani.to_uppercase().to_string(), "Ა");
1542 /// ```
1543 ///
1544 /// ## Compatibility digraphs for Latin-alphabet Serbo-Croatian
1545 ///
1546 /// The standard Latin alphabet for the Serbo-Croatian language
1547 /// (Bosnian, Croatian, Montenegrin, and Serbian) contains
1548 /// three digraphs: Dž, Lj, and Nj. These are usually represented as
1549 /// two characters. However, for compatibility with older character sets,
1550 /// Unicode includes single-character versions of these digraphs.
1551 /// Each has a uppercase, titlecase, and lowercase version:
1552 ///
1553 /// - `'DŽ'`, `'Dž'`, `'dž'`
1554 /// - `'LJ'`, `'Lj'`, `'lj'`
1555 /// - `'NJ'`, `'Nj'`, `'nj'`
1556 ///
1557 /// Unicode additionally encodes a casing triad for the Dz digraph
1558 /// without the caron: `'DZ'`, `'Dz'`, `'dz'`.
1559 ///
1560 /// ## Iota-subscritped Greek vowels
1561 ///
1562 /// In ancient Greek, the long vowels alpha (α), eta (η), and omega (ω)
1563 /// were sometimes followed by an iota (ι), forming a diphthong. Over time,
1564 /// the diphthong pronunciation was slowly lost, with the iota becoming mute.
1565 /// Eventually, the ι disappeared from the spelling as well.
1566 /// However, there remains a need to represent ancient texts faithfully.
1567 ///
1568 /// Modern editions of ancient Greek texts commonly use a reduced-sized
1569 /// ι symbol to denote mute iotas, while distinguishing them from ιs
1570 /// which continued to affect pronunciation. The exact standard differs
1571 /// between different publications. Some render the mute ι below its associated
1572 /// vowel (subscript), while others place it to the right of said vowel (adscript).
1573 /// The interaction of mute ι symbols with casing also varies.
1574 ///
1575 /// The Unicode Standard, for its default casing rules, chose to make lowercase
1576 /// Greek vowels with iota subscipt (e.g. `'ᾠ'`) titlecase to the uppercase vowel
1577 /// with iota subscript (`'ᾨ'`) but uppercase to the uppercase vowel followed by
1578 /// full-size uppercase iota (`"ὨΙ"`). This is just one convention among many
1579 /// in common use, but it is the one Unicode settled on,
1580 /// so it is what this method does also.
1581 ///
1582 /// # Note on locale
1583 ///
1584 /// As stated above, this method is locale-insensitive.
1585 /// If you need locale support, consider using an external crate,
1586 /// like [`icu_casemap`](https://crates.io/crates/icu_casemap)
1587 /// which is developed by Unicode. A description of one common
1588 /// locale-dependent casing issue follows (there are others):
1589 ///
1590 /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1591 ///
1592 /// * 'Dotless': I / ı, sometimes written ï
1593 /// * 'Dotted': İ / i
1594 ///
1595 /// Note that the lowercase dotted 'i' is the same codepoint as the Latin. Therefore:
1596 ///
1597 /// ```
1598 /// #![feature(titlecase)]
1599 /// let upper_i = 'i'.to_titlecase().to_string();
1600 /// ```
1601 ///
1602 /// `'i'`'s correct titlecase relies on the language of the text: if we're
1603 /// in `en-US`, it should be `"I"`, but if we're in `tr-TR` or `az-AZ`, it should
1604 /// be `"İ"`. `to_titlecase()` does not take this into account, and so:
1605 ///
1606 /// ```
1607 /// #![feature(titlecase)]
1608 /// let upper_i = 'i'.to_titlecase().to_string();
1609 ///
1610 /// assert_eq!(upper_i, "I");
1611 /// ```
1612 ///
1613 /// holds across languages.
1614 ///
1615 /// [`to_uppercase()`]: Self::to_uppercase()
1616 #[must_use = "this returns the titlecased character as a new iterator, \
1617 without modifying the original"]
1618 #[unstable(feature = "titlecase", issue = "153892")]
1619 #[inline]
1620 pub fn to_titlecase(self) -> ToTitlecase {
1621 ToTitlecase(CaseMappingIter::new(conversions::to_title(self)))
1622 }
1623
1624 /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
1625 /// `char`s.
1626 ///
1627 /// Prefer this method when converting a word into ALL CAPS, but consider [`to_titlecase()`]
1628 /// instead if you seek to capitalize Only The First Letter. See that method's documentation
1629 /// for more information on the difference between the two.
1630 ///
1631 /// If this `char` does not have an uppercase mapping, the iterator yields the same `char`.
1632 ///
1633 /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
1634 /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1635 ///
1636 /// [ucd]: https://www.unicode.org/reports/tr44/
1637 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1638 ///
1639 /// If this `char` expands to multiple `char`s, the iterator yields the `char`s given by
1640 /// [`SpecialCasing.txt`]. The maximum number of `char`s in a case mapping is 3.
1641 ///
1642 /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1643 ///
1644 /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1645 /// is independent of context and language. See [below](#note-on-locale)
1646 /// for more information.
1647 ///
1648 /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1649 /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1650 ///
1651 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1652 ///
1653 /// # Examples
1654 ///
1655 /// `'ſt'` (U+FB05) is a single Unicode code point (a ligature) that maps to "ST" in uppercase.
1656 ///
1657 /// As an iterator:
1658 ///
1659 /// ```
1660 /// for c in 'ſt'.to_uppercase() {
1661 /// print!("{c}");
1662 /// }
1663 /// println!();
1664 /// ```
1665 ///
1666 /// Using `println!` directly:
1667 ///
1668 /// ```
1669 /// println!("{}", 'ſt'.to_uppercase());
1670 /// ```
1671 ///
1672 /// Both are equivalent to:
1673 ///
1674 /// ```
1675 /// println!("ST");
1676 /// ```
1677 ///
1678 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1679 ///
1680 /// ```
1681 /// assert_eq!('c'.to_uppercase().to_string(), "C");
1682 /// assert_eq!('ა'.to_uppercase().to_string(), "Ა");
1683 /// assert_eq!('dž'.to_uppercase().to_string(), "DŽ");
1684 ///
1685 /// // Sometimes the result is more than one character:
1686 /// assert_eq!('ſt'.to_uppercase().to_string(), "ST");
1687 /// assert_eq!('ᾨ'.to_uppercase().to_string(), "ὨΙ");
1688 ///
1689 /// // Characters that do not have both uppercase and lowercase
1690 /// // convert into themselves.
1691 /// assert_eq!('山'.to_uppercase().to_string(), "山");
1692 /// ```
1693 ///
1694 /// # Note on locale
1695 ///
1696 /// As stated above, this method is locale-insensitive.
1697 /// If you need locale support, consider using an external crate,
1698 /// like [`icu_casemap`](https://crates.io/crates/icu_casemap)
1699 /// which is developed by Unicode. A description of one common
1700 /// locale-dependent casing issue follows (there are others):
1701 ///
1702 /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1703 ///
1704 /// * 'Dotless': I / ı, sometimes written ï
1705 /// * 'Dotted': İ / i
1706 ///
1707 /// Note that the lowercase dotted 'i' is the same codepoint as the Latin. Therefore:
1708 ///
1709 /// ```
1710 /// let upper_i = 'i'.to_uppercase().to_string();
1711 /// ```
1712 ///
1713 /// `'i'`'s correct uppercase relies on the language of the text: if we're
1714 /// in `en-US`, it should be `"I"`, but if we're in `tr-TR` or `az-AZ`, it should
1715 /// be `"İ"`. `to_uppercase()` does not take this into account, and so:
1716 ///
1717 /// ```
1718 /// let upper_i = 'i'.to_uppercase().to_string();
1719 ///
1720 /// assert_eq!(upper_i, "I");
1721 /// ```
1722 ///
1723 /// holds across languages.
1724 ///
1725 /// [`to_titlecase()`]: Self::to_titlecase()
1726 #[must_use = "this returns the uppercased character as a new iterator, \
1727 without modifying the original"]
1728 #[stable(feature = "rust1", since = "1.0.0")]
1729 #[inline]
1730 pub fn to_uppercase(self) -> ToUppercase {
1731 ToUppercase(CaseMappingIter::new(conversions::to_upper(self)))
1732 }
1733
1734 /// Returns an iterator that yields the case folding of this `char` as one or more
1735 /// `char`s.
1736 ///
1737 /// Case folding is meant to be used when performing case-insensitive string comparisons.
1738 /// Case-folded strings should not usually be exposed directly to users. For most,
1739 /// but not all, characters, the casefold mapping is identical to the lowercase one.
1740 ///
1741 /// This iterator yields the `char`(s) in the common or full case folding for this `char`,
1742 /// as given by the [Unicode Character Database][ucd] [`CaseFolding.txt`].
1743 /// The maximum number of `char`s in a case folding is 3.
1744 ///
1745 /// [ucd]: https://www.unicode.org/reports/tr44/
1746 /// [`CaseFolding.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt
1747 ///
1748 ///
1749 /// No [normalization] (e.g. NFC) is performed, so visually and semantically identical characters
1750 /// might still casefold differently. For example, `'ά'` (U+03AC GREEK SMALL LETTER ALPHA WITH TONOS)
1751 /// is considered distinct from `'ά'` (U+1F71 GREEK SMALL LETTER ALPHA WITH OXIA),
1752 /// even though Unicode considers them canonically equivalent.
1753 ///
1754 /// In addition, this method is independent of language/locale,
1755 /// so the special behavior of I/ı/İ/i in Turkish and Azeri is not handled.
1756 ///
1757 /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case folding in
1758 /// general and Chapter 3 (Conformance) discusses the default algorithm for case folding.
1759 ///
1760 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1761 ///
1762 /// # Examples
1763 ///
1764 /// The German sharp S `'ß'` (U+DF) is a single Unicode code point
1765 /// that casefolds to `"ss"`. Its uppercase variant '`ẞ`' (U+1E9E)
1766 /// has the same case-folding.
1767 ///
1768 /// As an iterator:
1769 ///
1770 /// ```
1771 /// #![feature(casefold)]
1772 /// assert!('ß'.to_casefold_unnormalized().eq(['s', 's']));
1773 /// assert!('ẞ'.to_casefold_unnormalized().eq(['s', 's']));
1774 /// ```
1775 ///
1776 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1777 ///
1778 /// ```
1779 /// #![feature(casefold)]
1780 /// assert_eq!('ß'.to_casefold_unnormalized().to_string(), "ss");
1781 /// assert_eq!('ẞ'.to_casefold_unnormalized().to_string(), "ss");
1782 /// ```
1783 ///
1784 /// No [normalization] is performed:
1785 ///
1786 /// ```rust
1787 /// #![feature(casefold)]
1788 /// // These two characters are visually and semantically identical;
1789 /// // Unicode considers them to be canonically equivalent.
1790 /// let alpha_tonos = 'ά';
1791 /// let alpha_oxia = 'ά';
1792 ///
1793 /// // However, they are different codepoints:
1794 /// assert_eq!(alpha_tonos, '\u{03AC}');
1795 /// assert_eq!(alpha_oxia, '\u{1F71}');
1796 ///
1797 /// // Their case-foldings are likewise unequal:
1798 /// assert!(alpha_tonos.to_casefold_unnormalized().eq(['\u{03AC}']));
1799 /// assert!(alpha_oxia.to_casefold_unnormalized().eq(['\u{1F71}']));
1800 /// ```
1801 ///
1802 /// # Note on locale
1803 ///
1804 /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1805 ///
1806 /// * 'Dotless': I / ı, sometimes written ï
1807 /// * 'Dotted': İ / i
1808 ///
1809 /// Note that the uppercase undotted 'I' is the same codepoint as the Latin. Therefore:
1810 ///
1811 /// ```
1812 /// #![feature(casefold)]
1813 /// let casefold_i = 'I'.to_casefold_unnormalized().to_string();
1814 /// ```
1815 ///
1816 /// `'I'`'s correct case folding relies on the language of the text: if we're
1817 /// in `en-US`, it should be `"i"`, but if we're in `tr-TR` or `az-AZ`, it should
1818 /// be `"ı"`. `to_casefold_unnormalized()` does not take this into account, and so:
1819 ///
1820 /// ```
1821 /// #![feature(casefold)]
1822 /// let casefold_i = 'I'.to_casefold_unnormalized().to_string();
1823 ///
1824 /// assert_eq!(casefold_i, "i");
1825 /// ```
1826 ///
1827 /// holds across languages.
1828 ///
1829 /// [normalization]: https://www.unicode.org/faq/normalization.html
1830 #[must_use = "this returns the case-folded character as a new iterator, \
1831 without modifying the original"]
1832 #[unstable(feature = "casefold", issue = "157000")]
1833 #[inline]
1834 pub fn to_casefold_unnormalized(self) -> ToCasefold {
1835 ToCasefold(CaseMappingIter::new(conversions::to_casefold(self)))
1836 }
1837
1838 /// Returns the code point value as a `u32`.
1839 ///
1840 /// # Examples
1841 ///
1842 /// ```
1843 /// #![feature(char_to_u32)]
1844 ///
1845 /// let ascii = 'a';
1846 /// let heart = '❤';
1847 ///
1848 /// assert_eq!(ascii.to_u32(), 97_u32);
1849 /// assert_eq!(heart.to_u32(), 0x2764_u32);
1850 /// ```
1851 #[must_use = "this returns the result of the operation, \
1852 without modifying the original"]
1853 #[unstable(feature = "char_to_u32", issue = "158938")]
1854 #[rustc_const_unstable(feature = "char_to_u32", issue = "158938")]
1855 #[inline(always)]
1856 pub const fn to_u32(self) -> u32 {
1857 self as u32
1858 }
1859
1860 /// Checks if the value is within the ASCII range.
1861 ///
1862 /// # Examples
1863 ///
1864 /// ```
1865 /// let ascii = 'a';
1866 /// let non_ascii = '❤';
1867 ///
1868 /// assert!(ascii.is_ascii());
1869 /// assert!(!non_ascii.is_ascii());
1870 /// ```
1871 #[must_use]
1872 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1873 #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")]
1874 #[rustc_diagnostic_item = "char_is_ascii"]
1875 #[inline]
1876 #[ferrocene::prevalidated]
1877 pub const fn is_ascii(&self) -> bool {
1878 *self as u32 <= 0x7F
1879 }
1880
1881 /// Returns `Some` if the value is within the ASCII range,
1882 /// or `None` if it's not.
1883 ///
1884 /// This is preferred to [`Self::is_ascii`] when you're passing the value
1885 /// along to something else that can take [`ascii::Char`] rather than
1886 /// needing to check again for itself whether the value is in ASCII.
1887 #[must_use]
1888 #[unstable(feature = "ascii_char", issue = "110998")]
1889 #[inline]
1890 #[ferrocene::prevalidated]
1891 pub const fn as_ascii(&self) -> Option<ascii::Char> {
1892 if self.is_ascii() {
1893 // SAFETY: Just checked that this is ASCII.
1894 Some(unsafe { ascii::Char::from_u8_unchecked(*self as u8) })
1895 } else {
1896 None
1897 }
1898 }
1899
1900 /// Converts this char into an [ASCII character](`ascii::Char`), without
1901 /// checking whether it is valid.
1902 ///
1903 /// # Safety
1904 ///
1905 /// This char must be within the ASCII range, or else this is UB.
1906 #[must_use]
1907 #[unstable(feature = "ascii_char", issue = "110998")]
1908 #[inline]
1909 pub const unsafe fn as_ascii_unchecked(&self) -> ascii::Char {
1910 assert_unsafe_precondition!(
1911 check_library_ub,
1912 "as_ascii_unchecked requires that the char is valid ASCII",
1913 (it: &char = self) => it.is_ascii()
1914 );
1915
1916 // SAFETY: the caller promised that this char is ASCII.
1917 unsafe { ascii::Char::from_u8_unchecked(*self as u8) }
1918 }
1919
1920 /// Makes a copy of the value in its ASCII upper case equivalent.
1921 ///
1922 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1923 /// but non-ASCII letters are unchanged.
1924 ///
1925 /// To uppercase the value in-place, use [`make_ascii_uppercase()`].
1926 ///
1927 /// To uppercase ASCII characters in addition to non-ASCII characters, use
1928 /// [`to_uppercase()`].
1929 ///
1930 /// # Examples
1931 ///
1932 /// ```
1933 /// let ascii = 'a';
1934 /// let non_ascii = '❤';
1935 ///
1936 /// assert_eq!('A', ascii.to_ascii_uppercase());
1937 /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
1938 /// ```
1939 ///
1940 /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase
1941 /// [`to_uppercase()`]: #method.to_uppercase
1942 #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
1943 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1944 #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
1945 #[inline]
1946 pub const fn to_ascii_uppercase(&self) -> char {
1947 if self.is_ascii_lowercase() {
1948 (*self as u8).ascii_change_case_unchecked() as char
1949 } else {
1950 *self
1951 }
1952 }
1953
1954 /// Makes a copy of the value in its ASCII lower case equivalent.
1955 ///
1956 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1957 /// but non-ASCII letters are unchanged.
1958 ///
1959 /// To lowercase the value in-place, use [`make_ascii_lowercase()`].
1960 ///
1961 /// To lowercase ASCII characters in addition to non-ASCII characters, use
1962 /// [`to_lowercase()`].
1963 ///
1964 /// # Examples
1965 ///
1966 /// ```
1967 /// let ascii = 'A';
1968 /// let non_ascii = '❤';
1969 ///
1970 /// assert_eq!('a', ascii.to_ascii_lowercase());
1971 /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
1972 /// ```
1973 ///
1974 /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase
1975 /// [`to_lowercase()`]: #method.to_lowercase
1976 #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
1977 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1978 #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
1979 #[inline]
1980 pub const fn to_ascii_lowercase(&self) -> char {
1981 if self.is_ascii_uppercase() {
1982 (*self as u8).ascii_change_case_unchecked() as char
1983 } else {
1984 *self
1985 }
1986 }
1987
1988 /// Checks that two values are an ASCII case-insensitive match.
1989 ///
1990 /// Equivalent to <code>[to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b)</code>.
1991 ///
1992 /// # Examples
1993 ///
1994 /// ```
1995 /// let upper_a = 'A';
1996 /// let lower_a = 'a';
1997 /// let lower_z = 'z';
1998 ///
1999 /// assert!(upper_a.eq_ignore_ascii_case(&lower_a));
2000 /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
2001 /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
2002 /// ```
2003 ///
2004 /// [to_ascii_lowercase]: #method.to_ascii_lowercase
2005 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2006 #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
2007 #[expect(clippy::manual_ignore_case_cmp, reason = "implements eq_ignore_ascii_case")]
2008 #[inline]
2009 pub const fn eq_ignore_ascii_case(&self, other: &char) -> bool {
2010 self.to_ascii_lowercase() == other.to_ascii_lowercase()
2011 }
2012
2013 /// Converts this type to its ASCII upper case equivalent in-place.
2014 ///
2015 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
2016 /// but non-ASCII letters are unchanged.
2017 ///
2018 /// To return a new uppercased value without modifying the existing one, use
2019 /// [`to_ascii_uppercase()`].
2020 ///
2021 /// # Examples
2022 ///
2023 /// ```
2024 /// let mut ascii = 'a';
2025 ///
2026 /// ascii.make_ascii_uppercase();
2027 ///
2028 /// assert_eq!('A', ascii);
2029 /// ```
2030 ///
2031 /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase
2032 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2033 #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")]
2034 #[inline]
2035 pub const fn make_ascii_uppercase(&mut self) {
2036 *self = self.to_ascii_uppercase();
2037 }
2038
2039 /// Converts this type to its ASCII lower case equivalent in-place.
2040 ///
2041 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
2042 /// but non-ASCII letters are unchanged.
2043 ///
2044 /// To return a new lowercased value without modifying the existing one, use
2045 /// [`to_ascii_lowercase()`].
2046 ///
2047 /// # Examples
2048 ///
2049 /// ```
2050 /// let mut ascii = 'A';
2051 ///
2052 /// ascii.make_ascii_lowercase();
2053 ///
2054 /// assert_eq!('a', ascii);
2055 /// ```
2056 ///
2057 /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase
2058 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2059 #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")]
2060 #[inline]
2061 pub const fn make_ascii_lowercase(&mut self) {
2062 *self = self.to_ascii_lowercase();
2063 }
2064
2065 /// Checks if the value is an ASCII alphabetic character:
2066 ///
2067 /// - U+0041 'A' ..= U+005A 'Z', or
2068 /// - U+0061 'a' ..= U+007A 'z'.
2069 ///
2070 /// # Examples
2071 ///
2072 /// ```
2073 /// let uppercase_a = 'A';
2074 /// let uppercase_g = 'G';
2075 /// let a = 'a';
2076 /// let g = 'g';
2077 /// let zero = '0';
2078 /// let percent = '%';
2079 /// let space = ' ';
2080 /// let lf = '\n';
2081 /// let esc = '\x1b';
2082 ///
2083 /// assert!(uppercase_a.is_ascii_alphabetic());
2084 /// assert!(uppercase_g.is_ascii_alphabetic());
2085 /// assert!(a.is_ascii_alphabetic());
2086 /// assert!(g.is_ascii_alphabetic());
2087 /// assert!(!zero.is_ascii_alphabetic());
2088 /// assert!(!percent.is_ascii_alphabetic());
2089 /// assert!(!space.is_ascii_alphabetic());
2090 /// assert!(!lf.is_ascii_alphabetic());
2091 /// assert!(!esc.is_ascii_alphabetic());
2092 /// ```
2093 #[must_use]
2094 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2095 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2096 #[inline]
2097 pub const fn is_ascii_alphabetic(&self) -> bool {
2098 matches!(*self, 'a'..='z' | 'A'..='Z')
2099 }
2100
2101 /// Checks if the value is an ASCII uppercase character:
2102 /// U+0041 'A' ..= U+005A 'Z'.
2103 ///
2104 /// # Examples
2105 ///
2106 /// ```
2107 /// let uppercase_a = 'A';
2108 /// let uppercase_g = 'G';
2109 /// let a = 'a';
2110 /// let g = 'g';
2111 /// let zero = '0';
2112 /// let percent = '%';
2113 /// let space = ' ';
2114 /// let lf = '\n';
2115 /// let esc = '\x1b';
2116 ///
2117 /// assert!(uppercase_a.is_ascii_uppercase());
2118 /// assert!(uppercase_g.is_ascii_uppercase());
2119 /// assert!(!a.is_ascii_uppercase());
2120 /// assert!(!g.is_ascii_uppercase());
2121 /// assert!(!zero.is_ascii_uppercase());
2122 /// assert!(!percent.is_ascii_uppercase());
2123 /// assert!(!space.is_ascii_uppercase());
2124 /// assert!(!lf.is_ascii_uppercase());
2125 /// assert!(!esc.is_ascii_uppercase());
2126 /// ```
2127 #[must_use]
2128 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2129 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2130 #[inline]
2131 pub const fn is_ascii_uppercase(&self) -> bool {
2132 matches!(*self, 'A'..='Z')
2133 }
2134
2135 /// Checks if the value is an ASCII lowercase character:
2136 /// U+0061 'a' ..= U+007A 'z'.
2137 ///
2138 /// # Examples
2139 ///
2140 /// ```
2141 /// let uppercase_a = 'A';
2142 /// let uppercase_g = 'G';
2143 /// let a = 'a';
2144 /// let g = 'g';
2145 /// let zero = '0';
2146 /// let percent = '%';
2147 /// let space = ' ';
2148 /// let lf = '\n';
2149 /// let esc = '\x1b';
2150 ///
2151 /// assert!(!uppercase_a.is_ascii_lowercase());
2152 /// assert!(!uppercase_g.is_ascii_lowercase());
2153 /// assert!(a.is_ascii_lowercase());
2154 /// assert!(g.is_ascii_lowercase());
2155 /// assert!(!zero.is_ascii_lowercase());
2156 /// assert!(!percent.is_ascii_lowercase());
2157 /// assert!(!space.is_ascii_lowercase());
2158 /// assert!(!lf.is_ascii_lowercase());
2159 /// assert!(!esc.is_ascii_lowercase());
2160 /// ```
2161 #[must_use]
2162 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2163 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2164 #[inline]
2165 pub const fn is_ascii_lowercase(&self) -> bool {
2166 matches!(*self, 'a'..='z')
2167 }
2168
2169 /// Checks if the value is an ASCII alphanumeric character:
2170 ///
2171 /// - U+0041 'A' ..= U+005A 'Z', or
2172 /// - U+0061 'a' ..= U+007A 'z', or
2173 /// - U+0030 '0' ..= U+0039 '9'.
2174 ///
2175 /// # Examples
2176 ///
2177 /// ```
2178 /// let uppercase_a = 'A';
2179 /// let uppercase_g = 'G';
2180 /// let a = 'a';
2181 /// let g = 'g';
2182 /// let zero = '0';
2183 /// let percent = '%';
2184 /// let space = ' ';
2185 /// let lf = '\n';
2186 /// let esc = '\x1b';
2187 ///
2188 /// assert!(uppercase_a.is_ascii_alphanumeric());
2189 /// assert!(uppercase_g.is_ascii_alphanumeric());
2190 /// assert!(a.is_ascii_alphanumeric());
2191 /// assert!(g.is_ascii_alphanumeric());
2192 /// assert!(zero.is_ascii_alphanumeric());
2193 /// assert!(!percent.is_ascii_alphanumeric());
2194 /// assert!(!space.is_ascii_alphanumeric());
2195 /// assert!(!lf.is_ascii_alphanumeric());
2196 /// assert!(!esc.is_ascii_alphanumeric());
2197 /// ```
2198 #[must_use]
2199 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2200 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2201 #[inline]
2202 pub const fn is_ascii_alphanumeric(&self) -> bool {
2203 matches!(*self, '0'..='9') | matches!(*self, 'A'..='Z') | matches!(*self, 'a'..='z')
2204 }
2205
2206 /// Checks if the value is an ASCII decimal digit:
2207 /// U+0030 '0' ..= U+0039 '9'.
2208 ///
2209 /// # Examples
2210 ///
2211 /// ```
2212 /// let uppercase_a = 'A';
2213 /// let uppercase_g = 'G';
2214 /// let a = 'a';
2215 /// let g = 'g';
2216 /// let zero = '0';
2217 /// let percent = '%';
2218 /// let space = ' ';
2219 /// let lf = '\n';
2220 /// let esc = '\x1b';
2221 ///
2222 /// assert!(!uppercase_a.is_ascii_digit());
2223 /// assert!(!uppercase_g.is_ascii_digit());
2224 /// assert!(!a.is_ascii_digit());
2225 /// assert!(!g.is_ascii_digit());
2226 /// assert!(zero.is_ascii_digit());
2227 /// assert!(!percent.is_ascii_digit());
2228 /// assert!(!space.is_ascii_digit());
2229 /// assert!(!lf.is_ascii_digit());
2230 /// assert!(!esc.is_ascii_digit());
2231 /// ```
2232 #[must_use]
2233 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2234 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2235 #[inline]
2236 pub const fn is_ascii_digit(&self) -> bool {
2237 matches!(*self, '0'..='9')
2238 }
2239
2240 /// Checks if the value is an ASCII octal digit:
2241 /// U+0030 '0' ..= U+0037 '7'.
2242 ///
2243 /// # Examples
2244 ///
2245 /// ```
2246 /// #![feature(is_ascii_octdigit)]
2247 ///
2248 /// let uppercase_a = 'A';
2249 /// let a = 'a';
2250 /// let zero = '0';
2251 /// let seven = '7';
2252 /// let nine = '9';
2253 /// let percent = '%';
2254 /// let lf = '\n';
2255 ///
2256 /// assert!(!uppercase_a.is_ascii_octdigit());
2257 /// assert!(!a.is_ascii_octdigit());
2258 /// assert!(zero.is_ascii_octdigit());
2259 /// assert!(seven.is_ascii_octdigit());
2260 /// assert!(!nine.is_ascii_octdigit());
2261 /// assert!(!percent.is_ascii_octdigit());
2262 /// assert!(!lf.is_ascii_octdigit());
2263 /// ```
2264 #[must_use]
2265 #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
2266 #[inline]
2267 pub const fn is_ascii_octdigit(&self) -> bool {
2268 matches!(*self, '0'..='7')
2269 }
2270
2271 /// Checks if the value is an ASCII hexadecimal digit:
2272 ///
2273 /// - U+0030 '0' ..= U+0039 '9', or
2274 /// - U+0041 'A' ..= U+0046 'F', or
2275 /// - U+0061 'a' ..= U+0066 'f'.
2276 ///
2277 /// # Examples
2278 ///
2279 /// ```
2280 /// let uppercase_a = 'A';
2281 /// let uppercase_g = 'G';
2282 /// let a = 'a';
2283 /// let g = 'g';
2284 /// let zero = '0';
2285 /// let percent = '%';
2286 /// let space = ' ';
2287 /// let lf = '\n';
2288 /// let esc = '\x1b';
2289 ///
2290 /// assert!(uppercase_a.is_ascii_hexdigit());
2291 /// assert!(!uppercase_g.is_ascii_hexdigit());
2292 /// assert!(a.is_ascii_hexdigit());
2293 /// assert!(!g.is_ascii_hexdigit());
2294 /// assert!(zero.is_ascii_hexdigit());
2295 /// assert!(!percent.is_ascii_hexdigit());
2296 /// assert!(!space.is_ascii_hexdigit());
2297 /// assert!(!lf.is_ascii_hexdigit());
2298 /// assert!(!esc.is_ascii_hexdigit());
2299 /// ```
2300 #[must_use]
2301 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2302 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2303 #[inline]
2304 pub const fn is_ascii_hexdigit(&self) -> bool {
2305 matches!(*self, '0'..='9') | matches!(*self, 'A'..='F') | matches!(*self, 'a'..='f')
2306 }
2307
2308 /// Checks if the value is an ASCII punctuation or symbol character
2309 /// (i.e. not alphanumeric, whitespace, or control):
2310 ///
2311 /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
2312 /// - U+003A ..= U+0040 `: ; < = > ? @`, or
2313 /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or
2314 /// - U+007B ..= U+007E `{ | } ~`
2315 ///
2316 /// # Examples
2317 ///
2318 /// ```
2319 /// let uppercase_a = 'A';
2320 /// let uppercase_g = 'G';
2321 /// let a = 'a';
2322 /// let g = 'g';
2323 /// let zero = '0';
2324 /// let percent = '%';
2325 /// let space = ' ';
2326 /// let lf = '\n';
2327 /// let esc = '\x1b';
2328 ///
2329 /// assert!(!uppercase_a.is_ascii_punctuation());
2330 /// assert!(!uppercase_g.is_ascii_punctuation());
2331 /// assert!(!a.is_ascii_punctuation());
2332 /// assert!(!g.is_ascii_punctuation());
2333 /// assert!(!zero.is_ascii_punctuation());
2334 /// assert!(percent.is_ascii_punctuation());
2335 /// assert!(!space.is_ascii_punctuation());
2336 /// assert!(!lf.is_ascii_punctuation());
2337 /// assert!(!esc.is_ascii_punctuation());
2338 /// ```
2339 #[must_use]
2340 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2341 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2342 #[inline]
2343 pub const fn is_ascii_punctuation(&self) -> bool {
2344 matches!(*self, '!'..='/')
2345 | matches!(*self, ':'..='@')
2346 | matches!(*self, '['..='`')
2347 | matches!(*self, '{'..='~')
2348 }
2349
2350 /// Checks if the value is an ASCII graphic character
2351 /// (i.e. not whitespace or control):
2352 /// U+0021 '!' ..= U+007E '~'.
2353 ///
2354 /// # Examples
2355 ///
2356 /// ```
2357 /// let uppercase_a = 'A';
2358 /// let uppercase_g = 'G';
2359 /// let a = 'a';
2360 /// let g = 'g';
2361 /// let zero = '0';
2362 /// let percent = '%';
2363 /// let space = ' ';
2364 /// let lf = '\n';
2365 /// let esc = '\x1b';
2366 ///
2367 /// assert!(uppercase_a.is_ascii_graphic());
2368 /// assert!(uppercase_g.is_ascii_graphic());
2369 /// assert!(a.is_ascii_graphic());
2370 /// assert!(g.is_ascii_graphic());
2371 /// assert!(zero.is_ascii_graphic());
2372 /// assert!(percent.is_ascii_graphic());
2373 /// assert!(!space.is_ascii_graphic());
2374 /// assert!(!lf.is_ascii_graphic());
2375 /// assert!(!esc.is_ascii_graphic());
2376 /// ```
2377 #[must_use]
2378 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2379 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2380 #[inline]
2381 pub const fn is_ascii_graphic(&self) -> bool {
2382 matches!(*self, '!'..='~')
2383 }
2384
2385 /// Checks if the value is an ASCII whitespace character:
2386 /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
2387 /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
2388 ///
2389 /// **Warning:** Because the list above excludes U+000B VERTICAL TAB,
2390 /// `c.is_ascii_whitespace()` is **not** equivalent to `c.is_ascii() && c.is_whitespace()`.
2391 ///
2392 /// Rust uses the WhatWG Infra Standard's [definition of ASCII
2393 /// whitespace][infra-aw]. There are several other definitions in
2394 /// wide use. For instance, [the POSIX locale][pct] includes
2395 /// U+000B VERTICAL TAB as well as all the above characters,
2396 /// but—from the very same specification—[the default rule for
2397 /// "field splitting" in the Bourne shell][bfs] considers *only*
2398 /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
2399 ///
2400 /// If you are writing a program that will process an existing
2401 /// file format, check what that format's definition of whitespace is
2402 /// before using this function.
2403 ///
2404 /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
2405 /// [pct]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01
2406 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06_05
2407 ///
2408 /// # Examples
2409 ///
2410 /// ```
2411 /// let uppercase_a = 'A';
2412 /// let uppercase_g = 'G';
2413 /// let a = 'a';
2414 /// let g = 'g';
2415 /// let zero = '0';
2416 /// let percent = '%';
2417 /// let space = ' ';
2418 /// let lf = '\n';
2419 /// let esc = '\x1b';
2420 ///
2421 /// assert!(!uppercase_a.is_ascii_whitespace());
2422 /// assert!(!uppercase_g.is_ascii_whitespace());
2423 /// assert!(!a.is_ascii_whitespace());
2424 /// assert!(!g.is_ascii_whitespace());
2425 /// assert!(!zero.is_ascii_whitespace());
2426 /// assert!(!percent.is_ascii_whitespace());
2427 /// assert!(space.is_ascii_whitespace());
2428 /// assert!(lf.is_ascii_whitespace());
2429 /// assert!(!esc.is_ascii_whitespace());
2430 /// ```
2431 #[must_use]
2432 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2433 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2434 #[inline]
2435 #[ferrocene::prevalidated]
2436 pub const fn is_ascii_whitespace(&self) -> bool {
2437 matches!(*self, '\t' | '\n' | '\x0C' | '\r' | ' ')
2438 }
2439
2440 /// Checks if the value is an ASCII control character:
2441 /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.
2442 /// Note that most ASCII whitespace characters are control
2443 /// characters, but SPACE is not.
2444 ///
2445 /// # Examples
2446 ///
2447 /// ```
2448 /// let uppercase_a = 'A';
2449 /// let uppercase_g = 'G';
2450 /// let a = 'a';
2451 /// let g = 'g';
2452 /// let zero = '0';
2453 /// let percent = '%';
2454 /// let space = ' ';
2455 /// let lf = '\n';
2456 /// let esc = '\x1b';
2457 ///
2458 /// assert!(!uppercase_a.is_ascii_control());
2459 /// assert!(!uppercase_g.is_ascii_control());
2460 /// assert!(!a.is_ascii_control());
2461 /// assert!(!g.is_ascii_control());
2462 /// assert!(!zero.is_ascii_control());
2463 /// assert!(!percent.is_ascii_control());
2464 /// assert!(!space.is_ascii_control());
2465 /// assert!(lf.is_ascii_control());
2466 /// assert!(esc.is_ascii_control());
2467 /// ```
2468 #[must_use]
2469 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2470 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2471 #[inline]
2472 pub const fn is_ascii_control(&self) -> bool {
2473 matches!(*self, '\0'..='\x1F' | '\x7F')
2474 }
2475}
2476
2477#[ferrocene::prevalidated]
2478pub(crate) struct EscapeDebugExtArgs {
2479 /// Escape single quotes?
2480 pub(crate) escape_single_quote: bool,
2481
2482 /// Escape double quotes?
2483 pub(crate) escape_double_quote: bool,
2484}
2485
2486impl EscapeDebugExtArgs {
2487 pub(crate) const ESCAPE_ALL: Self =
2488 Self { escape_single_quote: true, escape_double_quote: true };
2489}
2490
2491#[inline]
2492#[must_use]
2493#[ferrocene::prevalidated]
2494const fn len_utf8(code: u32) -> usize {
2495 match code {
2496 ..MAX_ONE_B => 1,
2497 ..MAX_TWO_B => 2,
2498 ..MAX_THREE_B => 3,
2499 _ => 4,
2500 }
2501}
2502
2503#[inline]
2504#[must_use]
2505const fn len_utf16(code: u32) -> usize {
2506 if (code & 0xFFFF) == code { 1 } else { 2 }
2507}
2508
2509/// Encodes a raw `u32` value as UTF-8 into the provided byte buffer,
2510/// and then returns the subslice of the buffer that contains the encoded character.
2511///
2512/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range.
2513/// (Creating a `char` in the surrogate range is UB.)
2514/// The result is valid [generalized UTF-8] but not valid UTF-8.
2515///
2516/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8
2517///
2518/// # Panics
2519///
2520/// Panics if the buffer is not large enough.
2521/// A buffer of length four is large enough to encode any `char`.
2522#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
2523#[doc(hidden)]
2524#[inline]
2525#[ferrocene::prevalidated]
2526pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
2527 let len = len_utf8(code);
2528 if dst.len() < len {
2529 const_panic!(
2530 "encode_utf8: buffer does not have enough bytes to encode code point",
2531 "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}",
2532 code: u32 = code,
2533 len: usize = len,
2534 dst_len: usize = dst.len(),
2535 );
2536 }
2537
2538 // SAFETY: `dst` is checked to be at least the length needed to encode the codepoint.
2539 unsafe { encode_utf8_raw_unchecked(code, dst.as_mut_ptr()) };
2540
2541 // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
2542 unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
2543}
2544
2545/// Encodes a raw `u32` value as UTF-8 into the byte buffer pointed to by `dst`.
2546///
2547/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range.
2548/// (Creating a `char` in the surrogate range is UB.)
2549/// The result is valid [generalized UTF-8] but not valid UTF-8.
2550///
2551/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8
2552///
2553/// # Safety
2554///
2555/// The behavior is undefined if the buffer pointed to by `dst` is not
2556/// large enough to hold the encoded codepoint. A buffer of length four
2557/// is large enough to encode any `char`.
2558///
2559/// For a safe version of this function, see the [`encode_utf8_raw`] function.
2560#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
2561#[doc(hidden)]
2562#[inline]
2563#[ferrocene::prevalidated]
2564pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) {
2565 let len = len_utf8(code);
2566 // SAFETY: The caller must guarantee that the buffer pointed to by `dst`
2567 // is at least `len` bytes long.
2568 unsafe {
2569 if len == 1 {
2570 *dst = code as u8;
2571 return;
2572 }
2573
2574 let last1 = (code >> 0 & 0x3F) as u8 | TAG_CONT;
2575 let last2 = (code >> 6 & 0x3F) as u8 | TAG_CONT;
2576 let last3 = (code >> 12 & 0x3F) as u8 | TAG_CONT;
2577 let last4 = (code >> 18 & 0x3F) as u8 | TAG_FOUR_B;
2578
2579 if len == 2 {
2580 *dst = last2 | TAG_TWO_B;
2581 *dst.add(1) = last1;
2582 return;
2583 }
2584
2585 if len == 3 {
2586 *dst = last3 | TAG_THREE_B;
2587 *dst.add(1) = last2;
2588 *dst.add(2) = last1;
2589 return;
2590 }
2591
2592 *dst = last4;
2593 *dst.add(1) = last3;
2594 *dst.add(2) = last2;
2595 *dst.add(3) = last1;
2596 }
2597}
2598
2599/// Encodes a raw `u32` value as native endian UTF-16 into the provided `u16` buffer,
2600/// and then returns the subslice of the buffer that contains the encoded character.
2601///
2602/// Unlike `char::encode_utf16`, this method also handles codepoints in the surrogate range.
2603/// (Creating a `char` in the surrogate range is UB.)
2604///
2605/// # Panics
2606///
2607/// Panics if the buffer is not large enough.
2608/// A buffer of length 2 is large enough to encode any `char`.
2609#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
2610#[doc(hidden)]
2611#[inline]
2612pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] {
2613 let len = len_utf16(code);
2614 match (len, &mut *dst) {
2615 (1, [a, ..]) => {
2616 *a = code as u16;
2617 }
2618 (2, [a, b, ..]) => {
2619 code -= 0x1_0000;
2620 *a = (code >> 10) as u16 | 0xD800;
2621 *b = (code & 0x3FF) as u16 | 0xDC00;
2622 }
2623 _ => {
2624 const_panic!(
2625 "encode_utf16: buffer does not have enough bytes to encode code point",
2626 "encode_utf16: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}",
2627 code: u32 = code,
2628 len: usize = len,
2629 dst_len: usize = dst.len(),
2630 )
2631 }
2632 };
2633 // SAFETY: `<&mut [u16]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
2634 unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
2635}