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