]> git.lizzy.rs Git - rust.git/blob - src/libcore/char/mod.rs
Rollup merge of #69813 - thomcc:nonzero-bitor, r=Amanieu
[rust.git] / src / libcore / char / mod.rs
1 //! A character type.
2 //!
3 //! The `char` type represents a single character. More specifically, since
4 //! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
5 //! scalar value]', which is similar to, but not the same as, a '[Unicode code
6 //! point]'.
7 //!
8 //! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
9 //! [Unicode code point]: http://www.unicode.org/glossary/#code_point
10 //!
11 //! This module exists for technical reasons, the primary documentation for
12 //! `char` is directly on [the `char` primitive type](../../std/primitive.char.html)
13 //! itself.
14 //!
15 //! This module is the home of the iterator implementations for the iterators
16 //! implemented on `char`, as well as some useful constants and conversion
17 //! functions that convert various types to `char`.
18
19 #![allow(non_snake_case)]
20 #![stable(feature = "core_char", since = "1.2.0")]
21
22 mod convert;
23 mod decode;
24 mod methods;
25
26 // stable re-exports
27 #[stable(feature = "char_from_unchecked", since = "1.5.0")]
28 pub use self::convert::from_u32_unchecked;
29 #[stable(feature = "try_from", since = "1.34.0")]
30 pub use self::convert::CharTryFromError;
31 #[stable(feature = "char_from_str", since = "1.20.0")]
32 pub use self::convert::ParseCharError;
33 #[stable(feature = "rust1", since = "1.0.0")]
34 pub use self::convert::{from_digit, from_u32};
35 #[stable(feature = "decode_utf16", since = "1.9.0")]
36 pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
37 #[stable(feature = "unicode_version", since = "1.45.0")]
38 pub use crate::unicode::UNICODE_VERSION;
39
40 use crate::fmt::{self, Write};
41 use crate::iter::FusedIterator;
42
43 // UTF-8 ranges and tags for encoding characters
44 const TAG_CONT: u8 = 0b1000_0000;
45 const TAG_TWO_B: u8 = 0b1100_0000;
46 const TAG_THREE_B: u8 = 0b1110_0000;
47 const TAG_FOUR_B: u8 = 0b1111_0000;
48 const MAX_ONE_B: u32 = 0x80;
49 const MAX_TWO_B: u32 = 0x800;
50 const MAX_THREE_B: u32 = 0x10000;
51
52 /*
53     Lu  Uppercase_Letter        an uppercase letter
54     Ll  Lowercase_Letter        a lowercase letter
55     Lt  Titlecase_Letter        a digraphic character, with first part uppercase
56     Lm  Modifier_Letter         a modifier letter
57     Lo  Other_Letter            other letters, including syllables and ideographs
58     Mn  Nonspacing_Mark         a nonspacing combining mark (zero advance width)
59     Mc  Spacing_Mark            a spacing combining mark (positive advance width)
60     Me  Enclosing_Mark          an enclosing combining mark
61     Nd  Decimal_Number          a decimal digit
62     Nl  Letter_Number           a letterlike numeric character
63     No  Other_Number            a numeric character of other type
64     Pc  Connector_Punctuation   a connecting punctuation mark, like a tie
65     Pd  Dash_Punctuation        a dash or hyphen punctuation mark
66     Ps  Open_Punctuation        an opening punctuation mark (of a pair)
67     Pe  Close_Punctuation       a closing punctuation mark (of a pair)
68     Pi  Initial_Punctuation     an initial quotation mark
69     Pf  Final_Punctuation       a final quotation mark
70     Po  Other_Punctuation       a punctuation mark of other type
71     Sm  Math_Symbol             a symbol of primarily mathematical use
72     Sc  Currency_Symbol         a currency sign
73     Sk  Modifier_Symbol         a non-letterlike modifier symbol
74     So  Other_Symbol            a symbol of other type
75     Zs  Space_Separator         a space character (of various non-zero widths)
76     Zl  Line_Separator          U+2028 LINE SEPARATOR only
77     Zp  Paragraph_Separator     U+2029 PARAGRAPH SEPARATOR only
78     Cc  Control                 a C0 or C1 control code
79     Cf  Format                  a format control character
80     Cs  Surrogate               a surrogate code point
81     Co  Private_Use             a private-use character
82     Cn  Unassigned              a reserved unassigned code point or a noncharacter
83 */
84
85 /// The highest valid code point a `char` can have.
86 ///
87 /// A [`char`] is a [Unicode Scalar Value], which means that it is a [Code
88 /// Point], but only ones within a certain range. `MAX` is the highest valid
89 /// code point that's a valid [Unicode Scalar Value].
90 ///
91 /// [`char`]: ../../std/primitive.char.html
92 /// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
93 /// [Code Point]: http://www.unicode.org/glossary/#code_point
94 #[stable(feature = "rust1", since = "1.0.0")]
95 pub const MAX: char = '\u{10ffff}';
96
97 /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
98 /// decoding error.
99 ///
100 /// It can occur, for example, when giving ill-formed UTF-8 bytes to
101 /// [`String::from_utf8_lossy`](../../std/string/struct.String.html#method.from_utf8_lossy).
102 #[stable(feature = "decode_utf16", since = "1.9.0")]
103 pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
104
105 /// Returns an iterator that yields the hexadecimal Unicode escape of a
106 /// character, as `char`s.
107 ///
108 /// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
109 /// its documentation for more.
110 ///
111 /// [`escape_unicode`]: ../../std/primitive.char.html#method.escape_unicode
112 /// [`char`]: ../../std/primitive.char.html
113 #[derive(Clone, Debug)]
114 #[stable(feature = "rust1", since = "1.0.0")]
115 pub struct EscapeUnicode {
116     c: char,
117     state: EscapeUnicodeState,
118
119     // The index of the next hex digit to be printed (0 if none),
120     // i.e., the number of remaining hex digits to be printed;
121     // increasing from the least significant digit: 0x543210
122     hex_digit_idx: usize,
123 }
124
125 // The enum values are ordered so that their representation is the
126 // same as the remaining length (besides the hexadecimal digits). This
127 // likely makes `len()` a single load from memory) and inline-worth.
128 #[derive(Clone, Debug)]
129 enum EscapeUnicodeState {
130     Done,
131     RightBrace,
132     Value,
133     LeftBrace,
134     Type,
135     Backslash,
136 }
137
138 #[stable(feature = "rust1", since = "1.0.0")]
139 impl Iterator for EscapeUnicode {
140     type Item = char;
141
142     fn next(&mut self) -> Option<char> {
143         match self.state {
144             EscapeUnicodeState::Backslash => {
145                 self.state = EscapeUnicodeState::Type;
146                 Some('\\')
147             }
148             EscapeUnicodeState::Type => {
149                 self.state = EscapeUnicodeState::LeftBrace;
150                 Some('u')
151             }
152             EscapeUnicodeState::LeftBrace => {
153                 self.state = EscapeUnicodeState::Value;
154                 Some('{')
155             }
156             EscapeUnicodeState::Value => {
157                 let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf;
158                 let c = from_digit(hex_digit, 16).unwrap();
159                 if self.hex_digit_idx == 0 {
160                     self.state = EscapeUnicodeState::RightBrace;
161                 } else {
162                     self.hex_digit_idx -= 1;
163                 }
164                 Some(c)
165             }
166             EscapeUnicodeState::RightBrace => {
167                 self.state = EscapeUnicodeState::Done;
168                 Some('}')
169             }
170             EscapeUnicodeState::Done => None,
171         }
172     }
173
174     #[inline]
175     fn size_hint(&self) -> (usize, Option<usize>) {
176         let n = self.len();
177         (n, Some(n))
178     }
179
180     #[inline]
181     fn count(self) -> usize {
182         self.len()
183     }
184
185     fn last(self) -> Option<char> {
186         match self.state {
187             EscapeUnicodeState::Done => None,
188
189             EscapeUnicodeState::RightBrace
190             | EscapeUnicodeState::Value
191             | EscapeUnicodeState::LeftBrace
192             | EscapeUnicodeState::Type
193             | EscapeUnicodeState::Backslash => Some('}'),
194         }
195     }
196 }
197
198 #[stable(feature = "exact_size_escape", since = "1.11.0")]
199 impl ExactSizeIterator for EscapeUnicode {
200     #[inline]
201     fn len(&self) -> usize {
202         // The match is a single memory access with no branching
203         self.hex_digit_idx
204             + match self.state {
205                 EscapeUnicodeState::Done => 0,
206                 EscapeUnicodeState::RightBrace => 1,
207                 EscapeUnicodeState::Value => 2,
208                 EscapeUnicodeState::LeftBrace => 3,
209                 EscapeUnicodeState::Type => 4,
210                 EscapeUnicodeState::Backslash => 5,
211             }
212     }
213 }
214
215 #[stable(feature = "fused", since = "1.26.0")]
216 impl FusedIterator for EscapeUnicode {}
217
218 #[stable(feature = "char_struct_display", since = "1.16.0")]
219 impl fmt::Display for EscapeUnicode {
220     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221         for c in self.clone() {
222             f.write_char(c)?;
223         }
224         Ok(())
225     }
226 }
227
228 /// An iterator that yields the literal escape code of a `char`.
229 ///
230 /// This `struct` is created by the [`escape_default`] method on [`char`]. See
231 /// its documentation for more.
232 ///
233 /// [`escape_default`]: ../../std/primitive.char.html#method.escape_default
234 /// [`char`]: ../../std/primitive.char.html
235 #[derive(Clone, Debug)]
236 #[stable(feature = "rust1", since = "1.0.0")]
237 pub struct EscapeDefault {
238     state: EscapeDefaultState,
239 }
240
241 #[derive(Clone, Debug)]
242 enum EscapeDefaultState {
243     Done,
244     Char(char),
245     Backslash(char),
246     Unicode(EscapeUnicode),
247 }
248
249 #[stable(feature = "rust1", since = "1.0.0")]
250 impl Iterator for EscapeDefault {
251     type Item = char;
252
253     fn next(&mut self) -> Option<char> {
254         match self.state {
255             EscapeDefaultState::Backslash(c) => {
256                 self.state = EscapeDefaultState::Char(c);
257                 Some('\\')
258             }
259             EscapeDefaultState::Char(c) => {
260                 self.state = EscapeDefaultState::Done;
261                 Some(c)
262             }
263             EscapeDefaultState::Done => None,
264             EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
265         }
266     }
267
268     #[inline]
269     fn size_hint(&self) -> (usize, Option<usize>) {
270         let n = self.len();
271         (n, Some(n))
272     }
273
274     #[inline]
275     fn count(self) -> usize {
276         self.len()
277     }
278
279     fn nth(&mut self, n: usize) -> Option<char> {
280         match self.state {
281             EscapeDefaultState::Backslash(c) if n == 0 => {
282                 self.state = EscapeDefaultState::Char(c);
283                 Some('\\')
284             }
285             EscapeDefaultState::Backslash(c) if n == 1 => {
286                 self.state = EscapeDefaultState::Done;
287                 Some(c)
288             }
289             EscapeDefaultState::Backslash(_) => {
290                 self.state = EscapeDefaultState::Done;
291                 None
292             }
293             EscapeDefaultState::Char(c) => {
294                 self.state = EscapeDefaultState::Done;
295
296                 if n == 0 { Some(c) } else { None }
297             }
298             EscapeDefaultState::Done => None,
299             EscapeDefaultState::Unicode(ref mut i) => i.nth(n),
300         }
301     }
302
303     fn last(self) -> Option<char> {
304         match self.state {
305             EscapeDefaultState::Unicode(iter) => iter.last(),
306             EscapeDefaultState::Done => None,
307             EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c),
308         }
309     }
310 }
311
312 #[stable(feature = "exact_size_escape", since = "1.11.0")]
313 impl ExactSizeIterator for EscapeDefault {
314     fn len(&self) -> usize {
315         match self.state {
316             EscapeDefaultState::Done => 0,
317             EscapeDefaultState::Char(_) => 1,
318             EscapeDefaultState::Backslash(_) => 2,
319             EscapeDefaultState::Unicode(ref iter) => iter.len(),
320         }
321     }
322 }
323
324 #[stable(feature = "fused", since = "1.26.0")]
325 impl FusedIterator for EscapeDefault {}
326
327 #[stable(feature = "char_struct_display", since = "1.16.0")]
328 impl fmt::Display for EscapeDefault {
329     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330         for c in self.clone() {
331             f.write_char(c)?;
332         }
333         Ok(())
334     }
335 }
336
337 /// An iterator that yields the literal escape code of a `char`.
338 ///
339 /// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
340 /// documentation for more.
341 ///
342 /// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug
343 /// [`char`]: ../../std/primitive.char.html
344 #[stable(feature = "char_escape_debug", since = "1.20.0")]
345 #[derive(Clone, Debug)]
346 pub struct EscapeDebug(EscapeDefault);
347
348 #[stable(feature = "char_escape_debug", since = "1.20.0")]
349 impl Iterator for EscapeDebug {
350     type Item = char;
351     fn next(&mut self) -> Option<char> {
352         self.0.next()
353     }
354     fn size_hint(&self) -> (usize, Option<usize>) {
355         self.0.size_hint()
356     }
357 }
358
359 #[stable(feature = "char_escape_debug", since = "1.20.0")]
360 impl ExactSizeIterator for EscapeDebug {}
361
362 #[stable(feature = "fused", since = "1.26.0")]
363 impl FusedIterator for EscapeDebug {}
364
365 #[stable(feature = "char_escape_debug", since = "1.20.0")]
366 impl fmt::Display for EscapeDebug {
367     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368         fmt::Display::fmt(&self.0, f)
369     }
370 }
371
372 /// Returns an iterator that yields the lowercase equivalent of a `char`.
373 ///
374 /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
375 /// its documentation for more.
376 ///
377 /// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase
378 /// [`char`]: ../../std/primitive.char.html
379 #[stable(feature = "rust1", since = "1.0.0")]
380 #[derive(Debug, Clone)]
381 pub struct ToLowercase(CaseMappingIter);
382
383 #[stable(feature = "rust1", since = "1.0.0")]
384 impl Iterator for ToLowercase {
385     type Item = char;
386     fn next(&mut self) -> Option<char> {
387         self.0.next()
388     }
389     fn size_hint(&self) -> (usize, Option<usize>) {
390         self.0.size_hint()
391     }
392 }
393
394 #[stable(feature = "fused", since = "1.26.0")]
395 impl FusedIterator for ToLowercase {}
396
397 #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
398 impl ExactSizeIterator for ToLowercase {}
399
400 /// Returns an iterator that yields the uppercase equivalent of a `char`.
401 ///
402 /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
403 /// its documentation for more.
404 ///
405 /// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase
406 /// [`char`]: ../../std/primitive.char.html
407 #[stable(feature = "rust1", since = "1.0.0")]
408 #[derive(Debug, Clone)]
409 pub struct ToUppercase(CaseMappingIter);
410
411 #[stable(feature = "rust1", since = "1.0.0")]
412 impl Iterator for ToUppercase {
413     type Item = char;
414     fn next(&mut self) -> Option<char> {
415         self.0.next()
416     }
417     fn size_hint(&self) -> (usize, Option<usize>) {
418         self.0.size_hint()
419     }
420 }
421
422 #[stable(feature = "fused", since = "1.26.0")]
423 impl FusedIterator for ToUppercase {}
424
425 #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
426 impl ExactSizeIterator for ToUppercase {}
427
428 #[derive(Debug, Clone)]
429 enum CaseMappingIter {
430     Three(char, char, char),
431     Two(char, char),
432     One(char),
433     Zero,
434 }
435
436 impl CaseMappingIter {
437     fn new(chars: [char; 3]) -> CaseMappingIter {
438         if chars[2] == '\0' {
439             if chars[1] == '\0' {
440                 CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0'
441             } else {
442                 CaseMappingIter::Two(chars[0], chars[1])
443             }
444         } else {
445             CaseMappingIter::Three(chars[0], chars[1], chars[2])
446         }
447     }
448 }
449
450 impl Iterator for CaseMappingIter {
451     type Item = char;
452     fn next(&mut self) -> Option<char> {
453         match *self {
454             CaseMappingIter::Three(a, b, c) => {
455                 *self = CaseMappingIter::Two(b, c);
456                 Some(a)
457             }
458             CaseMappingIter::Two(b, c) => {
459                 *self = CaseMappingIter::One(c);
460                 Some(b)
461             }
462             CaseMappingIter::One(c) => {
463                 *self = CaseMappingIter::Zero;
464                 Some(c)
465             }
466             CaseMappingIter::Zero => None,
467         }
468     }
469
470     fn size_hint(&self) -> (usize, Option<usize>) {
471         let size = match self {
472             CaseMappingIter::Three(..) => 3,
473             CaseMappingIter::Two(..) => 2,
474             CaseMappingIter::One(_) => 1,
475             CaseMappingIter::Zero => 0,
476         };
477         (size, Some(size))
478     }
479 }
480
481 impl fmt::Display for CaseMappingIter {
482     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483         match *self {
484             CaseMappingIter::Three(a, b, c) => {
485                 f.write_char(a)?;
486                 f.write_char(b)?;
487                 f.write_char(c)
488             }
489             CaseMappingIter::Two(b, c) => {
490                 f.write_char(b)?;
491                 f.write_char(c)
492             }
493             CaseMappingIter::One(c) => f.write_char(c),
494             CaseMappingIter::Zero => Ok(()),
495         }
496     }
497 }
498
499 #[stable(feature = "char_struct_display", since = "1.16.0")]
500 impl fmt::Display for ToLowercase {
501     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502         fmt::Display::fmt(&self.0, f)
503     }
504 }
505
506 #[stable(feature = "char_struct_display", since = "1.16.0")]
507 impl fmt::Display for ToUppercase {
508     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509         fmt::Display::fmt(&self.0, f)
510     }
511 }