]> git.lizzy.rs Git - rust.git/blob - src/libunicode/char.rs
Auto merge of #23678 - richo:check-flightcheck, r=alexcrichton
[rust.git] / src / libunicode / char.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Character manipulation (`char` type, Unicode Scalar Value)
12 //!
13 //! This module provides the `CharExt` trait, as well as its
14 //! implementation for the primitive `char` type, in order to allow
15 //! basic character manipulation.
16 //!
17 //! A `char` actually represents a
18 //! *[Unicode Scalar
19 //! Value](http://www.unicode.org/glossary/#unicode_scalar_value)*, as it can
20 //! contain any Unicode code point except high-surrogate and low-surrogate code
21 //! points.
22 //!
23 //! As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
24 //! (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
25 //! however the converse is not always true due to the above range limits
26 //! and, as such, should be performed via the `from_u32` function.
27
28 #![stable(feature = "rust1", since = "1.0.0")]
29 #![doc(primitive = "char")]
30
31 use core::char::CharExt as C;
32 use core::option::Option::{self, Some};
33 use core::iter::Iterator;
34 use tables::{derived_property, property, general_category, conversions, charwidth};
35
36 // stable reexports
37 pub use core::char::{MAX, from_u32, from_digit, EscapeUnicode, EscapeDefault};
38
39 // unstable reexports
40 pub use normalize::{decompose_canonical, decompose_compatible, compose};
41 pub use tables::normalization::canonical_combining_class;
42 pub use tables::UNICODE_VERSION;
43
44 /// An iterator over the lowercase mapping of a given character, returned from
45 /// the [`to_lowercase` method](../primitive.char.html#method.to_lowercase) on
46 /// characters.
47 #[stable(feature = "rust1", since = "1.0.0")]
48 pub struct ToLowercase(Option<char>);
49
50 #[stable(feature = "rust1", since = "1.0.0")]
51 impl Iterator for ToLowercase {
52     type Item = char;
53     fn next(&mut self) -> Option<char> { self.0.take() }
54 }
55
56 /// An iterator over the uppercase mapping of a given character, returned from
57 /// the [`to_uppercase` method](../primitive.char.html#method.to_uppercase) on
58 /// characters.
59 #[stable(feature = "rust1", since = "1.0.0")]
60 pub struct ToUppercase(Option<char>);
61
62 #[stable(feature = "rust1", since = "1.0.0")]
63 impl Iterator for ToUppercase {
64     type Item = char;
65     fn next(&mut self) -> Option<char> { self.0.take() }
66 }
67
68 #[stable(feature = "rust1", since = "1.0.0")]
69 #[lang = "char"]
70 impl char {
71     /// Checks if a `char` parses as a numeric digit in the given radix.
72     ///
73     /// Compared to `is_numeric()`, this function only recognizes the characters
74     /// `0-9`, `a-z` and `A-Z`.
75     ///
76     /// # Return value
77     ///
78     /// Returns `true` if `c` is a valid digit under `radix`, and `false`
79     /// otherwise.
80     ///
81     /// # Panics
82     ///
83     /// Panics if given a radix > 36.
84     ///
85     /// # Examples
86     ///
87     /// ```
88     /// let c = '1';
89     ///
90     /// assert!(c.is_digit(10));
91     ///
92     /// assert!('f'.is_digit(16));
93     /// ```
94     #[stable(feature = "rust1", since = "1.0.0")]
95     #[inline]
96     pub fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) }
97
98     /// Converts a character to the corresponding digit.
99     ///
100     /// # Return value
101     ///
102     /// If `c` is between '0' and '9', the corresponding value between 0 and
103     /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns
104     /// none if the character does not refer to a digit in the given radix.
105     ///
106     /// # Panics
107     ///
108     /// Panics if given a radix outside the range [0..36].
109     ///
110     /// # Examples
111     ///
112     /// ```
113     /// let c = '1';
114     ///
115     /// assert_eq!(c.to_digit(10), Some(1));
116     ///
117     /// assert_eq!('f'.to_digit(16), Some(15));
118     /// ```
119     #[stable(feature = "rust1", since = "1.0.0")]
120     pub fn to_digit(self, radix: u32) -> Option<u32> { C::to_digit(self, radix) }
121
122     /// Returns an iterator that yields the hexadecimal Unicode escape of a
123     /// character, as `char`s.
124     ///
125     /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
126     /// where `NNNN` is the shortest hexadecimal representation of the code
127     /// point.
128     ///
129     /// # Examples
130     ///
131     /// ```
132     /// for i in '❤'.escape_unicode() {
133     ///     println!("{}", i);
134     /// }
135     /// ```
136     ///
137     /// This prints:
138     ///
139     /// ```text
140     /// \
141     /// u
142     /// {
143     /// 2
144     /// 7
145     /// 6
146     /// 4
147     /// }
148     /// ```
149     ///
150     /// Collecting into a `String`:
151     ///
152     /// ```
153     /// let heart: String = '❤'.escape_unicode().collect();
154     ///
155     /// assert_eq!(heart, r"\u{2764}");
156     /// ```
157     #[stable(feature = "rust1", since = "1.0.0")]
158     pub fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) }
159
160     /// Returns an iterator that yields the 'default' ASCII and
161     /// C++11-like literal escape of a character, as `char`s.
162     ///
163     /// The default is chosen with a bias toward producing literals that are
164     /// legal in a variety of languages, including C++11 and similar C-family
165     /// languages. The exact rules are:
166     ///
167     /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
168     /// * Single-quote, double-quote and backslash chars are backslash-
169     ///   escaped.
170     /// * Any other chars in the range [0x20,0x7e] are not escaped.
171     /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
172     ///
173     /// # Examples
174     ///
175     /// ```
176     /// for i in '"'.escape_default() {
177     ///     println!("{}", i);
178     /// }
179     /// ```
180     ///
181     /// This prints:
182     ///
183     /// ```text
184     /// \
185     /// "
186     /// ```
187     ///
188     /// Collecting into a `String`:
189     ///
190     /// ```
191     /// let quote: String = '"'.escape_default().collect();
192     ///
193     /// assert_eq!(quote, "\\\"");
194     /// ```
195     #[stable(feature = "rust1", since = "1.0.0")]
196     pub fn escape_default(self) -> EscapeDefault { C::escape_default(self) }
197
198     /// Returns the number of bytes this character would need if encoded in
199     /// UTF-8.
200     ///
201     /// # Examples
202     ///
203     /// ```
204     /// let n = 'ß'.len_utf8();
205     ///
206     /// assert_eq!(n, 2);
207     /// ```
208     #[stable(feature = "rust1", since = "1.0.0")]
209     pub fn len_utf8(self) -> usize { C::len_utf8(self) }
210
211     /// Returns the number of 16-bit code units this character would need if
212     /// encoded in UTF-16.
213     ///
214     /// # Examples
215     ///
216     /// ```
217     /// let n = 'ß'.len_utf16();
218     ///
219     /// assert_eq!(n, 1);
220     /// ```
221     #[stable(feature = "rust1", since = "1.0.0")]
222     pub fn len_utf16(self) -> usize { C::len_utf16(self) }
223
224     /// Encodes this character as UTF-8 into the provided byte buffer, and then
225     /// returns the number of bytes written.
226     ///
227     /// If the buffer is not large enough, nothing will be written into it and a
228     /// `None` will be returned. A buffer of length four is large enough to
229     /// encode any `char`.
230     ///
231     /// # Examples
232     ///
233     /// In both of these examples, 'ß' takes two bytes to encode.
234     ///
235     /// ```
236     /// # #![feature(unicode)]
237     /// let mut b = [0; 2];
238     ///
239     /// let result = 'ß'.encode_utf8(&mut b);
240     ///
241     /// assert_eq!(result, Some(2));
242     /// ```
243     ///
244     /// A buffer that's too small:
245     ///
246     /// ```
247     /// # #![feature(unicode)]
248     /// let mut b = [0; 1];
249     ///
250     /// let result = 'ß'.encode_utf8(&mut b);
251     ///
252     /// assert_eq!(result, None);
253     /// ```
254     #[unstable(feature = "unicode",
255                reason = "pending decision about Iterator/Writer/Reader")]
256     pub fn encode_utf8(self, dst: &mut [u8]) -> Option<usize> { C::encode_utf8(self, dst) }
257
258     /// Encodes this character as UTF-16 into the provided `u16` buffer, and
259     /// then returns the number of `u16`s written.
260     ///
261     /// If the buffer is not large enough, nothing will be written into it and a
262     /// `None` will be returned. A buffer of length 2 is large enough to encode
263     /// any `char`.
264     ///
265     /// # Examples
266     ///
267     /// In both of these examples, 'ß' takes one `u16` to encode.
268     ///
269     /// ```
270     /// # #![feature(unicode)]
271     /// let mut b = [0; 1];
272     ///
273     /// let result = 'ß'.encode_utf16(&mut b);
274     ///
275     /// assert_eq!(result, Some(1));
276     /// ```
277     ///
278     /// A buffer that's too small:
279     ///
280     /// ```
281     /// # #![feature(unicode)]
282     /// let mut b = [0; 0];
283     ///
284     /// let result = 'ß'.encode_utf8(&mut b);
285     ///
286     /// assert_eq!(result, None);
287     /// ```
288     #[unstable(feature = "unicode",
289                reason = "pending decision about Iterator/Writer/Reader")]
290     pub fn encode_utf16(self, dst: &mut [u16]) -> Option<usize> { C::encode_utf16(self, dst) }
291
292     /// Returns whether the specified character is considered a Unicode
293     /// alphabetic code point.
294     #[stable(feature = "rust1", since = "1.0.0")]
295     #[inline]
296     pub fn is_alphabetic(self) -> bool {
297         match self {
298             'a' ... 'z' | 'A' ... 'Z' => true,
299             c if c > '\x7f' => derived_property::Alphabetic(c),
300             _ => false
301         }
302     }
303
304     /// Returns whether the specified character satisfies the 'XID_Start'
305     /// Unicode property.
306     ///
307     /// 'XID_Start' is a Unicode Derived Property specified in
308     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
309     /// mostly similar to ID_Start but modified for closure under NFKx.
310     #[unstable(feature = "unicode",
311                reason = "mainly needed for compiler internals")]
312     #[inline]
313     pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
314
315     /// Returns whether the specified `char` satisfies the 'XID_Continue'
316     /// Unicode property.
317     ///
318     /// 'XID_Continue' is a Unicode Derived Property specified in
319     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
320     /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
321     #[unstable(feature = "unicode",
322                reason = "mainly needed for compiler internals")]
323     #[inline]
324     pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
325
326     /// Indicates whether a character is in lowercase.
327     ///
328     /// This is defined according to the terms of the Unicode Derived Core
329     /// Property `Lowercase`.
330     #[stable(feature = "rust1", since = "1.0.0")]
331     #[inline]
332     pub fn is_lowercase(self) -> bool {
333         match self {
334             'a' ... 'z' => true,
335             c if c > '\x7f' => derived_property::Lowercase(c),
336             _ => false
337         }
338     }
339
340     /// Indicates whether a character is in uppercase.
341     ///
342     /// This is defined according to the terms of the Unicode Derived Core
343     /// Property `Uppercase`.
344     #[stable(feature = "rust1", since = "1.0.0")]
345     #[inline]
346     pub fn is_uppercase(self) -> bool {
347         match self {
348             'A' ... 'Z' => true,
349             c if c > '\x7f' => derived_property::Uppercase(c),
350             _ => false
351         }
352     }
353
354     /// Indicates whether a character is whitespace.
355     ///
356     /// Whitespace is defined in terms of the Unicode Property `White_Space`.
357     #[stable(feature = "rust1", since = "1.0.0")]
358     #[inline]
359     pub fn is_whitespace(self) -> bool {
360         match self {
361             ' ' | '\x09' ... '\x0d' => true,
362             c if c > '\x7f' => property::White_Space(c),
363             _ => false
364         }
365     }
366
367     /// Indicates whether a character is alphanumeric.
368     ///
369     /// Alphanumericness is defined in terms of the Unicode General Categories
370     /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
371     #[stable(feature = "rust1", since = "1.0.0")]
372     #[inline]
373     pub fn is_alphanumeric(self) -> bool {
374         self.is_alphabetic() || self.is_numeric()
375     }
376
377     /// Indicates whether a character is a control code point.
378     ///
379     /// Control code points are defined in terms of the Unicode General
380     /// Category `Cc`.
381     #[stable(feature = "rust1", since = "1.0.0")]
382     #[inline]
383     pub fn is_control(self) -> bool { general_category::Cc(self) }
384
385     /// Indicates whether the character is numeric (Nd, Nl, or No).
386     #[stable(feature = "rust1", since = "1.0.0")]
387     #[inline]
388     pub fn is_numeric(self) -> bool {
389         match self {
390             '0' ... '9' => true,
391             c if c > '\x7f' => general_category::N(c),
392             _ => false
393         }
394     }
395
396     /// Converts a character to its lowercase equivalent.
397     ///
398     /// The case-folding performed is the common or simple mapping. See
399     /// `to_uppercase()` for references and more information.
400     ///
401     /// # Return value
402     ///
403     /// Returns an iterator which yields the characters corresponding to the
404     /// lowercase equivalent of the character. If no conversion is possible then
405     /// the input character is returned.
406     #[stable(feature = "rust1", since = "1.0.0")]
407     #[inline]
408     pub fn to_lowercase(self) -> ToLowercase {
409         ToLowercase(Some(conversions::to_lower(self)))
410     }
411
412     /// Converts a character to its uppercase equivalent.
413     ///
414     /// The case-folding performed is the common or simple mapping: it maps
415     /// one Unicode codepoint to its uppercase equivalent according to the
416     /// Unicode database [1]. The additional [`SpecialCasing.txt`] is not yet
417     /// considered here, but the iterator returned will soon support this form
418     /// of case folding.
419     ///
420     /// A full reference can be found here [2].
421     ///
422     /// # Return value
423     ///
424     /// Returns an iterator which yields the characters corresponding to the
425     /// uppercase equivalent of the character. If no conversion is possible then
426     /// the input character is returned.
427     ///
428     /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
429     ///
430     /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
431     ///
432     /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
433     #[stable(feature = "rust1", since = "1.0.0")]
434     #[inline]
435     pub fn to_uppercase(self) -> ToUppercase {
436         ToUppercase(Some(conversions::to_upper(self)))
437     }
438
439     /// Returns this character's displayed width in columns, or `None` if it is a
440     /// control character other than `'\x00'`.
441     ///
442     /// `is_cjk` determines behavior for characters in the Ambiguous category:
443     /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
444     /// In CJK contexts, `is_cjk` should be `true`, else it should be `false`.
445     /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
446     /// recommends that these characters be treated as 1 column (i.e.,
447     /// `is_cjk` = `false`) if the context cannot be reliably determined.
448     #[unstable(feature = "unicode",
449                reason = "needs expert opinion. is_cjk flag stands out as ugly")]
450     pub fn width(self, is_cjk: bool) -> Option<usize> { charwidth::width(self, is_cjk) }
451 }