From fd9d7aa2cf76c949633cb4156642654238c03921 Mon Sep 17 00:00:00 2001 From: tinaun Date: Sat, 27 May 2017 18:12:16 -0400 Subject: [PATCH] added `FromStr` Impl for `char` --- .../library-features/char-error-internals.md | 5 ++ src/libcore/char.rs | 59 ++++++++++++++++++- src/libcore/tests/char.rs | 11 ++++ src/libstd/error.rs | 8 +++ src/libstd/lib.rs | 1 + src/libstd_unicode/char.rs | 2 + 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/library-features/char-error-internals.md diff --git a/src/doc/unstable-book/src/library-features/char-error-internals.md b/src/doc/unstable-book/src/library-features/char-error-internals.md new file mode 100644 index 00000000000..8013b4988e1 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/char-error-internals.md @@ -0,0 +1,5 @@ +# `char_error_internals` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 98268e3813f..44f5fdbf431 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -19,7 +19,7 @@ use char_private::is_printable; use convert::TryFrom; use fmt::{self, Write}; use slice; -use str::from_utf8_unchecked_mut; +use str::{from_utf8_unchecked_mut, FromStr}; use iter::FusedIterator; use mem::transmute; @@ -208,6 +208,63 @@ impl From for char { } } + +/// An error which can be returned when parsing a char. +#[stable(feature = "char_from_str", since = "1.19.0")] +#[derive(Clone, Debug)] +pub struct ParseCharError { + kind: CharErrorKind, +} + +impl ParseCharError { + #[unstable(feature = "char_error_internals", + reason = "this method should not be available publicly", + issue = "0")] + #[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.19.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.19.0")] +impl FromStr for char { + type Err = ParseCharError; + + #[inline] + fn from_str(s: &str) -> Result { + 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 }) + } + } + } +} + + #[unstable(feature = "try_from", issue = "33417")] impl TryFrom for char { type Error = CharTryFromError; diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index e4012ec91e2..7c3b90c8153 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -10,6 +10,7 @@ use std::{char,str}; use std::convert::TryFrom; +use std::str::FromStr; #[test] fn test_convert() { @@ -28,6 +29,16 @@ fn test_convert() { assert!(char::try_from(0xFFFF_FFFF_u32).is_err()); } +#[test] +fn test_from_str() { + assert_eq!(char::from_str("a").unwrap(), 'a'); + assert_eq!(char::try_from("a").unwrap(), 'a'); + assert_eq!(char::from_str("\0").unwrap(), '\0'); + assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}'); + assert!(char::from_str("").is_err()); + assert!(char::from_str("abc").is_err()); +} + #[test] fn test_is_lowercase() { assert!('a'.is_lowercase()); diff --git a/src/libstd/error.rs b/src/libstd/error.rs index f56e3a5d780..47f96cabe15 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -321,6 +321,14 @@ impl Error for char::CharTryFromError { } } +#[stable(feature = "char_from_str", since = "1.19.0")] +impl Error for char::ParseCharError { + fn description(&self) -> &str { + self.__description() + } +} + + // copied from any.rs impl Error + 'static { /// Returns true if the boxed type is the same as `T` diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b0820d6f05a..4e825a69321 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -253,6 +253,7 @@ #![feature(cfg_target_thread_local)] #![feature(cfg_target_vendor)] #![feature(char_escape_debug)] +#![feature(char_error_internals)] #![feature(char_internals)] #![feature(collections)] #![feature(collections_range)] diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 92e5369758b..7476de162da 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -38,6 +38,8 @@ use tables::{conversions, derived_property, general_category, property}; pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode}; +#[stable(feature = "char_from_str", since = "1.19.0")] +pub use core::char::ParseCharError; // unstable reexports #[unstable(feature = "try_from", issue = "33417")]