text: //! Character conversions.
  
  use crate::convert::TryFrom;
  use crate::fmt;
  use crate::mem::transmute;
  use crate::str::FromStr;
  
  use super::MAX;
  
  /// Converts a `u32` to a `char`.
  ///
  /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
  /// `as`:
  ///
  /// ```
  /// let c = '💯';
  /// let i = c as u32;
  ///
  /// assert_eq!(128175, i);
  /// ```
  ///
  /// However, the reverse is not true: not all valid [`u32`]s are valid
  /// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
  /// for a [`char`].
  ///
  /// [`char`]: ../../std/primitive.char.html
  /// [`u32`]: ../../std/primitive.u32.html
  ///
  /// For an unsafe version of this function which ignores these checks, see
  /// [`from_u32_unchecked`].
  ///
  /// [`from_u32_unchecked`]: fn.from_u32_unchecked.html
  ///
  /// # Examples
  ///
  /// Basic usage:
  ///
  /// ```
  /// use std::char;
  ///
  /// let c = char::from_u32(0x2764);
  ///
  /// assert_eq!(Some('❤'), c);
  /// ```
  ///
  /// Returning `None` when the input is not a valid [`char`]:
  ///
  /// ```
  /// use std::char;
  ///
  /// let c = char::from_u32(0x110000);
  ///
  /// assert_eq!(None, c);
  /// ```
  #[inline]
  #[stable(feature = "rust1", since = "1.0.0")]
  pub fn from_u32(i: u32) -> Option<char> {
      char::try_from(i).ok()
  }
  
  /// Converts a `u32` to a `char`, ignoring validity.
  ///
  /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
  /// `as`:
  ///
  /// ```
  /// let c = '💯';
  /// let i = c as u32;
  ///
  /// assert_eq!(128175, i);
  /// ```
  ///
  /// However, the reverse is not true: not all valid [`u32`]s are valid
  /// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
  /// [`char`], possibly creating an invalid one.
  ///
  /// [`char`]: ../../std/primitive.char.html
  /// [`u32`]: ../../std/primitive.u32.html
  ///
  /// # Safety
  ///
  /// This function is unsafe, as it may construct invalid `char` values.
  ///
  /// For a safe version of this function, see the [`from_u32`] function.
  ///
  /// [`from_u32`]: fn.from_u32.html
  ///
  /// # Examples
  ///
  /// Basic usage:
  ///
  /// ```
  /// use std::char;
  ///
  /// let c = unsafe { char::from_u32_unchecked(0x2764) };
  ///
  /// assert_eq!('❤', c);
  /// ```
  #[inline]
  #[stable(feature = "char_from_unchecked", since = "1.5.0")]
  pub unsafe fn from_u32_unchecked(i: u32) -> char {
      transmute(i)
  }
  
  #[stable(feature = "char_convert", since = "1.13.0")]
  impl From<char> for u32 {
      /// Converts a [`char`] into a [`u32`].
      ///
      /// # Examples
      ///
      /// ```
      /// use std::mem;
      ///
      /// let c = 'c';
      /// let u = u32::from(c);
      /// assert!(4 == mem::size_of_val(&u))
      /// ```
      #[inline]
      fn from(c: char) -> Self {
          c as u32
      }
  }
  
  /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
  ///
  /// Unicode is designed such that this effectively decodes bytes
  /// with the character encoding that IANA calls ISO-8859-1.
  /// This encoding is compatible with ASCII.
  ///
  /// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
  /// which leaves some "blanks", byte values that are not assigned to any character.
  /// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
  ///
  /// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
  /// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
  /// to punctuation and various Latin characters.
  ///
  /// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
  /// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
  /// for a superset of Windows-1252 that fills the remaining blanks with corresponding
  /// C0 and C1 control codes.
  #[stable(feature = "char_convert", since = "1.13.0")]
  impl From<u8> for char {
      /// Converts a [`u8`] into a [`char`].
      ///
      /// # Examples
      ///
      /// ```
      /// use std::mem;
      ///
      /// let u = 32 as u8;
      /// let c = char::from(u);
      /// assert!(4 == mem::size_of_val(&c))
      /// ```
      #[inline]
      fn from(i: u8) -> Self {
          i as char
      }
  }
  
  /// An error which can be returned when parsing a char.
  #[stable(feature = "char_from_str", since = "1.20.0")]
  #[derive(Clone, Debug, PartialEq, Eq)]
  pub struct ParseCharError {
      kind: CharErrorKind,
  }
  
  impl ParseCharError {
      #[unstable(
          feature = "char_error_internals",
          reason = "this method should not be available publicly",
          issue = "none"
      )]
      #[doc(hidden)]
      pub fn __description(&self) -> &str {
          match self.kind {
              CharErrorKind::EmptyString => "cannot parse char from empty string",
              CharErrorKind::TooManyChars => "too many characters in string",
          }
      }
  }
  
  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
  enum CharErrorKind {
      EmptyString,
      TooManyChars,
  }
  
  #[stable(feature = "char_from_str", since = "1.20.0")]
  impl fmt::Display for ParseCharError {
      fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
          self.__description().fmt(f)
      }
  }
  
  #[stable(feature = "char_from_str", since = "1.20.0")]
  impl FromStr for char {
      type Err = ParseCharError;
  
      #[inline]
      fn from_str(s: &str) -> Result<Self, Self::Err> {
          let mut chars = s.chars();
          match (chars.next(), chars.next()) {
              (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
              (Some(c), None) => Ok(c),
              _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
          }
      }
  }
  
  #[stable(feature = "try_from", since = "1.34.0")]
  impl TryFrom<u32> for char {
      type Error = CharTryFromError;
  
      #[inline]
      fn try_from(i: u32) -> Result<Self, Self::Error> {
          if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
              Err(CharTryFromError(()))
          } else {
              // SAFETY: checked that it's a legal unicode value
              Ok(unsafe { from_u32_unchecked(i) })
          }
      }
  }
  
  /// The error type returned when a conversion from u32 to char fails.
  #[stable(feature = "try_from", since = "1.34.0")]
  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
  pub struct CharTryFromError(());
  
  #[stable(feature = "try_from", since = "1.34.0")]
  impl fmt::Display for CharTryFromError {
      fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
          "converted integer out of range for `char`".fmt(f)
      }
  }
  
  /// Converts a digit in the given radix to a `char`.
  ///
  /// A 'radix' here is sometimes also called a 'base'. A radix of two
  /// indicates a binary number, a radix of ten, decimal, and a radix of
  /// sixteen, hexadecimal, to give some common values. Arbitrary
  /// radices are supported.
  ///
  /// `from_digit()` will return `None` if the input is not a digit in
  /// the given radix.
  ///
  /// # Panics
  ///
  /// Panics if given a radix larger than 36.
  ///
  /// # Examples
  ///
  /// Basic usage:
  ///
  /// ```
  /// use std::char;
  ///
  /// let c = char::from_digit(4, 10);
  ///
  /// assert_eq!(Some('4'), c);
  ///
  /// // Decimal 11 is a single digit in base 16
  /// let c = char::from_digit(11, 16);
  ///
  /// assert_eq!(Some('b'), c);
  /// ```
  ///
  /// Returning `None` when the input is not a digit:
  ///
  /// ```
  /// use std::char;
  ///
  /// let c = char::from_digit(20, 10);
  ///
  /// assert_eq!(None, c);
  /// ```
  ///
  /// Passing a large radix, causing a panic:
  ///
  /// ```
  /// use std::thread;
  /// use std::char;
  ///
  /// let result = thread::spawn(|| {
  ///     // this panics
  ///     let c = char::from_digit(1, 37);
  /// }).join();
  ///
  /// assert!(result.is_err());
  /// ```
  #[inline]
  #[stable(feature = "rust1", since = "1.0.0")]
  pub fn from_digit(num: u32, radix: u32) -> Option<char> {
      if radix > 36 {
          panic!("from_digit: radix is too high (maximum 36)");
      }
      if num < radix {
          let num = num as u8;
          if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
      } else {
          None
      }
  }
  