diff options
author | Nadrieril | 2019-08-04 14:07:34 +0200 |
---|---|---|
committer | Nadrieril | 2019-08-06 21:40:24 +0200 |
commit | e52f50080d8e0e6d6a05b1045e3e0e840acb50d0 (patch) | |
tree | 711de34ac82aef0aa84113ad5577614aefb4640f /dhall_syntax | |
parent | 696efe66336a268054c475fab9fe6505bdfc7b60 (diff) |
Braced escape sequences
Diffstat (limited to '')
-rw-r--r-- | dhall_syntax/src/parser.rs | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index db1699b..2450c76 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -402,11 +402,31 @@ make_parser! { "n" => "\n".to_owned(), "r" => "\r".to_owned(), "t" => "\t".to_owned(), + // "uXXXX" or "u{XXXXX}" _ => { - // "uXXXX" - use std::convert::TryFrom; - let c = u16::from_str_radix(&s[1..5], 16).unwrap(); - let c = char::try_from(u32::from(c)).unwrap(); + use std::convert::{TryFrom, TryInto}; + + let s = &s[1..]; + let s = if &s[0..1] == "{" { + &s[1..s.len()-1] + } else { + &s[0..s.len()] + }; + + if s.len() > 8 { + Err(format!("Escape sequences can't have more than 8 chars: \"{}\"", s))? + } + + // pad with zeroes + let s: String = std::iter::repeat('0') + .take(8 - s.len()) + .chain(s.chars()) + .collect(); + + // `s` has length 8, so `bytes` has length 4 + let bytes: &[u8] = &hex::decode(s).unwrap(); + let c = u32::from_be_bytes(bytes.try_into().unwrap()); + let c = char::try_from(c).unwrap(); std::iter::once(c).collect() } } |