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