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