556 lines
19 KiB
Rust
556 lines
19 KiB
Rust
use crate::error::Error;
|
|
use crate::error::ExpectedKind;
|
|
use crate::error::io_eof;
|
|
|
|
use crate::hex;
|
|
|
|
use crate::value::CompoundClass;
|
|
use crate::value::Domain;
|
|
use crate::value::DomainDecode;
|
|
use crate::value::Map;
|
|
use crate::value::NestedValue;
|
|
use crate::value::Reader;
|
|
use crate::value::Record;
|
|
use crate::value::Set;
|
|
use crate::value::Token;
|
|
use crate::value::Value;
|
|
use crate::value::boundary as B;
|
|
use crate::value::reader::ReaderResult;
|
|
use crate::value::source::BinarySource;
|
|
|
|
use lazy_static::lazy_static;
|
|
|
|
use num::bigint::BigInt;
|
|
|
|
use std::convert::TryInto;
|
|
use std::io;
|
|
use std::iter::FromIterator;
|
|
use std::marker::PhantomData;
|
|
|
|
pub struct TextReader<'de, 'src, S: BinarySource<'de>> {
|
|
pub source: &'src mut S,
|
|
phantom: PhantomData<&'de ()>,
|
|
}
|
|
|
|
impl<'de, 'src, S: BinarySource<'de>> TextReader<'de, 'src, S>
|
|
{
|
|
pub fn new(source: &'src mut S) -> Self {
|
|
TextReader {
|
|
source,
|
|
phantom: PhantomData,
|
|
}
|
|
}
|
|
|
|
fn syntax_error(&mut self, message: &str) -> io::Error {
|
|
self.source.syntax_error(message)
|
|
}
|
|
|
|
fn peek(&mut self) -> io::Result<Option<u8>> {
|
|
self.source.peek()
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn peek_noeof(&mut self) -> io::Result<u8> {
|
|
self.source.peek()?.ok_or_else(io_eof)
|
|
}
|
|
|
|
fn skip(&mut self) -> io::Result<()> {
|
|
self.source.skip()
|
|
}
|
|
|
|
fn next_byte(&mut self) -> io::Result<u8> {
|
|
let b = self.peek_noeof()?;
|
|
self.source.skip()?;
|
|
Ok(b)
|
|
}
|
|
|
|
fn skip_whitespace(&mut self) {
|
|
// Deliberately swallows errors.
|
|
while let Ok(Some(c)) = self.peek() {
|
|
match c {
|
|
b' ' | b'\t' | b'\r' | b'\n' | b',' => {
|
|
let _ = self.skip();
|
|
()
|
|
}
|
|
_ => break,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn gather_annotations<N: NestedValue, Dec: DomainDecode<N::Embedded>>(
|
|
&mut self,
|
|
decode_embedded: &mut Dec,
|
|
) -> ReaderResult<Vec<N>> {
|
|
let mut vs = Vec::new();
|
|
loop {
|
|
self.skip_whitespace();
|
|
match self.peek_noeof()? {
|
|
b';' => { self.skip()?; vs.push(N::new(self.comment_line()?)) }
|
|
b'@' => { self.skip()?; vs.push(self.demand_next_domain(true, decode_embedded)?) }
|
|
_ => return Ok(vs),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn skip_annotations(&mut self) -> ReaderResult<()> {
|
|
loop {
|
|
self.skip_whitespace();
|
|
match self.peek_noeof()? {
|
|
b';' => { self.skip()?; self.comment_line()?; },
|
|
b'@' => { self.skip()?; self.skip_value()?; },
|
|
_ => return Ok(()),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn decode_utf8(&mut self, bs: Vec<u8>) -> io::Result<String> {
|
|
String::from_utf8(bs).map_err(|_| self.syntax_error("Invalid UTF-8"))
|
|
}
|
|
|
|
fn comment_line(&mut self) -> io::Result<String> {
|
|
let mut bs = Vec::new();
|
|
loop {
|
|
let b = self.peek_noeof()?;
|
|
self.skip()?;
|
|
match b {
|
|
b'\r' | b'\n' => return Ok(self.decode_utf8(bs)?),
|
|
_ => bs.push(b),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn read_hex_float<N: NestedValue>(&mut self, bytecount: usize) -> io::Result<N> {
|
|
if self.next_byte()? != b'"' {
|
|
return Err(self.syntax_error("Missing open-double-quote in hex-encoded floating-point number"));
|
|
}
|
|
let bs = self.read_hex_binary()?;
|
|
if bs.len() != bytecount {
|
|
return Err(self.syntax_error("Incorrect number of bytes in hex-encoded floating-point number"));
|
|
}
|
|
match bytecount {
|
|
4 => Ok(Value::from(f32::from_bits(u32::from_be_bytes(bs.try_into().unwrap()))).wrap()),
|
|
8 => Ok(Value::from(f64::from_bits(u64::from_be_bytes(bs.try_into().unwrap()))).wrap()),
|
|
_ => Err(self.syntax_error("Unsupported byte count in hex-encoded floating-point number")),
|
|
}
|
|
}
|
|
|
|
fn read_stringlike<X, H, R>(
|
|
&mut self,
|
|
mut seed: R,
|
|
xform_item: X,
|
|
terminator: u8,
|
|
hexescape: u8,
|
|
hexescaper: H,
|
|
) -> io::Result<R>
|
|
where
|
|
X: Fn(&mut Self, &mut R, u8) -> io::Result<()>,
|
|
H: Fn(&mut Self, &mut R) -> io::Result<()>,
|
|
{
|
|
loop {
|
|
match self.next_byte()? {
|
|
c if c == terminator => return Ok(seed),
|
|
b'\\' => match self.next_byte()? {
|
|
c if c == hexescape => hexescaper(self, &mut seed)?,
|
|
c if c == terminator || c == b'\\' || c == b'/' => xform_item(self, &mut seed, c)?,
|
|
b'b' => xform_item(self, &mut seed, b'\x08')?,
|
|
b'f' => xform_item(self, &mut seed, b'\x0c')?,
|
|
b'n' => xform_item(self, &mut seed, b'\x0a')?,
|
|
b'r' => xform_item(self, &mut seed, b'\x0d')?,
|
|
b't' => xform_item(self, &mut seed, b'\x09')?,
|
|
_ => return Err(self.syntax_error("Invalid escape code")),
|
|
},
|
|
c => xform_item(self, &mut seed, c)?,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn hexnum(&mut self, count: usize) -> io::Result<u32> {
|
|
let mut v: u32 = 0;
|
|
for _ in 0 .. count {
|
|
let c = self.next_byte()?;
|
|
match (c as char).to_digit(16) {
|
|
Some(d) =>
|
|
v = v << 4 | d,
|
|
None =>
|
|
return Err(self.syntax_error("Bad hex escape")),
|
|
}
|
|
}
|
|
Ok(v)
|
|
}
|
|
|
|
fn append_codepoint(&mut self, bs: &mut Vec<u8>, n: u32) -> io::Result<()> {
|
|
let c = char::from_u32(n).ok_or_else(|| self.syntax_error("Bad code point"))?;
|
|
let mut buf = [0; 4];
|
|
let _ = c.encode_utf8(&mut buf);
|
|
bs.extend(&buf[0 .. c.len_utf8()]);
|
|
Ok(())
|
|
}
|
|
|
|
fn read_string(&mut self, delimiter: u8) -> io::Result<String> {
|
|
let raw = self.read_stringlike(
|
|
Vec::new(),
|
|
|_r, bs, c| Ok(bs.push(c)),
|
|
delimiter,
|
|
b'u',
|
|
|r, bs| {
|
|
let n1 = r.hexnum(4)?;
|
|
if (0xd800 ..= 0xdbff).contains(&n1) {
|
|
let mut ok = true;
|
|
ok = ok && r.next_byte()? == b'\\';
|
|
ok = ok && r.next_byte()? == b'u';
|
|
if !ok {
|
|
Err(r.syntax_error("Missing second half of surrogate pair"))
|
|
} else {
|
|
let n2 = r.hexnum(4)?;
|
|
if (0xdc00 ..= 0xdfff).contains(&n2) {
|
|
let n = ((n1 - 0xd800) << 10) + (n2 - 0xdc00) + 0x10000;
|
|
r.append_codepoint(bs, n)
|
|
} else {
|
|
Err(r.syntax_error("Bad second half of surrogate pair"))
|
|
}
|
|
}
|
|
} else {
|
|
r.append_codepoint(bs, n1)
|
|
}
|
|
})?;
|
|
self.decode_utf8(raw)
|
|
}
|
|
|
|
fn read_literal_binary<N: NestedValue>(&mut self) -> io::Result<N> {
|
|
Ok(N::new(&self.read_stringlike(
|
|
Vec::new(),
|
|
|_r, bs, b| Ok(bs.push(b)),
|
|
b'"',
|
|
b'x',
|
|
|r, bs| Ok(bs.push(r.hexnum(2)? as u8)))?[..]))
|
|
}
|
|
|
|
fn read_hex_binary(&mut self) -> io::Result<Vec<u8>> {
|
|
let mut s = String::new();
|
|
loop {
|
|
self.skip_whitespace();
|
|
let c1 = self.next_byte()? as char;
|
|
if c1 == '"' {
|
|
return Ok(hex::HexParser::Strict.decode(&s).unwrap());
|
|
}
|
|
let c2 = self.next_byte()? as char;
|
|
if !(c1.is_digit(16) && c2.is_digit(16)) {
|
|
return Err(self.syntax_error("Invalid hex binary"));
|
|
}
|
|
s.push(c1);
|
|
s.push(c2);
|
|
}
|
|
}
|
|
|
|
fn read_base64_binary<N: NestedValue>(&mut self) -> io::Result<N> {
|
|
let mut bs = Vec::new();
|
|
loop {
|
|
self.skip_whitespace();
|
|
let mut c = self.next_byte()?;
|
|
if c == b']' {
|
|
let bs = base64::decode_config(&self.decode_utf8(bs)?, base64::STANDARD_NO_PAD)
|
|
.map_err(|_| self.syntax_error("Invalid base64 character"))?;
|
|
return Ok(N::new(&bs[..]));
|
|
}
|
|
if c == b'-' { c = b'+'; }
|
|
if c == b'_' { c = b'/'; }
|
|
if c == b'=' { continue; }
|
|
bs.push(c);
|
|
}
|
|
}
|
|
|
|
fn upto<N: NestedValue, Dec: DomainDecode<N::Embedded>>(
|
|
&mut self,
|
|
delimiter: u8,
|
|
read_annotations: bool,
|
|
decode_embedded: &mut Dec,
|
|
) -> io::Result<Vec<N>> {
|
|
let mut vs = Vec::new();
|
|
loop {
|
|
self.skip_whitespace();
|
|
if self.peek()? == Some(delimiter) {
|
|
self.skip()?;
|
|
return Ok(vs);
|
|
}
|
|
vs.push(self.demand_next_domain(read_annotations, decode_embedded)?);
|
|
}
|
|
}
|
|
|
|
fn read_dictionary<N: NestedValue, Dec: DomainDecode<N::Embedded>>(
|
|
&mut self,
|
|
read_annotations: bool,
|
|
decode_embedded: &mut Dec,
|
|
) -> io::Result<N> {
|
|
let mut d = Map::new();
|
|
loop {
|
|
self.skip_whitespace();
|
|
if self.peek_noeof()? == b'}' {
|
|
self.skip()?;
|
|
return Ok(N::new(d));
|
|
}
|
|
let k = self.demand_next_domain(read_annotations, decode_embedded)?;
|
|
self.skip_whitespace();
|
|
if self.next_byte()? != b':' {
|
|
return Err(self.syntax_error("Missing expected key/value separator"));
|
|
}
|
|
let v = self.demand_next_domain(read_annotations, decode_embedded)?;
|
|
d.insert(k, v);
|
|
}
|
|
}
|
|
|
|
fn read_raw_symbol_or_number<N: NestedValue>(&mut self, mut bs: Vec<u8>) -> io::Result<N> {
|
|
lazy_static! {
|
|
static ref NUMBER_RE: regex::Regex = regex::Regex::new(
|
|
r"^([-+]?\d+)(((\.\d+([eE][-+]?\d+)?)|([eE][-+]?\d+))([fF]?))?$").unwrap();
|
|
}
|
|
loop {
|
|
let c = match self.peek()? {
|
|
None => b' ',
|
|
Some(c) if (c as char).is_whitespace() => b' ',
|
|
Some(c) => c
|
|
};
|
|
match c {
|
|
b'(' | b')' | b'{' | b'}' | b'[' | b']' | b'<' | b'>' |
|
|
b'"' | b';' | b',' | b'@' | b'#' | b':' | b'|' | b' ' => {
|
|
let s = self.decode_utf8(bs)?;
|
|
return match NUMBER_RE.captures(&s) {
|
|
None => Ok(N::symbol(&s)),
|
|
Some(m) => match m.get(2) {
|
|
None => Ok(N::new(s.parse::<BigInt>().map_err(
|
|
|_| self.syntax_error(&format!(
|
|
"Invalid signed-integer number: {:?}", s)))?)),
|
|
Some(_) => {
|
|
if let Some(maybe_f) = m.get(7) {
|
|
let s = m[1].to_owned() + &m[3];
|
|
if maybe_f.range().is_empty() {
|
|
Ok(N::new(s.parse::<f64>().map_err(
|
|
|_| self.syntax_error(&format!(
|
|
"Invalid double-precision number: {:?}", s)))?))
|
|
} else {
|
|
Ok(N::new(s.parse::<f32>().map_err(
|
|
|_| self.syntax_error(&format!(
|
|
"Invalid single-precision number: {:?}", s)))?))
|
|
}
|
|
} else {
|
|
panic!("Internal error: cannot analyze number {:?}", s)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
c => {
|
|
self.skip()?;
|
|
bs.push(c)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'de, 'src, S: BinarySource<'de>> Reader<'de> for TextReader<'de, 'src, S>
|
|
{
|
|
fn next_domain<N: NestedValue, Dec: DomainDecode<N::Embedded>>(
|
|
&mut self,
|
|
read_annotations: bool,
|
|
decode_embedded: &mut Dec,
|
|
) -> io::Result<Option<N>> {
|
|
self.skip_whitespace();
|
|
let c = match self.peek()? {
|
|
None => return Ok(None),
|
|
Some(c) => c,
|
|
};
|
|
Ok(Some(match c {
|
|
b'"' => {
|
|
self.skip()?;
|
|
N::new(self.read_string(b'"')?)
|
|
}
|
|
b'|' => {
|
|
self.skip()?;
|
|
N::symbol(&self.read_string(b'|')?)
|
|
}
|
|
b';' | b'@' => {
|
|
if read_annotations {
|
|
let mut annotations = self.gather_annotations(decode_embedded)?;
|
|
let av: N = self.demand_next_domain(read_annotations, decode_embedded)?;
|
|
let (existing_annotations, v) = av.pieces();
|
|
if let Some(vs) = existing_annotations {
|
|
annotations.extend_from_slice(&vs[..]);
|
|
}
|
|
N::wrap(Some(Box::new(annotations)), v)
|
|
} else {
|
|
self.skip_annotations()?;
|
|
self.demand_next_domain(read_annotations, decode_embedded)?
|
|
}
|
|
}
|
|
b':' => {
|
|
return Err(self.syntax_error("Unexpected key/value separator between items"));
|
|
}
|
|
b'#' => {
|
|
self.skip()?;
|
|
match self.next_byte()? {
|
|
b'f' => N::new(false),
|
|
b't' => N::new(true),
|
|
b'{' => N::new(Set::from_iter(self.upto(b'}', read_annotations, decode_embedded)?.into_iter())),
|
|
b'"' => self.read_literal_binary()?,
|
|
b'x' => match self.next_byte()? {
|
|
b'"' => N::new(&self.read_hex_binary()?[..]),
|
|
b'f' => self.read_hex_float(4)?,
|
|
b'd' => self.read_hex_float(8)?,
|
|
_ => return Err(self.syntax_error("Invalid #x syntax")),
|
|
},
|
|
b'[' => self.read_base64_binary()?,
|
|
b'!' => Value::Embedded(decode_embedded.decode_embedded(self, read_annotations)?).wrap(),
|
|
other => return Err(self.syntax_error(&format!("Invalid # syntax: {:?}", other))),
|
|
}
|
|
}
|
|
b'<' => {
|
|
self.skip()?;
|
|
let vs = self.upto(b'>', read_annotations, decode_embedded)?;
|
|
if vs.is_empty() {
|
|
return Err(self.syntax_error("Missing record label"));
|
|
}
|
|
Value::Record(Record(vs)).wrap()
|
|
}
|
|
b'[' => {
|
|
self.skip()?;
|
|
N::new(self.upto(b']', read_annotations, decode_embedded)?)
|
|
}
|
|
b'{' => {
|
|
self.skip()?;
|
|
self.read_dictionary(read_annotations, decode_embedded)?
|
|
}
|
|
b'>' => return Err(self.syntax_error("Unexpected >")),
|
|
b']' => return Err(self.syntax_error("Unexpected ]")),
|
|
b'}' => return Err(self.syntax_error("Unexpected }")),
|
|
other => {
|
|
self.skip()?;
|
|
self.read_raw_symbol_or_number(vec![other])?
|
|
}
|
|
}))
|
|
}
|
|
|
|
fn open_record(&mut self) -> ReaderResult<()> {
|
|
self.skip_annotations()?;
|
|
if self.peek()? != Some(b'<') { return Err(Error::Expected(ExpectedKind::Record)); }
|
|
self.skip()?;
|
|
Ok(())
|
|
}
|
|
|
|
fn open_sequence(&mut self) -> ReaderResult<()> {
|
|
self.skip_annotations()?;
|
|
if self.peek()? != Some(b'[') { return Err(Error::Expected(ExpectedKind::Sequence)); }
|
|
self.skip()?;
|
|
Ok(())
|
|
}
|
|
|
|
fn open_set(&mut self) -> ReaderResult<()> {
|
|
self.skip_annotations()?;
|
|
let mark = self.mark()?;
|
|
match self.next_byte()? {
|
|
b'#' => match self.next_byte()? {
|
|
b'{' => return Ok(()),
|
|
_ => (),
|
|
},
|
|
_ => (),
|
|
}
|
|
self.restore(&mark)?;
|
|
Err(Error::Expected(ExpectedKind::Set))
|
|
}
|
|
|
|
fn open_dictionary(&mut self) -> ReaderResult<()> {
|
|
self.skip_annotations()?;
|
|
if self.peek()? != Some(b'{') { return Err(Error::Expected(ExpectedKind::Dictionary)); }
|
|
self.skip()?;
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn boundary(&mut self, b: &B::Type) -> ReaderResult<()> {
|
|
match b {
|
|
B::Type {
|
|
closing: Some(B::Item::DictionaryKey),
|
|
opening: Some(B::Item::DictionaryValue),
|
|
} => {
|
|
self.skip_whitespace();
|
|
if self.next_byte()? != b':' {
|
|
Err(self.syntax_error("Missing expected key/value separator"))?;
|
|
}
|
|
},
|
|
_ => (),
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<bool> {
|
|
self.skip_whitespace();
|
|
match self.peek_noeof()? {
|
|
b'>' | b']' | b'}' => {
|
|
self.skip()?;
|
|
Ok(true)
|
|
}
|
|
_ => {
|
|
b.shift(Some(i.clone()));
|
|
self.boundary(b)?;
|
|
Ok(false)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn open_embedded(&mut self) -> ReaderResult<()> {
|
|
self.skip_annotations()?;
|
|
let mark = self.mark()?;
|
|
match self.next_byte()? {
|
|
b'#' => match self.next_byte()? {
|
|
b'!' => return Ok(()),
|
|
_ => (),
|
|
},
|
|
_ => (),
|
|
}
|
|
self.restore(&mark)?;
|
|
Err(Error::Expected(ExpectedKind::Embedded))
|
|
}
|
|
|
|
fn close_embedded(&mut self) -> ReaderResult<()> {
|
|
Ok(())
|
|
}
|
|
|
|
type Mark = S::Mark;
|
|
|
|
fn mark(&mut self) -> io::Result<Self::Mark> {
|
|
self.source.mark()
|
|
}
|
|
|
|
fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> {
|
|
self.source.restore(mark)
|
|
}
|
|
|
|
fn next_token<D: Domain, Dec: DomainDecode<D>>(
|
|
&mut self,
|
|
read_embedded_annotations: bool,
|
|
decode_embedded: &mut Dec,
|
|
) -> io::Result<Token<D>> {
|
|
self.skip_annotations()?;
|
|
let mark = self.mark()?;
|
|
Ok(match self.next_byte()? {
|
|
b'<' => Token::Compound(CompoundClass::Record),
|
|
b'[' => Token::Compound(CompoundClass::Sequence),
|
|
b'{' => Token::Compound(CompoundClass::Dictionary),
|
|
b'>' => Token::End,
|
|
b']' => Token::End,
|
|
b'}' => Token::End,
|
|
b'#' => match self.next_byte()? {
|
|
b'!' => Token::Embedded(decode_embedded.decode_embedded(self, read_embedded_annotations)?),
|
|
b'{' => Token::Compound(CompoundClass::Set),
|
|
_ => {
|
|
self.restore(&mark)?;
|
|
Token::Atom(self.demand_next_domain(false, decode_embedded)?)
|
|
}
|
|
},
|
|
_ => {
|
|
self.restore(&mark)?;
|
|
Token::Atom(self.demand_next_domain(false, decode_embedded)?)
|
|
}
|
|
})
|
|
}
|
|
}
|