diff --git a/src/de/mod.rs b/src/de/mod.rs index 6585a589..b10f12c0 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -1,7 +1,5 @@ //! Generic deserialization framework. -use std::str; - pub mod impls; pub mod value; @@ -204,10 +202,9 @@ pub trait Visitor { fn visit_char(&mut self, v: char) -> Result where E: Error, { - // The unwraps in here should be safe. - let mut s = &mut [0; 4]; - let len = v.encode_utf8(s).unwrap(); - self.visit_str(str::from_utf8(&s[..len]).unwrap()) + // FIXME: this allocation is required in order to be compatible with stable rust, which + // doesn't support encoding a `char` into a stack buffer. + self.visit_string(v.to_string()) } fn visit_str(&mut self, _v: &str) -> Result diff --git a/src/json/de.rs b/src/json/de.rs index c966e668..f1653d33 100644 --- a/src/json/de.rs +++ b/src/json/de.rs @@ -2,8 +2,6 @@ use std::char; use std::io; use std::str; -use unicode::str::Utf16Item; - use de; use super::error::{Error, ErrorCode}; @@ -345,35 +343,44 @@ impl Deserializer // Non-BMP characters are encoded as a sequence of // two hex escapes, representing UTF-16 surrogates. n1 @ 0xD800 ... 0xDBFF => { - let c1 = try!(self.next_char()); - let c2 = try!(self.next_char()); - match (c1, c2) { + match (try!(self.next_char()), try!(self.next_char())) { (Some(b'\\'), Some(b'u')) => (), _ => { return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape)); } } - let buf = &[n1, try!(self.decode_hex_escape())]; - match ::unicode::str::utf16_items(buf).next() { - Some(Utf16Item::ScalarValue(c)) => c, - _ => { - return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape)); + let n2 = try!(self.decode_hex_escape()); + + if n2 < 0xDC00 || n2 > 0xDFFF { + return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape)); + } + + let n = (((n1 - 0xD800) as u32) << 10 | + (n2 - 0xDC00) as u32) + 0x1_0000; + + match char::from_u32(n as u32) { + Some(c) => c, + None => { + return Err(self.error(ErrorCode::InvalidUnicodeCodePoint)); } } } - n => match char::from_u32(n as u32) { - Some(c) => c, - None => { - return Err(self.error(ErrorCode::InvalidUnicodeCodePoint)); + n => { + match char::from_u32(n as u32) { + Some(c) => c, + None => { + return Err(self.error(ErrorCode::InvalidUnicodeCodePoint)); + } } } }; - let buf = &mut [0; 4]; - let len = c.encode_utf8(buf).unwrap_or(0); - self.str_buf.extend(buf[..len].iter().map(|b| *b)); + // FIXME: this allocation is required in order to be compatible with stable + // rust, which doesn't support encoding a `char` into a stack buffer. + let buf = c.to_string(); + self.str_buf.extend(buf.bytes()); } _ => { return Err(self.error(ErrorCode::InvalidEscape)); diff --git a/src/json/ser.rs b/src/json/ser.rs index 85133a6c..54c57726 100644 --- a/src/json/ser.rs +++ b/src/json/ser.rs @@ -386,9 +386,9 @@ pub fn escape_str(wr: &mut W, value: &str) -> io::Result<()> fn escape_char(wr: &mut W, value: char) -> io::Result<()> where W: io::Write { - let buf = &mut [0; 4]; - value.encode_utf8(buf); - escape_bytes(wr, buf) + // FIXME: this allocation is required in order to be compatible with stable + // rust, which doesn't support encoding a `char` into a stack buffer. + escape_bytes(wr, value.to_string().as_bytes()) } fn fmt_f32_or_null(wr: &mut W, value: f32) -> io::Result<()> diff --git a/src/lib.rs b/src/lib.rs index 6abdd4e8..f5de433c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,9 +6,8 @@ //! leaving serde to perform roughly the same speed as a hand written serializer for a specific //! type. -#![feature(collections, core, std_misc, unicode)] +#![feature(collections, core, std_misc)] -extern crate unicode; pub use ser::{Serialize, Serializer}; pub use de::{Deserialize, Deserializer, Error}; diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 88ad6af4..5c317398 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -1,7 +1,5 @@ //! Generic serialization framework. -use std::str; - pub mod impls; /////////////////////////////////////////////////////////////////////////////// @@ -97,10 +95,9 @@ pub trait Serializer { /// single character. #[inline] fn visit_char(&mut self, v: char) -> Result<(), Self::Error> { - // The unwraps in here should be safe. - let mut s = &mut [0; 4]; - let len = v.encode_utf8(s).unwrap(); - self.visit_str(str::from_utf8(&s[..len]).unwrap()) + // FIXME: this allocation is required in order to be compatible with stable rust, which + // doesn't support encoding a `char` into a stack buffer. + self.visit_str(&v.to_string()) } /// `visit_str` serializes a `&str`.