Skip to content

Commit f040208

Browse files
committed
Implement TryFrom<u32> for char
For symmetry with From<char> for u32.
1 parent 41d0a89 commit f040208

File tree

5 files changed

+49
-6
lines changed

5 files changed

+49
-6
lines changed

src/libcore/char.rs

+29-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#![stable(feature = "core_char", since = "1.2.0")]
1717

1818
use char_private::is_printable;
19+
use convert::TryFrom;
20+
use fmt;
1921
use iter::FusedIterator;
2022
use mem::transmute;
2123

@@ -122,12 +124,7 @@ pub const MAX: char = '\u{10ffff}';
122124
#[inline]
123125
#[stable(feature = "rust1", since = "1.0.0")]
124126
pub fn from_u32(i: u32) -> Option<char> {
125-
// catch out-of-bounds and surrogates
126-
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
127-
None
128-
} else {
129-
Some(unsafe { from_u32_unchecked(i) })
130-
}
127+
char::try_from(i).ok()
131128
}
132129

133130
/// Converts a `u32` to a `char`, ignoring validity.
@@ -209,6 +206,32 @@ impl From<u8> for char {
209206
}
210207
}
211208

209+
#[unstable(feature = "try_from", issue = "33417")]
210+
impl TryFrom<u32> for char {
211+
type Err = CharTryFromError;
212+
213+
#[inline]
214+
fn try_from(i: u32) -> Result<Self, Self::Err> {
215+
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
216+
Err(CharTryFromError(()))
217+
} else {
218+
Ok(unsafe { from_u32_unchecked(i) })
219+
}
220+
}
221+
}
222+
223+
/// The error type returned when a conversion from u32 to char fails.
224+
#[unstable(feature = "try_from", issue = "33417")]
225+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
226+
pub struct CharTryFromError(());
227+
228+
#[unstable(feature = "try_from", issue = "33417")]
229+
impl fmt::Display for CharTryFromError {
230+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231+
"converted integer out of range for `char`".fmt(f)
232+
}
233+
}
234+
212235
/// Converts a digit in the given radix to a `char`.
213236
///
214237
/// A 'radix' here is sometimes also called a 'base'. A radix of two

src/libcoretest/char.rs

+10
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,23 @@
99
// except according to those terms.
1010

1111
use std::char;
12+
use std::convert::TryFrom;
1213

1314
#[test]
1415
fn test_convert() {
1516
assert_eq!(u32::from('a'), 0x61);
1617
assert_eq!(char::from(b'\0'), '\0');
1718
assert_eq!(char::from(b'a'), 'a');
1819
assert_eq!(char::from(b'\xFF'), '\u{FF}');
20+
assert_eq!(char::try_from(0_u32), Ok('\0'));
21+
assert_eq!(char::try_from(0x61_u32), Ok('a'));
22+
assert_eq!(char::try_from(0xD7FF_u32), Ok('\u{D7FF}'));
23+
assert!(char::try_from(0xD800_u32).is_err());
24+
assert!(char::try_from(0xDFFF_u32).is_err());
25+
assert_eq!(char::try_from(0xE000_u32), Ok('\u{E000}'));
26+
assert_eq!(char::try_from(0x10FFFF_u32), Ok('\u{10FFFF}'));
27+
assert!(char::try_from(0x110000_u32).is_err());
28+
assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
1929
}
2030

2131
#[test]

src/librustc_unicode/char.rs

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
4040
pub use core::char::{EncodeUtf16, EncodeUtf8, EscapeDebug, EscapeDefault, EscapeUnicode};
4141

4242
// unstable reexports
43+
#[unstable(feature = "try_from", issue = "33417")]
44+
pub use core::char::CharTryFromError;
4345
#[unstable(feature = "decode_utf8", issue = "33906")]
4446
pub use core::char::{DecodeUtf8, decode_utf8};
4547
#[unstable(feature = "unicode", issue = "27783")]

src/librustc_unicode/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#![feature(fused)]
3939
#![feature(lang_items)]
4040
#![feature(staged_api)]
41+
#![feature(try_from)]
4142
#![feature(unicode)]
4243

4344
mod tables;

src/libstd/error.rs

+7
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,13 @@ impl<'a, T: ?Sized + Reflect> Error for cell::BorrowMutError<'a, T> {
302302
}
303303
}
304304

305+
#[unstable(feature = "try_from", issue = "33417")]
306+
impl Error for char::CharTryFromError {
307+
fn description(&self) -> &str {
308+
"converted integer out of range for `char`"
309+
}
310+
}
311+
305312
// copied from any.rs
306313
impl Error + 'static {
307314
/// Returns true if the boxed type is the same as `T`

0 commit comments

Comments
 (0)