summaryrefslogtreecommitdiff
path: root/dhall_syntax
diff options
context:
space:
mode:
authorNadrieril2019-08-04 14:07:34 +0200
committerNadrieril2019-08-06 21:40:24 +0200
commite52f50080d8e0e6d6a05b1045e3e0e840acb50d0 (patch)
tree711de34ac82aef0aa84113ad5577614aefb4640f /dhall_syntax
parent696efe66336a268054c475fab9fe6505bdfc7b60 (diff)
Braced escape sequences
Diffstat (limited to '')
-rw-r--r--dhall_syntax/src/parser.rs28
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()
}
}