Skip to main content

encode_unicode/
utf8_char.rs

1/* Copyright 2016-2022 Torbjørn Birch Moltu
2 *
3 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 * http://opensource.org/licenses/MIT>, at your option. This file may not be
6 * copied, modified, or distributed except according to those terms.
7 */
8
9use crate::errors::{FromStrError, EmptyStrError, NonAsciiError, Utf8Error};
10use crate::utf8_iterators::Utf8Iterator;
11use crate::traits::{CharExt, U8UtfExt};
12use crate::utf16_char::Utf16Char;
13extern crate core;
14use core::{hash, fmt, str, ptr};
15use core::cmp::Ordering;
16use core::borrow::Borrow;
17use core::ops::Deref;
18#[cfg(feature="std")]
19use core::iter::FromIterator;
20#[cfg(feature="ascii")]
21extern crate ascii;
22#[cfg(feature="ascii")]
23use ascii::{AsciiChar,ToAsciiChar,ToAsciiCharError};
24
25
26// I don't think there is any good default value for char, but char does.
27#[derive(Default)]
28// char doesn't do anything more advanced than u32 for Eq/Ord, so we shouldn't either.
29// The default impl of Ord for arrays works out because longer codepoints
30//     start with more ones, so if they're equal, the length is the same,
31// breaks down for values above 0x1f_ff_ff but those can only be created by unsafe code.
32#[derive(PartialEq,Eq, PartialOrd,Ord)]
33
34#[derive(Clone,Copy)]
35
36
37/// An unicode codepoint stored as UTF-8.
38///
39/// It can be borrowed as a `str`, and has the same size as `char`.
40pub struct Utf8Char {
41    bytes: [u8; 4],
42}
43
44
45  /////////////////////
46 //conversion traits//
47/////////////////////
48impl str::FromStr for Utf8Char {
49    type Err = FromStrError;
50    /// Create an `Utf8Char` from a string slice.
51    /// The string must contain exactly one codepoint.
52    ///
53    /// # Examples
54    ///
55    /// ```
56    /// use encode_unicode::error::FromStrError::*;
57    /// use encode_unicode::Utf8Char;
58    /// use std::str::FromStr;
59    ///
60    /// assert_eq!(Utf8Char::from_str("a"), Ok(Utf8Char::from('a')));
61    /// assert_eq!(Utf8Char::from_str("🂠"), Ok(Utf8Char::from('🂠')));
62    /// assert_eq!(Utf8Char::from_str(""), Err(Empty));
63    /// assert_eq!(Utf8Char::from_str("ab"), Err(MultipleCodepoints));
64    /// assert_eq!(Utf8Char::from_str("é"), Err(MultipleCodepoints));// 'e'+u301 combining mark
65    /// ```
66    fn from_str(s: &str) -> Result<Self, FromStrError> {
67        if s.is_empty() {
68            Err(FromStrError::Empty)
69        } else if s.len() != 1+s.as_bytes()[0].extra_utf8_bytes_unchecked() {
70            Err(FromStrError::MultipleCodepoints)
71        } else {
72            let mut bytes = [0; 4];
73            bytes[..s.len()].copy_from_slice(s.as_bytes());
74            Ok(Utf8Char{bytes})
75        }
76    }
77}
78impl From<Utf16Char> for Utf8Char {
79    fn from(utf16: Utf16Char) -> Utf8Char {
80        match utf16.to_tuple() {
81            (ascii @ 0..=0x00_7f, _) => {
82                Utf8Char{ bytes: [ascii as u8, 0, 0, 0] }
83            },
84            (unit @ 0..=0x07_ff, _) => {
85                let byte2 = 0x80 |  (unit & 0x00_3f) as u8;
86                let byte1 = 0xc0 | ((unit & 0x07_c0) >> 6) as u8;
87                Utf8Char{ bytes: [byte1, byte2, 0, 0] }
88            },
89            (unit, None) => {
90                let byte3 = 0x80 |  (unit & 0x00_3f) as u8;
91                let byte2 = 0x80 | ((unit & 0x0f_c0) >> 6) as u8;
92                let byte1 = 0xe0 | ((unit & 0xf0_00) >> 12) as u8;
93                Utf8Char{ bytes: [byte1, byte2, byte3, 0] }
94            },
95            (first, Some(second)) => {
96                let first = first + (0x01_00_00u32 >> 10) as u16;
97                let byte4 = 0x80 |  (second & 0x00_3f) as u8;
98                let byte3 = 0x80 | ((second & 0x03_c0) >> 6) as u8
99                                 | (( first & 0x00_03) << 4) as u8;
100                let byte2 = 0x80 | (( first & 0x00_fc) >> 2) as u8;
101                let byte1 = 0xf0 | (( first & 0x07_00) >> 8) as u8;
102                Utf8Char{ bytes: [byte1, byte2, byte3, byte4] }
103            }
104        }
105    }
106}
107impl From<char> for Utf8Char {
108    fn from(c: char) -> Self {
109        Utf8Char::new(c)
110    }
111}
112impl From<Utf8Char> for char {
113    fn from(uc: Utf8Char) -> char {
114        uc.to_char()
115    }
116}
117impl IntoIterator for Utf8Char {
118    type Item=u8;
119    type IntoIter=Utf8Iterator;
120    /// Iterate over the byte values.
121    fn into_iter(self) -> Utf8Iterator {
122        Utf8Iterator::from(self)
123    }
124}
125
126#[cfg(feature="std")]
127impl Extend<Utf8Char> for Vec<u8> {
128    fn extend<I:IntoIterator<Item=Utf8Char>>(&mut self,  iter: I) {
129        let iter = iter.into_iter();
130        self.reserve(iter.size_hint().0);
131        for u8c in iter {
132            // twice as fast as self.extend_from_slice(u8c.as_bytes());
133            self.push(u8c.bytes[0]);
134            for &extra in &u8c.bytes[1..] {
135                if extra != 0 {
136                    self.push(extra);
137                }
138            }
139        }
140    }
141}
142#[cfg(feature="std")]
143impl<'a> Extend<&'a Utf8Char> for Vec<u8> {
144    fn extend<I:IntoIterator<Item=&'a Utf8Char>>(&mut self,  iter: I) {
145        self.extend(iter.into_iter().cloned())
146    }
147}
148#[cfg(feature="std")]
149impl Extend<Utf8Char> for String {
150    fn extend<I:IntoIterator<Item=Utf8Char>>(&mut self,  iter: I) {
151        unsafe { self.as_mut_vec().extend(iter) }
152    }
153}
154#[cfg(feature="std")]
155impl<'a> Extend<&'a Utf8Char> for String {
156    fn extend<I:IntoIterator<Item=&'a Utf8Char>>(&mut self,  iter: I) {
157        self.extend(iter.into_iter().cloned())
158    }
159}
160#[cfg(feature="std")]
161impl FromIterator<Utf8Char> for String {
162    fn from_iter<I:IntoIterator<Item=Utf8Char>>(iter: I) -> String {
163        let mut string = String::new();
164        string.extend(iter);
165        return string;
166    }
167}
168#[cfg(feature="std")]
169impl<'a> FromIterator<&'a Utf8Char> for String {
170    fn from_iter<I:IntoIterator<Item=&'a Utf8Char>>(iter: I) -> String {
171        iter.into_iter().cloned().collect()
172    }
173}
174#[cfg(feature="std")]
175impl FromIterator<Utf8Char> for Vec<u8> {
176    fn from_iter<I:IntoIterator<Item=Utf8Char>>(iter: I) -> Self {
177        iter.into_iter().collect::<String>().into_bytes()
178    }
179}
180#[cfg(feature="std")]
181impl<'a> FromIterator<&'a Utf8Char> for Vec<u8> {
182    fn from_iter<I:IntoIterator<Item=&'a Utf8Char>>(iter: I) -> Self {
183        iter.into_iter().cloned().collect::<String>().into_bytes()
184    }
185}
186
187
188  /////////////////
189 //getter traits//
190/////////////////
191impl AsRef<[u8]> for Utf8Char {
192    fn as_ref(&self) -> &[u8] {
193        &self.bytes[..self.len()]
194    }
195}
196impl AsRef<str> for Utf8Char {
197    fn as_ref(&self) -> &str {
198        unsafe{ str::from_utf8_unchecked( self.as_ref() ) }
199    }
200}
201impl Borrow<[u8]> for Utf8Char {
202    fn borrow(&self) -> &[u8] {
203        self.as_ref()
204    }
205}
206impl Borrow<str> for Utf8Char {
207    fn borrow(&self) -> &str {
208        self.as_ref()
209    }
210}
211impl Deref for Utf8Char {
212    type Target = str;
213    fn deref(&self) -> &Self::Target {
214        self.as_ref()
215    }
216}
217
218
219  ////////////////
220 //ascii traits//
221////////////////
222#[cfg(feature="ascii")]
223/// Requires the feature "ascii".
224impl From<AsciiChar> for Utf8Char {
225    fn from(ac: AsciiChar) -> Self {
226        Utf8Char{ bytes: [ac.as_byte(),0,0,0] }
227    }
228}
229#[cfg(feature="ascii")]
230/// Requires the feature "ascii".
231impl ToAsciiChar for Utf8Char {
232    fn to_ascii_char(self) -> Result<AsciiChar, ToAsciiCharError> {
233        self.bytes[0].to_ascii_char()
234    }
235    unsafe fn to_ascii_char_unchecked(self) -> AsciiChar {
236        unsafe { self.bytes[0].to_ascii_char_unchecked() }
237    }
238}
239
240
241  /////////////////////////////////////////////////////////
242 //Genaral traits that cannot be derived to emulate char//
243/////////////////////////////////////////////////////////
244impl hash::Hash for Utf8Char {
245    fn hash<H : hash::Hasher>(&self,  state: &mut H) {
246        self.to_char().hash(state);
247    }
248}
249impl fmt::Debug for Utf8Char {
250    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result {
251        fmt::Debug::fmt(&self.to_char(), fmtr)
252    }
253}
254impl fmt::Display for Utf8Char {
255    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result {
256        fmtr.write_str(self.as_str())
257    }
258}
259
260
261  ////////////////////////////////
262 //Comparisons with other types//
263////////////////////////////////
264impl PartialEq<char> for Utf8Char {
265    fn eq(&self,  u32c: &char) -> bool {
266        *self == Utf8Char::from(*u32c)
267    }
268}
269impl PartialEq<Utf8Char> for char {
270    fn eq(&self,  u8c: &Utf8Char) -> bool {
271        Utf8Char::from(*self) == *u8c
272    }
273}
274impl PartialOrd<char> for Utf8Char {
275    fn partial_cmp(&self,  u32c: &char) -> Option<Ordering> {
276        self.partial_cmp(&Self::from(*u32c))
277    }
278}
279impl PartialOrd<Utf8Char> for char {
280    fn partial_cmp(&self,  u8c: &Utf8Char) -> Option<Ordering> {
281        Utf8Char::from(*self).partial_cmp(u8c)
282    }
283}
284
285impl PartialEq<Utf16Char> for Utf8Char {
286    fn eq(&self,  u16c: &Utf16Char) -> bool {
287        *self == Self::from(*u16c)
288    }
289}
290impl PartialOrd<Utf16Char> for Utf8Char {
291    fn partial_cmp(&self,  u16c: &Utf16Char) -> Option<Ordering> {
292        self.partial_cmp(&Self::from(*u16c))
293    }
294}
295// The other direction is implemented in utf16_char.rs
296
297/// Only considers the byte equal if both it and the `Utf8Char` represents ASCII characters.
298///
299/// There is no impl in the opposite direction, as this should only be used to
300/// compare `Utf8Char`s against constants.
301///
302/// # Examples
303///
304/// ```
305/// # use encode_unicode::Utf8Char;
306/// assert!(Utf8Char::from('8') == b'8');
307/// assert!(Utf8Char::from_array([0xf1,0x80,0x80,0x80]).unwrap() != 0xf1);
308/// assert!(Utf8Char::from('\u{ff}') != 0xff);
309/// assert!(Utf8Char::from('\u{80}') != 0x80);
310/// ```
311impl PartialEq<u8> for Utf8Char {
312    fn eq(&self,  byte: &u8) -> bool {
313        self.bytes[0] == *byte  &&  self.bytes[1] == 0
314    }
315}
316#[cfg(feature = "ascii")]
317/// `Utf8Char`s that are not ASCII never compare equal.
318impl PartialEq<AsciiChar> for Utf8Char {
319    #[inline]
320    fn eq(&self,  ascii: &AsciiChar) -> bool {
321        self.bytes[0] == *ascii as u8
322    }
323}
324#[cfg(feature = "ascii")]
325/// `Utf8Char`s that are not ASCII never compare equal.
326impl PartialEq<Utf8Char> for AsciiChar {
327    #[inline]
328    fn eq(&self,  u8c: &Utf8Char) -> bool {
329        u8c == self
330    }
331}
332#[cfg(feature = "ascii")]
333/// `Utf8Char`s that are not ASCII always compare greater.
334impl PartialOrd<AsciiChar> for Utf8Char {
335    #[inline]
336    fn partial_cmp(&self,  ascii: &AsciiChar) -> Option<Ordering> {
337        self.bytes[0].partial_cmp(ascii)
338    }
339}
340#[cfg(feature = "ascii")]
341/// `Utf8Char`s that are not ASCII always compare greater.
342impl PartialOrd<Utf8Char> for AsciiChar {
343    #[inline]
344    fn partial_cmp(&self,  u8c: &Utf8Char) -> Option<Ordering> {
345        self.partial_cmp(&u8c.bytes[0])
346    }
347}
348
349
350  ///////////////////////////////////////////////////////
351 //pub impls that should be together for nicer rustdoc//
352///////////////////////////////////////////////////////
353impl Utf8Char {
354    /// A `const fn` alternative to the trait-based `Utf8Char::from(char)`.
355    ///
356    /// # Example
357    ///
358    /// ```
359    /// # use encode_unicode::Utf8Char;
360    /// const REPLACEMENT_CHARACTER: Utf8Char = Utf8Char::new('\u{fffd}');
361    /// ```
362    pub const fn new(c: char) -> Self {
363        if c.is_ascii() {
364            Utf8Char{bytes: [c as u8, 0, 0, 0]}
365        } else {
366            // How many extra UTF-8 bytes that are needed to represent an
367            // UTF-32 codepoint with a number of bits.
368            // Stored as a bit-packed array using two bits per value.
369            // 0..=7 bits = no extra bytes
370            // +4 = 8..=11 bits = one xtra byte (5+6 bits)
371            // +5 = 12..=16 bits = two extra bytes (4+6+6 bits)
372            // +5 = 17..=21 bits = three extra bytes (3+6+6+6 bits)
373            const EXTRA_BYTES: u64 = 0b11_11_11_11_11__10_10_10_10_10__01_01_01_01__00_00_00_00_00_00_00__00;
374            let bits_used = 32 - (c as u32).leading_zeros();
375            let len = 1 + ((EXTRA_BYTES >> (bits_used*2)) & 0b11);
376            // copied from CharExt::to_utf8_array()
377            let mut c = c as u32;
378            let mut parts = 0;// convert to 6-bit bytes
379                        parts |= c & 0x3f;  c>>=6;
380            parts<<=8;  parts |= c & 0x3f;  c>>=6;
381            parts<<=8;  parts |= c & 0x3f;  c>>=6;
382            parts<<=8;  parts |= c & 0x3f;
383            parts |= 0x80_80_80_80;// set the most significant bit
384            parts >>= 8*(4-len);// right-align bytes
385            // Now, unused bytes are zero, (which matters for Utf8Char.eq())
386            // and the rest are 0b10xx_xxxx
387
388            // set header on first byte
389            parts |= (0xff_00u32 >> len)  &  0xff;// store length
390            parts &= !(1u32 << (7-len));// clear the next bit after it
391
392            Utf8Char {bytes: parts.to_le_bytes()}
393        }
394    }
395
396    /// Create an `Utf8Char` from the first codepoint in a `str`.
397    ///
398    /// Returns an error if the `str` is empty.
399    ///
400    /// # Examples
401    ///
402    /// ```
403    /// use encode_unicode::Utf8Char;
404    ///
405    /// assert_eq!(Utf8Char::from_str_start("a"), Ok((Utf8Char::from('a'),1)));
406    /// assert_eq!(Utf8Char::from_str_start("ab"), Ok((Utf8Char::from('a'),1)));
407    /// assert_eq!(Utf8Char::from_str_start("🂠 "), Ok((Utf8Char::from('🂠'),4)));
408    /// assert_eq!(Utf8Char::from_str_start("é"), Ok((Utf8Char::from('e'),1)));// 'e'+u301 combining mark
409    /// assert!(Utf8Char::from_str_start("").is_err());
410    /// ```
411    pub fn from_str_start(src: &str) -> Result<(Self,usize),EmptyStrError> {
412        unsafe {
413            if src.is_empty() {
414                Err(EmptyStrError)
415            } else {
416                Ok(Utf8Char::from_slice_start_unchecked(src.as_bytes()))
417            }
418        }
419    }
420    /// Create an `Utf8Char` of the first codepoint in an UTF-8 slice.  
421    /// Also returns the length of the UTF-8 sequence for the codepoint.
422    ///
423    /// If the slice is from a `str`, use `::from_str_start()` to skip UTF-8 validation.
424    ///
425    /// # Errors
426    ///
427    /// Returns an `Err` if the slice is empty, doesn't start with a valid
428    /// UTF-8 sequence or is too short for the sequence.
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// use encode_unicode::Utf8Char;
434    /// use encode_unicode::error::Utf8ErrorKind::*;
435    ///
436    /// assert_eq!(Utf8Char::from_slice_start(&[b'A', b'B', b'C']), Ok((Utf8Char::from('A'),1)));
437    /// assert_eq!(Utf8Char::from_slice_start(&[0xdd, 0xbb]), Ok((Utf8Char::from('\u{77b}'),2)));
438    ///
439    /// assert_eq!(Utf8Char::from_slice_start(&[]).unwrap_err().kind(), TooFewBytes);
440    /// assert_eq!(Utf8Char::from_slice_start(&[0xf0, 0x99]).unwrap_err().kind(), TooFewBytes);
441    /// assert_eq!(Utf8Char::from_slice_start(&[0xee, b'F', 0x80]).unwrap_err().kind(), InterruptedSequence);
442    /// assert_eq!(Utf8Char::from_slice_start(&[0xee, 0x99, 0x0f]).unwrap_err().kind(), InterruptedSequence);
443    /// ```
444    pub fn from_slice_start(src: &[u8]) -> Result<(Self,usize),Utf8Error> {
445        char::from_utf8_slice_start(src).map(|(_,len)| {
446            let mut bytes = [0; 4];
447            bytes[..len].copy_from_slice(&src[..len]);
448            (Utf8Char{bytes}, len)
449        })
450    }
451    /// A `from_slice_start()` that doesn't validate the codepoint.
452    ///
453    /// # Safety
454    ///
455    /// The slice must be non-empty and start with a valid UTF-8 codepoint.  
456    /// Invalid or incomplete values might cause reads of uninitalized memory.
457    pub unsafe fn from_slice_start_unchecked(src: &[u8]) -> (Self,usize) {
458        unsafe {
459            let len = 1+src.get_unchecked(0).extra_utf8_bytes_unchecked();
460            let mut bytes = [0; 4];
461            ptr::copy_nonoverlapping(src.as_ptr(), bytes.as_mut_ptr() as *mut u8, len);
462            (Utf8Char{bytes}, len)
463        }
464    }
465    /// Create an `Utf8Char` from a byte array after validating it.
466    ///
467    /// The codepoint must start at the first byte.  
468    /// Unused bytes are set to zero by this function and so can be anything.
469    ///
470    /// # Errors
471    ///
472    /// Returns an `Err` if the array doesn't start with a valid UTF-8 sequence.
473    ///
474    /// # Examples
475    ///
476    /// ```
477    /// use encode_unicode::Utf8Char;
478    /// use encode_unicode::error::Utf8ErrorKind::*;
479    ///
480    /// assert_eq!(Utf8Char::from_array([b'A', 0, 0, 0]), Ok(Utf8Char::from('A')));
481    /// assert_eq!(Utf8Char::from_array([0xf4, 0x8b, 0xbb, 0xbb]), Ok(Utf8Char::from('\u{10befb}')));
482    /// assert_eq!(Utf8Char::from_array([b'A', b'B', b'C', b'D']), Ok(Utf8Char::from('A')));
483    /// assert_eq!(Utf8Char::from_array([0, 0, 0xcc, 0xbb]), Ok(Utf8Char::from('\0')));
484    ///
485    /// assert_eq!(Utf8Char::from_array([0xef, b'F', 0x80, 0x80]).unwrap_err().kind(), InterruptedSequence);
486    /// assert_eq!(Utf8Char::from_array([0xc1, 0x80, 0, 0]).unwrap_err().kind(), NonUtf8Byte);
487    /// assert_eq!(Utf8Char::from_array([0xe0, 0x9a, 0xbf, 0]).unwrap_err().kind(), OverlongEncoding);
488    /// assert_eq!(Utf8Char::from_array([0xf4, 0xaa, 0x99, 0x88]).unwrap_err().kind(), TooHighCodepoint);
489    /// ```
490    pub fn from_array(utf8: [u8;4]) -> Result<Self,Utf8Error> {
491        // perform all validation
492        char::from_utf8_array(utf8)?;
493        let extra = utf8[0].extra_utf8_bytes_unchecked() as u32;
494        // zero unused bytes in one operation by transmuting the arrary to
495        // u32, apply an endian-corrected mask and transmute back
496        let mask = u32::from_le(0xff_ff_ff_ff >> (8*(3-extra)));
497        let unused_zeroed = mask  &  u32::from_ne_bytes(utf8); // native endian
498        Ok(Utf8Char{ bytes: unused_zeroed.to_ne_bytes() })
499    }
500    /// Zero-cost constructor.
501    ///
502    /// # Safety
503    ///
504    /// Must contain a valid codepoint starting at the first byte, with the
505    /// unused bytes zeroed.  
506    /// Bad values can easily lead to undefined behavior.
507    #[inline]
508    pub const unsafe fn from_array_unchecked(utf8: [u8;4]) -> Self {
509        Utf8Char{ bytes: utf8 }
510    }
511    /// Create an `Utf8Char` from a single byte.
512    ///
513    /// The byte must be an ASCII character.
514    ///
515    /// # Errors
516    ///
517    /// Returns `NonAsciiError` if the byte greater than 127.
518    ///
519    /// # Examples
520    ///
521    /// ```
522    /// # use encode_unicode::Utf8Char;
523    /// assert_eq!(Utf8Char::from_ascii(b'a').unwrap(), 'a');
524    /// assert!(Utf8Char::from_ascii(128).is_err());
525    /// ```
526    pub const fn from_ascii(ascii: u8) -> Result<Self,NonAsciiError> {
527        [Ok(Utf8Char{ bytes: [ascii, 0, 0, 0] }), Err(NonAsciiError)][(ascii >> 7) as usize]
528    }
529    /// Create an `Utf8Char` from a single byte without checking that it's a
530    /// valid codepoint on its own, which is only true for ASCII characters.
531    ///
532    /// # Safety
533    ///
534    /// The byte must be less than 128.
535    #[inline]
536    pub const unsafe fn from_ascii_unchecked(ascii: u8) -> Self {
537        Utf8Char{ bytes: [ascii, 0, 0, 0] }
538    }
539
540    /// The number of bytes this character needs.
541    ///
542    /// Is between 1 and 4 (inclusive) and identical to `.as_ref().len()` or
543    /// `.as_char().len_utf8()`.
544    #[inline]
545    pub const fn len(self) -> usize {
546        // Invariants of the extra bytes enambles algorithms that
547        // `u8.extra_utf8_bytes_unchecked()` cannot use.
548        // Some of them turned out to require fewer x86 instructions:
549
550        // Exploits that unused bytes are zero and calculates the number of
551        // trailing zero bytes.
552        // Setting a bit in the first byte prevents the function from returning
553        // 0 for '\0' (which has 32 leading zeros).
554        // trailing and leading is swapped below to optimize for little-endian
555        // architectures.
556        (4 - (u32::from_le_bytes(self.bytes)|1).leading_zeros()/8) as usize
557
558        // Exploits that the extra bytes have their most significant bit set if
559        // in use.
560        // Takes fewer instructions than the one above if popcnt can be used,
561        // (which it cannot by default,
562        //  set RUSTFLAGS='-C target-cpu=native' to enable)
563        //let all = u32::from_ne_bytes(self.bytes);
564        //let msb_mask = u32::from_be(0x00808080);
565        //let add_one = u32::from_be(0x80000000);
566        //((all & msb_mask) | add_one).count_ones() as usize
567    }
568    // There is no .is_emty() because this type is never empty.
569
570    /// Checks that the codepoint is an ASCII character.
571    pub const fn is_ascii(self) -> bool {
572        self.bytes[0].is_ascii()
573    }
574    /// Checks that two characters are an ASCII case-insensitive match.
575    ///
576    /// Is equivalent to `a.to_ascii_lowercase() == b.to_ascii_lowercase()`.
577    pub const fn eq_ignore_ascii_case(&self,  other: &Self) -> bool {
578        if self.is_ascii() {
579            self.bytes[0].eq_ignore_ascii_case(&other.bytes[0])
580        } else {
581            // [u8; 4] can't be const compared as of Rust 1.60, but u32 can
582            u32::from_le_bytes(self.bytes) == u32::from_le_bytes(other.bytes)
583        }
584    }
585    /// Converts the character to its ASCII upper case equivalent.
586    ///
587    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
588    /// but non-ASCII letters are unchanged.
589    pub const fn to_ascii_uppercase(mut self) -> Self {
590        self.bytes[0] = self.bytes[0].to_ascii_uppercase();
591        self
592    }
593    /// Converts the character to its ASCII lower case equivalent.
594    ///
595    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
596    /// but non-ASCII letters are unchanged.
597    pub const fn to_ascii_lowercase(mut self) -> Self {
598        self.bytes[0] = self.bytes[0].to_ascii_lowercase();
599        self
600    }
601    /// Converts the character to its ASCII upper case equivalent in-place.
602    ///
603    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
604    /// but non-ASCII letters are unchanged.
605    #[inline]
606    pub fn make_ascii_uppercase(&mut self) {
607        self.bytes[0].make_ascii_uppercase()
608    }
609    /// Converts the character to its ASCII lower case equivalent in-place.
610    ///
611    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
612    /// but non-ASCII letters are unchanged.
613    #[inline]
614    pub fn make_ascii_lowercase(&mut self) {
615        self.bytes[0].make_ascii_lowercase();
616    }
617
618    /// Convert from UTF-8 to UTF-32
619    pub fn to_char(self) -> char {
620        unsafe { char::from_utf8_exact_slice_unchecked(&self.bytes[..self.len()]) }
621    }
622    /// Write the internal representation to a slice,
623    /// and then returns the number of bytes written.
624    ///
625    /// # Panics
626    ///
627    /// Will panic the buffer is too small;
628    /// You can get the required length from `.len()`,
629    /// but a buffer of length four is always large enough.
630    pub fn to_slice(self,  dst: &mut[u8]) -> usize {
631        if self.len() > dst.len() {
632            panic!("The provided buffer is too small.");
633        }
634        dst[..self.len()].copy_from_slice(&self.bytes[..self.len()]);
635        self.len()
636    }
637    /// Expose the internal array and the number of used bytes.
638    pub const fn to_array(self) -> ([u8;4],usize) {
639        (self.bytes, self.len())
640    }
641    /// Return a `str` view of the array the codepoint is stored as.
642    ///
643    /// Is an unambiguous version of `.as_ref()`.
644    pub fn as_str(&self) -> &str {
645        self.deref()
646    }
647}