TextReader/TextWriter
This commit is contained in:
parent
9b100ab9aa
commit
9d4e6998f2
|
@ -12,7 +12,9 @@ license = "Apache-2.0"
|
|||
gitlab = { repository = "preserves/preserves" }
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13"
|
||||
num = "0.2"
|
||||
regex = "1.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_bytes = "0.11"
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ use std::borrow::Cow;
|
|||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use super::value::{IOValue, IOValueDomainCodec, PackedReader};
|
||||
use super::value::boundary as B;
|
||||
use super::value::{IOValue, IOValueDomainCodec, PackedReader, TextReader, ViaCodec};
|
||||
use super::value::reader::{Reader, IOBinarySource, BytesBinarySource};
|
||||
|
||||
pub use super::error::Error;
|
||||
|
@ -25,6 +26,10 @@ where
|
|||
from_reader(&mut PackedReader::new(&mut BytesBinarySource::new(bytes), IOValueDomainCodec))
|
||||
}
|
||||
|
||||
pub fn from_text<'de, T>(text: &str) -> Result<T> where T: Deserialize<'de> {
|
||||
from_reader(&mut TextReader::new(text, ViaCodec::new(IOValueDomainCodec)))
|
||||
}
|
||||
|
||||
pub fn from_read<'de, 'r, IOR: io::Read + io::Seek, T>(read: &'r mut IOR) ->
|
||||
Result<T>
|
||||
where
|
||||
|
@ -147,31 +152,30 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
let is_some = self.read.open_option()?;
|
||||
let result = if is_some {
|
||||
self.read.ensure_more_expected()?;
|
||||
visitor.visit_some(&mut *self)?
|
||||
if let Some(mut b) = self.read.open_option()? {
|
||||
self.read.ensure_more_expected(&mut b, &B::Item::RecordField)?;
|
||||
let result = visitor.visit_some(&mut *self)?;
|
||||
self.read.ensure_complete(b, &B::Item::RecordField)?;
|
||||
Ok(result)
|
||||
} else {
|
||||
visitor.visit_none::<Error>()?
|
||||
};
|
||||
self.read.ensure_complete()?;
|
||||
Ok(result)
|
||||
Ok(visitor.visit_none::<Error>()?)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
self.read.open_simple_record("tuple", Some(0))?;
|
||||
let b = self.read.open_simple_record("tuple", Some(0))?;
|
||||
let result = visitor.visit_unit::<Error>()?;
|
||||
self.read.ensure_complete()?;
|
||||
self.read.ensure_complete(b, &B::Item::RecordField)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V)
|
||||
-> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
self.read.open_simple_record(name, Some(0))?;
|
||||
let b = self.read.open_simple_record(name, Some(0))?;
|
||||
let result = visitor.visit_unit::<Error>()?;
|
||||
self.read.ensure_complete()?;
|
||||
self.read.ensure_complete(b, &B::Item::RecordField)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
|
@ -179,14 +183,14 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
-> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
match super::value::magic::transmit_input_value(
|
||||
name, || Ok(self.read.demand_next(false)?))?
|
||||
name, || Ok(self.read.demand_next(true)?))?
|
||||
{
|
||||
Some(v) => visitor.visit_u64(v),
|
||||
None => {
|
||||
self.read.open_simple_record(name, Some(1))?;
|
||||
self.read.ensure_more_expected()?;
|
||||
let mut b = self.read.open_simple_record(name, Some(1))?;
|
||||
self.read.ensure_more_expected(&mut b, &B::Item::RecordField)?;
|
||||
let result = visitor.visit_newtype_struct(&mut *self)?;
|
||||
self.read.ensure_complete()?;
|
||||
self.read.ensure_complete(b, &B::Item::RecordField)?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
@ -195,14 +199,14 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value> where V: Visitor<'de> {
|
||||
// Hack around serde's model: Deserialize *sets* as sequences,
|
||||
// too, and reconstruct them as Rust Sets on the visitor side.
|
||||
self.read.open_sequence_or_set()?;
|
||||
visitor.visit_seq(Seq::new(self))
|
||||
let i = self.read.open_sequence_or_set()?;
|
||||
visitor.visit_seq(Seq::new(self, B::Type::default(), i))
|
||||
}
|
||||
|
||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
self.read.open_simple_record("tuple", Some(len))?;
|
||||
let mut seq = Seq::new(self);
|
||||
let b = self.read.open_simple_record("tuple", Some(len))?;
|
||||
let mut seq = Seq::new(self, b, B::Item::RecordField);
|
||||
let result = visitor.visit_seq(&mut seq)?;
|
||||
seq.skip_remainder()?;
|
||||
Ok(result)
|
||||
|
@ -211,8 +215,8 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
fn deserialize_tuple_struct<V>(self, name: &'static str, len: usize, visitor: V)
|
||||
-> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
self.read.open_simple_record(name, Some(len))?;
|
||||
let mut seq = Seq::new(self);
|
||||
let b = self.read.open_simple_record(name, Some(len))?;
|
||||
let mut seq = Seq::new(self, b, B::Item::RecordField);
|
||||
let result = visitor.visit_seq(&mut seq)?;
|
||||
seq.skip_remainder()?;
|
||||
Ok(result)
|
||||
|
@ -220,7 +224,7 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
|
||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value> where V: Visitor<'de> {
|
||||
self.read.open_dictionary()?;
|
||||
let mut seq = Seq::new(self);
|
||||
let mut seq = Seq::new(self, B::Type::default(), B::Item::DictionaryKey);
|
||||
let result = visitor.visit_map(&mut seq)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -231,8 +235,8 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
visitor: V)
|
||||
-> Result<V::Value> where V: Visitor<'de>
|
||||
{
|
||||
self.read.open_simple_record(name, Some(fields.len()))?;
|
||||
let mut seq = Seq::new(self);
|
||||
let b = self.read.open_simple_record(name, Some(fields.len()))?;
|
||||
let mut seq = Seq::new(self, b, B::Item::RecordField);
|
||||
let result = visitor.visit_seq(&mut seq)?;
|
||||
seq.skip_remainder()?;
|
||||
Ok(result)
|
||||
|
@ -262,22 +266,27 @@ impl<'r, 'de, 'a, R: Reader<'de, IOValue, IOValue>> serde::de::Deserializer<'de>
|
|||
}
|
||||
|
||||
pub struct Seq<'de, 'r, 'a, R: Reader<'de, IOValue, IOValue>> {
|
||||
b: B::Type,
|
||||
i: B::Item,
|
||||
de: &'a mut Deserializer<'de, 'r, R>,
|
||||
}
|
||||
|
||||
impl<'de, 'r, 'a, R: Reader<'de, IOValue, IOValue>> Seq<'de, 'r, 'a, R> {
|
||||
fn new(de: &'a mut Deserializer<'de, 'r, R>) -> Self {
|
||||
Seq { de }
|
||||
fn new(de: &'a mut Deserializer<'de, 'r, R>, b: B::Type, i: B::Item) -> Self {
|
||||
Seq { b, i, de }
|
||||
}
|
||||
|
||||
fn skip_remainder(&mut self) -> Result<()> {
|
||||
self.de.read.skip_remainder()
|
||||
while !self.de.read.close_compound(&mut self.b, &self.i)? {
|
||||
self.de.read.skip_value()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_item<T>(&mut self, seed: T) ->
|
||||
Result<Option<T::Value>> where T: DeserializeSeed<'de>
|
||||
{
|
||||
match self.de.read.close_compound()? {
|
||||
match self.de.read.close_compound(&mut self.b, &self.i)? {
|
||||
true => Ok(None),
|
||||
false => Ok(Some(seed.deserialize(&mut *self.de)?)),
|
||||
}
|
||||
|
@ -290,7 +299,7 @@ impl<'de, 'r, 'a, R: Reader<'de, IOValue, IOValue>> SeqAccess<'de> for Seq<'de,
|
|||
fn next_element_seed<T>(&mut self, seed: T) ->
|
||||
Result<Option<T::Value>> where T: DeserializeSeed<'de>
|
||||
{
|
||||
self.next_item(seed)
|
||||
Ok(self.next_item(seed)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,12 +309,14 @@ impl<'de, 'r, 'a, R: Reader<'de, IOValue, IOValue>> MapAccess<'de> for Seq<'de,
|
|||
fn next_key_seed<K>(&mut self, seed: K) ->
|
||||
Result<Option<K::Value>> where K: DeserializeSeed<'de>
|
||||
{
|
||||
self.i = B::Item::DictionaryKey;
|
||||
self.next_item(seed)
|
||||
}
|
||||
|
||||
fn next_value_seed<V>(&mut self, seed: V) ->
|
||||
Result<V::Value> where V: DeserializeSeed<'de>
|
||||
{
|
||||
self.i = B::Item::DictionaryValue;
|
||||
match self.next_item(seed)? {
|
||||
Some(item) => Ok(item),
|
||||
None => Err(Error::MissingItem),
|
||||
|
@ -320,9 +331,9 @@ impl<'de, 'r, 'a, R: Reader<'de, IOValue, IOValue>> EnumAccess<'de> for &'a mut
|
|||
fn variant_seed<V>(self, seed: V)
|
||||
-> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>
|
||||
{
|
||||
self.read.open_record(None)?;
|
||||
let b = self.read.open_record(None)?;
|
||||
let variant = seed.deserialize(&mut *self)?;
|
||||
Ok((variant, Seq::new(self)))
|
||||
Ok((variant, Seq::new(self, b, B::Item::RecordField)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,20 +10,7 @@ pub enum HexFormatter {
|
|||
}
|
||||
|
||||
pub fn hexdigit(v: u8) -> char {
|
||||
(if v < 10 {('0' as u8) + v} else {('a' as u8) + v - 10}) as char
|
||||
}
|
||||
|
||||
pub fn unhex(c: char) -> Option<u8> {
|
||||
if c >= '0' && c <= '9' {
|
||||
return Some((c as u8) - ('0' as u8));
|
||||
}
|
||||
if c >= 'a' && c <= 'f' {
|
||||
return Some((c as u8) - ('a' as u8) + 10);
|
||||
}
|
||||
if c >= 'A' && c <= 'F' {
|
||||
return Some((c as u8) - ('A' as u8) + 10);
|
||||
}
|
||||
None
|
||||
char::from_digit(v as u32, 16).expect("hexadecimal digit value")
|
||||
}
|
||||
|
||||
impl HexParser {
|
||||
|
@ -32,7 +19,7 @@ impl HexParser {
|
|||
let mut buf: u8 = 0;
|
||||
let mut buf_full = false;
|
||||
for c in s.chars() {
|
||||
match unhex(c) {
|
||||
match c.to_digit(16) {
|
||||
None =>
|
||||
match self {
|
||||
HexParser::Liberal => (),
|
||||
|
@ -41,10 +28,10 @@ impl HexParser {
|
|||
},
|
||||
Some(nibble) =>
|
||||
if buf_full {
|
||||
result.push(buf << 4 | nibble);
|
||||
result.push(buf << 4 | (nibble as u8));
|
||||
buf_full = false;
|
||||
} else {
|
||||
buf = nibble;
|
||||
buf = nibble as u8;
|
||||
buf_full = true;
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use serde::Serialize;
|
||||
use super::value::IOValueDomainCodec;
|
||||
use super::value::boundary as B;
|
||||
use super::value::writer::{Writer, CompoundWriter};
|
||||
|
||||
pub use super::error::Error;
|
||||
|
@ -16,16 +17,22 @@ impl<'w, W: Writer> Serializer<'w, W> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SerializeCompound<'a, 'w, W: Writer> {
|
||||
ser: &'a mut Serializer<'w, W>,
|
||||
c: W::SeqWriter,
|
||||
enum SequenceVariant<W: Writer> {
|
||||
Sequence(W::SeqWriter),
|
||||
Record(W::RecWriter),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SerializeDictionary<'a, 'w, W: Writer> {
|
||||
pub struct SerializeCompound<'a, 'w, W: Writer> {
|
||||
b: B::Type,
|
||||
i: B::Item,
|
||||
ser: &'a mut Serializer<'w, W>,
|
||||
d: W::SetWriter,
|
||||
c: SequenceVariant<W>,
|
||||
}
|
||||
|
||||
pub struct SerializeDictionary<'a, 'w, W: Writer> {
|
||||
b: B::Type,
|
||||
ser: &'a mut Serializer<'w, W>,
|
||||
d: W::DictWriter,
|
||||
}
|
||||
|
||||
impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
||||
|
@ -85,13 +92,12 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
|
||||
fn serialize_char(self, v: char) -> Result<Self::Ok> {
|
||||
let mut c = self.write.start_record(Some(1))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol("UnicodeScalar")?;
|
||||
c.delimit()?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?;
|
||||
c.write_u32(v as u32)?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordField))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
|
||||
|
@ -104,37 +110,36 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
|
||||
fn serialize_none(self) -> Result<Self::Ok> {
|
||||
let mut c = self.write.start_record(Some(0))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol("None")?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordLabel))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok> where T: Serialize {
|
||||
let mut c = self.write.start_record(Some(1))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol("Some")?;
|
||||
c.delimit()?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?;
|
||||
to_writer(&mut c, v)?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordField))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok> {
|
||||
let mut c = self.write.start_record(Some(0))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol("tuple")?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordLabel))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
|
||||
let mut c = self.write.start_record(Some(0))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(name)?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordLabel))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
|
@ -144,10 +149,10 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
Result<Self::Ok>
|
||||
{
|
||||
let mut c = self.write.start_record(Some(0))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(variant_name)?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordLabel))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) ->
|
||||
|
@ -158,13 +163,12 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
None => {
|
||||
// TODO: This is apparently discouraged, and we should apparently just serialize `value`?
|
||||
let mut c = self.write.start_record(Some(1))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(name)?;
|
||||
c.delimit()?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?;
|
||||
to_writer(&mut c, value)?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordField))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,36 +181,33 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
Result<Self::Ok> where T: Serialize
|
||||
{
|
||||
let mut c = self.write.start_record(Some(1))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(variant_name)?;
|
||||
c.delimit()?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?;
|
||||
to_writer(&mut c, value)?;
|
||||
c.delimit()?;
|
||||
Ok(self.write.end_seq(c)?)
|
||||
c.boundary(&B::end(B::Item::RecordField))?;
|
||||
Ok(self.write.end_record(c)?)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, count: Option<usize>) -> Result<Self::SerializeSeq> {
|
||||
let c = self.write.start_sequence(count)?;
|
||||
Ok(SerializeCompound { ser: self, c })
|
||||
Ok(SerializeCompound::seq(self, c))
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, count: usize) -> Result<Self::SerializeTuple> {
|
||||
let mut c = self.write.start_record(Some(count))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol("tuple")?;
|
||||
c.delimit()?;
|
||||
Ok(SerializeCompound { ser: self, c })
|
||||
Ok(SerializeCompound::rec(self, c))
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, name: &'static str, count: usize) ->
|
||||
Result<Self::SerializeTupleStruct>
|
||||
{
|
||||
let mut c = self.write.start_record(Some(count))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(name)?;
|
||||
c.delimit()?;
|
||||
Ok(SerializeCompound { ser: self, c })
|
||||
Ok(SerializeCompound::rec(self, c))
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
|
@ -217,23 +218,21 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
Result<Self::SerializeTupleVariant>
|
||||
{
|
||||
let mut c = self.write.start_record(Some(count))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(variant_name)?;
|
||||
c.delimit()?;
|
||||
Ok(SerializeCompound { ser: self, c })
|
||||
Ok(SerializeCompound::rec(self, c))
|
||||
}
|
||||
|
||||
fn serialize_map(self, count: Option<usize>) -> Result<Self::SerializeMap> {
|
||||
let d = self.write.start_dictionary(count)?;
|
||||
Ok(SerializeDictionary { ser: self, d })
|
||||
Ok(SerializeDictionary { b: B::Type::default(), ser: self, d })
|
||||
}
|
||||
|
||||
fn serialize_struct(self, name: &'static str, count: usize) -> Result<Self::SerializeStruct> {
|
||||
let mut c = self.write.start_record(Some(count))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(name)?;
|
||||
c.delimit()?;
|
||||
Ok(SerializeCompound { ser: self, c })
|
||||
Ok(SerializeCompound::rec(self, c))
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
|
@ -244,10 +243,9 @@ impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> {
|
|||
Result<Self::SerializeStructVariant>
|
||||
{
|
||||
let mut c = self.write.start_record(Some(count))?;
|
||||
c.extend()?;
|
||||
c.boundary(&B::start(B::Item::RecordLabel))?;
|
||||
c.write_symbol(variant_name)?;
|
||||
c.delimit()?;
|
||||
Ok(SerializeCompound { ser: self, c })
|
||||
Ok(SerializeCompound::rec(self, c))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,32 +254,69 @@ impl<'a, 'w, W: Writer> serde::ser::SerializeMap for SerializeDictionary<'a, 'w,
|
|||
type Error = Error;
|
||||
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<()> where T: Serialize {
|
||||
self.d.extend()?;
|
||||
self.b.opening = Some(B::Item::DictionaryKey);
|
||||
self.d.boundary(&self.b)?;
|
||||
to_writer(&mut self.d, key)?;
|
||||
self.b.shift(None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: Serialize {
|
||||
self.b.opening = Some(B::Item::DictionaryValue);
|
||||
self.d.boundary(&self.b)?;
|
||||
to_writer(&mut self.d, value)?;
|
||||
Ok(self.d.delimit()?)
|
||||
self.b.shift(None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok> {
|
||||
Ok(self.ser.write.end_set(self.d)?)
|
||||
fn end(mut self) -> Result<Self::Ok> {
|
||||
self.d.boundary(&self.b)?;
|
||||
Ok(self.ser.write.end_dictionary(self.d)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'w, W: Writer> SerializeCompound<'a, 'w, W> {
|
||||
fn seq(ser: &'a mut Serializer<'w, W>, c: W::SeqWriter) -> Self {
|
||||
SerializeCompound {
|
||||
b: B::Type::default(),
|
||||
i: B::Item::SequenceValue,
|
||||
ser,
|
||||
c: SequenceVariant::Sequence(c),
|
||||
}
|
||||
}
|
||||
|
||||
fn rec(ser: &'a mut Serializer<'w, W>, c: W::RecWriter) -> Self {
|
||||
SerializeCompound {
|
||||
b: B::end(B::Item::RecordLabel),
|
||||
i: B::Item::RecordField,
|
||||
ser,
|
||||
c: SequenceVariant::Record(c),
|
||||
}
|
||||
}
|
||||
|
||||
fn extend<T: ?Sized>(&mut self, value: &T) -> Result<()>
|
||||
where T: Serialize
|
||||
{
|
||||
self.c.extend()?;
|
||||
to_writer(&mut self.c, value)?;
|
||||
Ok(self.c.delimit()?)
|
||||
self.b.opening = Some(self.i.clone());
|
||||
match &mut self.c {
|
||||
SequenceVariant::Sequence(w) => { w.boundary(&self.b)?; to_writer(w, value)?; }
|
||||
SequenceVariant::Record(w) => { w.boundary(&self.b)?; to_writer(w, value)?; }
|
||||
}
|
||||
self.b.shift(None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn complete(self) -> Result<()> {
|
||||
Ok(self.ser.write.end_seq(self.c)?)
|
||||
match self.c {
|
||||
SequenceVariant::Sequence(mut w) => {
|
||||
w.boundary(&self.b)?;
|
||||
Ok(self.ser.write.end_sequence(w)?)
|
||||
}
|
||||
SequenceVariant::Record(mut w) => {
|
||||
w.boundary(&self.b)?;
|
||||
Ok(self.ser.write.end_record(w)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Type {
|
||||
pub closing: Option<Item>,
|
||||
pub opening: Option<Item>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Item {
|
||||
Annotation,
|
||||
AnnotatedValue,
|
||||
DictionaryKey,
|
||||
DictionaryValue,
|
||||
RecordField,
|
||||
RecordLabel,
|
||||
SequenceValue,
|
||||
SetValue,
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn shift(&mut self, i: Option<Item>) {
|
||||
let tmp = std::mem::replace(&mut self.opening, i);
|
||||
self.closing = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(i: Item) -> Type {
|
||||
Type {
|
||||
closing: None,
|
||||
opening: Some(i),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mid(c: Item, o: Item) -> Type {
|
||||
Type {
|
||||
closing: Some(c),
|
||||
opening: Some(o),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(i: Item) -> Type {
|
||||
Type {
|
||||
closing: Some(i),
|
||||
opening: None,
|
||||
}
|
||||
}
|
|
@ -1,11 +1,26 @@
|
|||
use std::io;
|
||||
|
||||
use super::BinarySource;
|
||||
use super::BytesBinarySource;
|
||||
use super::Embeddable;
|
||||
use super::IOValue;
|
||||
use super::Reader;
|
||||
use super::Writer;
|
||||
use super::packed::PackedReader;
|
||||
use super::packed;
|
||||
|
||||
pub trait DomainParse<D: Embeddable> {
|
||||
fn parse_embedded(
|
||||
&mut self,
|
||||
v: &IOValue,
|
||||
) -> io::Result<D>;
|
||||
}
|
||||
|
||||
pub trait DomainUnparse<D: Embeddable> {
|
||||
fn unparse_embedded(
|
||||
&mut self,
|
||||
d: &D,
|
||||
) -> io::Result<IOValue>;
|
||||
}
|
||||
|
||||
pub trait DomainDecode<D: Embeddable> {
|
||||
fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
|
||||
|
@ -23,7 +38,16 @@ pub trait DomainEncode<D: Embeddable> {
|
|||
) -> io::Result<()>;
|
||||
}
|
||||
|
||||
impl <'a, D: Embeddable, T: DomainDecode<D>> DomainDecode<D> for &'a mut T {
|
||||
impl<'a, D: Embeddable, T: DomainParse<D>> DomainParse<D> for &'a mut T {
|
||||
fn parse_embedded(
|
||||
&mut self,
|
||||
v: &IOValue,
|
||||
) -> io::Result<D> {
|
||||
(**self).parse_embedded(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, D: Embeddable, T: DomainDecode<D>> DomainDecode<D> for &'a mut T {
|
||||
fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
|
||||
&mut self,
|
||||
src: &'src mut S,
|
||||
|
@ -41,7 +65,7 @@ impl DomainDecode<IOValue> for IOValueDomainCodec {
|
|||
src: &'src mut S,
|
||||
read_annotations: bool,
|
||||
) -> io::Result<IOValue> {
|
||||
PackedReader::new(src, IOValueDomainCodec).demand_next(read_annotations)
|
||||
packed::PackedReader::new(src, IOValueDomainCodec).demand_next(read_annotations)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,3 +100,55 @@ impl<D: Embeddable> DomainEncode<D> for NoEmbeddedDomainCodec {
|
|||
Err(io::Error::new(io::ErrorKind::Unsupported, "Embedded values not supported here"))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ViaCodec<C>(C);
|
||||
|
||||
impl<C> ViaCodec<C> {
|
||||
pub fn new(c: C) -> Self {
|
||||
ViaCodec(c)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Embeddable, C: DomainDecode<D>> DomainParse<D> for ViaCodec<C> {
|
||||
fn parse_embedded(
|
||||
&mut self,
|
||||
v: &IOValue,
|
||||
) -> io::Result<D> {
|
||||
let bs = packed::PackedWriter::encode_iovalue(v)?;
|
||||
self.0.decode_embedded(&mut BytesBinarySource::new(&bs), true)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Embeddable, C: DomainEncode<D>> DomainUnparse<D> for ViaCodec<C> {
|
||||
fn unparse_embedded(
|
||||
&mut self,
|
||||
d: &D,
|
||||
) -> io::Result<IOValue> {
|
||||
let mut bs = Vec::new();
|
||||
let w = &mut packed::PackedWriter::new(&mut bs);
|
||||
self.0.encode_embedded(w, d)?;
|
||||
packed::annotated_iovalue_from_bytes(&bs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Embeddable, C: DomainParse<D>> DomainDecode<D> for ViaCodec<C> {
|
||||
fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
|
||||
&mut self,
|
||||
src: &'src mut S,
|
||||
read_annotations: bool,
|
||||
) -> io::Result<D> {
|
||||
let v = src.packed(IOValueDomainCodec).demand_next(read_annotations)?;
|
||||
self.0.parse_embedded(&v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Embeddable, C: DomainUnparse<D>> DomainEncode<D> for ViaCodec<C> {
|
||||
fn encode_embedded<W: Writer>(
|
||||
&mut self,
|
||||
w: &mut W,
|
||||
d: &D,
|
||||
) -> io::Result<()> {
|
||||
let v = self.0.unparse_embedded(d)?;
|
||||
w.write(&mut IOValueDomainCodec, &v)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod boundary;
|
||||
pub mod de;
|
||||
pub mod domain;
|
||||
pub mod magic;
|
||||
|
@ -6,14 +7,19 @@ pub mod reader;
|
|||
pub mod repr;
|
||||
pub mod ser;
|
||||
pub mod signed_integer;
|
||||
pub mod suspendable;
|
||||
pub mod text;
|
||||
pub mod writer;
|
||||
|
||||
pub use de::Deserializer;
|
||||
pub use de::from_value;
|
||||
pub use domain::DomainDecode;
|
||||
pub use domain::DomainEncode;
|
||||
pub use domain::DomainParse;
|
||||
pub use domain::DomainUnparse;
|
||||
pub use domain::IOValueDomainCodec;
|
||||
pub use domain::NoEmbeddedDomainCodec;
|
||||
pub use domain::ViaCodec;
|
||||
pub use packed::PackedReader;
|
||||
pub use packed::PackedWriter;
|
||||
pub use reader::BinarySource;
|
||||
|
@ -28,6 +34,7 @@ pub use repr::AtomClass;
|
|||
pub use repr::CompoundClass;
|
||||
pub use repr::Domain;
|
||||
pub use repr::Double;
|
||||
pub use repr::DummyValue;
|
||||
pub use repr::Embeddable;
|
||||
pub use repr::Float;
|
||||
pub use repr::IOValue;
|
||||
|
@ -42,6 +49,8 @@ pub use repr::Value;
|
|||
pub use repr::ValueClass;
|
||||
pub use ser::Serializer;
|
||||
pub use ser::to_value;
|
||||
pub use text::TextReader;
|
||||
pub use text::TextWriter;
|
||||
pub use writer::Writer;
|
||||
|
||||
pub fn invert_map<A, B>(m: &Map<A, B>) -> Map<B, A>
|
||||
|
|
|
@ -20,6 +20,7 @@ use super::super::{
|
|||
Set,
|
||||
Value,
|
||||
|
||||
boundary as B,
|
||||
reader::{
|
||||
Token,
|
||||
BinarySource,
|
||||
|
@ -353,18 +354,25 @@ impl<'de, 'src, D: Embeddable, N: NestedValue<D>, Dec: DomainDecode<D>, S: Binar
|
|||
}))
|
||||
}
|
||||
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<()> {
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<B::Type> {
|
||||
self.next_compound(Tag::Record, ExpectedKind::Record(arity))?;
|
||||
self.ensure_more_expected()
|
||||
let mut b = B::Type::default();
|
||||
self.ensure_more_expected(&mut b, &B::Item::RecordLabel)?;
|
||||
Ok(b)
|
||||
}
|
||||
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<()> {
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<B::Item> {
|
||||
match self.peek_next_nonannotation_tag()? {
|
||||
Tag::Sequence | Tag::Set => {
|
||||
Tag::Sequence => {
|
||||
self.skip()?;
|
||||
Ok(())
|
||||
Ok(B::Item::SequenceValue)
|
||||
}
|
||||
_ => Err(self.expected(ExpectedKind::SequenceOrSet)),
|
||||
Tag::Set => {
|
||||
self.skip()?;
|
||||
Ok(B::Item::SetValue)
|
||||
}
|
||||
_ =>
|
||||
Err(self.expected(ExpectedKind::SequenceOrSet)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,7 +388,11 @@ impl<'de, 'src, D: Embeddable, N: NestedValue<D>, Dec: DomainDecode<D>, S: Binar
|
|||
self.next_compound(Tag::Dictionary, ExpectedKind::Dictionary)
|
||||
}
|
||||
|
||||
fn close_compound(&mut self) -> ReaderResult<bool> {
|
||||
fn boundary(&mut self, _b: &B::Type) -> ReaderResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close_compound(&mut self, _b: &mut B::Type, _i: &B::Item) -> ReaderResult<bool> {
|
||||
Ok(self.peekend()?)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,75 +2,17 @@ use num::bigint::BigInt;
|
|||
use num::cast::ToPrimitive;
|
||||
use std::convert::TryInto;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ops::DerefMut;
|
||||
use super::constants::Tag;
|
||||
use super::super::DomainEncode;
|
||||
use super::super::Embeddable;
|
||||
use super::super::IOValue;
|
||||
use super::super::IOValueDomainCodec;
|
||||
use super::super::NestedValue;
|
||||
use super::super::boundary as B;
|
||||
use super::super::suspendable::Suspendable;
|
||||
|
||||
use super::super::writer::{Writer, AnnotationWriter, CompoundWriter, varint};
|
||||
|
||||
pub enum Suspendable<T> {
|
||||
Active(T),
|
||||
Suspended,
|
||||
}
|
||||
|
||||
impl<T> Suspendable<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
Suspendable::Active(t)
|
||||
}
|
||||
|
||||
pub fn suspend(&mut self) -> Self {
|
||||
match self {
|
||||
Suspendable::Active(_) => mem::replace(self, Suspendable::Suspended),
|
||||
Suspendable::Suspended =>
|
||||
panic!("Attempt to suspend suspended Suspendable"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resume(&mut self, other: Self) {
|
||||
match self {
|
||||
Suspendable::Suspended =>
|
||||
match other {
|
||||
Suspendable::Active(_) => *self = other,
|
||||
Suspendable::Suspended =>
|
||||
panic!("Attempt to resume from suspended Suspendable"),
|
||||
},
|
||||
Suspendable::Active(_) =>
|
||||
panic!("Attempt to resume non-suspended Suspendable"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take(self) -> T {
|
||||
match self {
|
||||
Suspendable::Active(t) => t,
|
||||
Suspendable::Suspended =>
|
||||
panic!("Attempt to take from suspended Suspendable"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Suspendable<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Suspendable::Suspended => panic!("Suspended Suspendable at deref"),
|
||||
Suspendable::Active(t) => t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Suspendable<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self {
|
||||
Suspendable::Suspended => panic!("Empty Suspendable at deref_mut"),
|
||||
Suspendable::Active(t) => t
|
||||
}
|
||||
}
|
||||
}
|
||||
use super::super::writer::{Writer, CompoundWriter, varint};
|
||||
|
||||
pub struct PackedWriter<W: io::Write>(Suspendable<W>);
|
||||
|
||||
|
@ -153,7 +95,7 @@ impl BinaryOrderWriter {
|
|||
}
|
||||
|
||||
fn finish<W: WriteWriter>(mut self, w: &mut W) -> io::Result<()> {
|
||||
if !self.buffer().is_empty() { panic!("Missing final delimit()"); }
|
||||
if !self.buffer().is_empty() { panic!("Missing final boundary()"); }
|
||||
self.items_mut().pop();
|
||||
self.items_mut().sort();
|
||||
for bs in self.items() {
|
||||
|
@ -184,33 +126,26 @@ impl WriteWriter for BinaryOrderWriter {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: WriteWriter> AnnotationWriter for T {
|
||||
fn start_annotation(&mut self) -> io::Result<()> {
|
||||
Ok(self.write_tag(Tag::Annotation)?)
|
||||
}
|
||||
|
||||
fn start_value(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: io::Write> CompoundWriter for PackedWriter<W> {
|
||||
fn extend(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delimit(&mut self) -> io::Result<()> {
|
||||
fn boundary(&mut self, b: &B::Type) -> io::Result<()> {
|
||||
if let Some(B::Item::Annotation) = b.opening {
|
||||
self.write_tag(Tag::Annotation)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl CompoundWriter for BinaryOrderWriter {
|
||||
fn extend(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delimit(&mut self) -> io::Result<()> {
|
||||
self.items_mut().push(vec![]);
|
||||
fn boundary(&mut self, b: &B::Type) -> io::Result<()> {
|
||||
match b.closing {
|
||||
Some(B::Item::DictionaryValue) |
|
||||
Some(B::Item::RecordField) |
|
||||
Some(B::Item::SequenceValue) |
|
||||
Some(B::Item::SetValue) =>
|
||||
self.items_mut().push(vec![]),
|
||||
_ =>
|
||||
()
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -224,12 +159,12 @@ macro_rules! binary_order_writer_method {
|
|||
|
||||
impl Writer for BinaryOrderWriter {
|
||||
type AnnWriter = PackedWriter<Vec<u8>>;
|
||||
type RecWriter = PackedWriter<Vec<u8>>;
|
||||
type SeqWriter = PackedWriter<Vec<u8>>;
|
||||
type SetWriter = BinaryOrderWriter;
|
||||
type DictWriter = BinaryOrderWriter;
|
||||
type EmbeddedWriter = PackedWriter<Vec<u8>>;
|
||||
|
||||
binary_order_writer_method!(mut align(natural_chunksize: u64) -> io::Result<()>);
|
||||
|
||||
fn start_annotations(&mut self) -> io::Result<Self::AnnWriter> {
|
||||
Ok(self.pop())
|
||||
}
|
||||
|
@ -259,15 +194,20 @@ impl Writer for BinaryOrderWriter {
|
|||
binary_order_writer_method!(mut write_bytes(v: &[u8]) -> io::Result<()>);
|
||||
binary_order_writer_method!(mut write_symbol(v: &str) -> io::Result<()>);
|
||||
|
||||
fn start_record(&mut self, _field_count: Option<usize>) -> io::Result<Self::SeqWriter> {
|
||||
fn start_record(&mut self, _field_count: Option<usize>) -> io::Result<Self::RecWriter> {
|
||||
self.write_tag(Tag::Record)?;
|
||||
Ok(self.pop())
|
||||
}
|
||||
fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> {
|
||||
self.push(rec);
|
||||
self.write_tag(Tag::End)
|
||||
}
|
||||
|
||||
fn start_sequence(&mut self, _item_count: Option<usize>) -> io::Result<Self::SeqWriter> {
|
||||
self.write_tag(Tag::Sequence)?;
|
||||
Ok(self.pop())
|
||||
}
|
||||
fn end_seq(&mut self, seq: Self::SeqWriter) -> io::Result<()> {
|
||||
fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> {
|
||||
self.push(seq);
|
||||
self.write_tag(Tag::End)
|
||||
}
|
||||
|
@ -276,12 +216,16 @@ impl Writer for BinaryOrderWriter {
|
|||
self.write_tag(Tag::Set)?;
|
||||
Ok(BinaryOrderWriter::new())
|
||||
}
|
||||
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> io::Result<Self::SetWriter> {
|
||||
fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> {
|
||||
set.finish(self)
|
||||
}
|
||||
|
||||
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> io::Result<Self::DictWriter> {
|
||||
self.write_tag(Tag::Dictionary)?;
|
||||
Ok(BinaryOrderWriter::new())
|
||||
}
|
||||
fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> {
|
||||
set.finish(self)
|
||||
fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> {
|
||||
dict.finish(self)
|
||||
}
|
||||
|
||||
fn start_embedded(&mut self) -> io::Result<Self::EmbeddedWriter> {
|
||||
|
@ -304,8 +248,10 @@ macro_rules! fits_in_bytes {
|
|||
impl<W: io::Write> Writer for PackedWriter<W>
|
||||
{
|
||||
type AnnWriter = Self;
|
||||
type RecWriter = Self;
|
||||
type SeqWriter = Self;
|
||||
type SetWriter = BinaryOrderWriter;
|
||||
type DictWriter = BinaryOrderWriter;
|
||||
type EmbeddedWriter = Self;
|
||||
|
||||
fn start_annotations(&mut self) -> io::Result<Self::AnnWriter> {
|
||||
|
@ -317,10 +263,6 @@ impl<W: io::Write> Writer for PackedWriter<W>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn align(&mut self, _natural_chunksize: u64) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_bool(&mut self, v: bool) -> io::Result<()> {
|
||||
self.write_tag(if v { Tag::True } else { Tag::False })
|
||||
}
|
||||
|
@ -472,17 +414,22 @@ impl<W: io::Write> Writer for PackedWriter<W>
|
|||
self.write_atom(Tag::Symbol, v.as_bytes())
|
||||
}
|
||||
|
||||
fn start_record(&mut self, _field_count: Option<usize>) -> io::Result<Self::SeqWriter> {
|
||||
fn start_record(&mut self, _field_count: Option<usize>) -> io::Result<Self::RecWriter> {
|
||||
self.write_tag(Tag::Record)?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> {
|
||||
self.resume(rec);
|
||||
self.write_tag(Tag::End)
|
||||
}
|
||||
|
||||
fn start_sequence(&mut self, _item_count: Option<usize>) -> io::Result<Self::SeqWriter> {
|
||||
self.write_tag(Tag::Sequence)?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_seq(&mut self, seq: Self::SeqWriter) -> io::Result<()> {
|
||||
fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> {
|
||||
self.resume(seq);
|
||||
self.write_tag(Tag::End)
|
||||
}
|
||||
|
@ -492,13 +439,17 @@ impl<W: io::Write> Writer for PackedWriter<W>
|
|||
Ok(BinaryOrderWriter::new())
|
||||
}
|
||||
|
||||
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> io::Result<Self::SetWriter> {
|
||||
fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> {
|
||||
set.finish(self)
|
||||
}
|
||||
|
||||
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> io::Result<Self::DictWriter> {
|
||||
self.write_tag(Tag::Dictionary)?;
|
||||
Ok(BinaryOrderWriter::new())
|
||||
}
|
||||
|
||||
fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> {
|
||||
set.finish(self)
|
||||
fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> {
|
||||
dict.finish(self)
|
||||
}
|
||||
|
||||
fn start_embedded(&mut self) -> io::Result<Self::EmbeddedWriter> {
|
||||
|
|
|
@ -12,6 +12,7 @@ use super::IOValue;
|
|||
use super::IOValueDomainCodec;
|
||||
use super::NestedValue;
|
||||
use super::CompoundClass;
|
||||
use super::boundary as B;
|
||||
use super::signed_integer::SignedInteger;
|
||||
|
||||
pub type ReaderResult<T> = std::result::Result<T, error::Error>;
|
||||
|
@ -25,12 +26,16 @@ pub enum Token<D: Embeddable, N: NestedValue<D>> {
|
|||
|
||||
pub trait Reader<'de, D: Embeddable, N: NestedValue<D>> {
|
||||
fn next(&mut self, read_annotations: bool) -> io::Result<Option<N>>;
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<()>;
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<()>;
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<B::Type>;
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<B::Item>;
|
||||
fn open_sequence(&mut self) -> ReaderResult<()>;
|
||||
fn open_set(&mut self) -> ReaderResult<()>;
|
||||
fn open_dictionary(&mut self) -> ReaderResult<()>;
|
||||
fn close_compound(&mut self) -> ReaderResult<bool>;
|
||||
fn boundary(&mut self, b: &B::Type) -> ReaderResult<()>;
|
||||
|
||||
// close_compound implies a b.shift(...) and a self.boundary(b).
|
||||
fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<bool>;
|
||||
|
||||
fn open_embedded(&mut self) -> ReaderResult<()>;
|
||||
fn close_embedded(&mut self) -> ReaderResult<()>;
|
||||
|
||||
|
@ -95,24 +100,29 @@ pub trait Reader<'de, D: Embeddable, N: NestedValue<D>> {
|
|||
Ok(Cow::Owned(self.demand_next(false)?.value().to_symbol()?.to_owned()))
|
||||
}
|
||||
|
||||
fn open_option(&mut self) -> ReaderResult<bool>
|
||||
fn open_option(&mut self) -> ReaderResult<Option<B::Type>>
|
||||
{
|
||||
self.open_record(None)?;
|
||||
let b = self.open_record(None)?;
|
||||
let label: &str = &self.next_symbol()?;
|
||||
match label {
|
||||
"None" => Ok(false),
|
||||
"Some" => Ok(true),
|
||||
_ => Err(error::Error::Expected(ExpectedKind::Option,
|
||||
Received::ReceivedRecordWithLabel(label.to_owned()))),
|
||||
"None" => {
|
||||
self.ensure_complete(b, &B::Item::RecordField)?;
|
||||
Ok(None)
|
||||
}
|
||||
"Some" =>
|
||||
Ok(Some(b)),
|
||||
_ =>
|
||||
Err(error::Error::Expected(ExpectedKind::Option,
|
||||
Received::ReceivedRecordWithLabel(label.to_owned()))),
|
||||
}
|
||||
}
|
||||
|
||||
fn open_simple_record(&mut self, name: &str, arity: Option<usize>) -> ReaderResult<()>
|
||||
fn open_simple_record(&mut self, name: &str, arity: Option<usize>) -> ReaderResult<B::Type>
|
||||
{
|
||||
self.open_record(arity)?;
|
||||
let b = self.open_record(arity)?;
|
||||
let label: &str = &self.next_symbol()?;
|
||||
if label == name {
|
||||
Ok(())
|
||||
Ok(b)
|
||||
} else {
|
||||
Err(error::Error::Expected(ExpectedKind::SimpleRecord(name.to_owned(), arity),
|
||||
Received::ReceivedRecordWithLabel(label.to_owned())))
|
||||
|
@ -130,23 +140,16 @@ pub trait Reader<'de, D: Embeddable, N: NestedValue<D>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn skip_remainder(&mut self) -> ReaderResult<()> {
|
||||
while !self.close_compound()? {
|
||||
self.skip_value()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_more_expected(&mut self) -> ReaderResult<()> {
|
||||
if !self.close_compound()? {
|
||||
fn ensure_more_expected(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<()> {
|
||||
if !self.close_compound(b, i)? {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(error::Error::MissingItem)
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_complete(&mut self) -> ReaderResult<()> {
|
||||
if !self.close_compound()? {
|
||||
fn ensure_complete(&mut self, mut b: B::Type, i: &B::Item) -> ReaderResult<()> {
|
||||
if !self.close_compound(&mut b, i)? {
|
||||
Err(error::Error::MissingCloseDelimiter)
|
||||
} else {
|
||||
Ok(())
|
||||
|
@ -162,11 +165,11 @@ impl<'r, 'de, D: Embeddable, N: NestedValue<D>, R: Reader<'de, D, N>>
|
|||
(*self).next(read_annotations)
|
||||
}
|
||||
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<()> {
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<B::Type> {
|
||||
(*self).open_record(arity)
|
||||
}
|
||||
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<()> {
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<B::Item> {
|
||||
(*self).open_sequence_or_set()
|
||||
}
|
||||
|
||||
|
@ -182,8 +185,12 @@ impl<'r, 'de, D: Embeddable, N: NestedValue<D>, R: Reader<'de, D, N>>
|
|||
(*self).open_dictionary()
|
||||
}
|
||||
|
||||
fn close_compound(&mut self) -> ReaderResult<bool> {
|
||||
(*self).close_compound()
|
||||
fn boundary(&mut self, b: &B::Type) -> ReaderResult<()> {
|
||||
(*self).boundary(b)
|
||||
}
|
||||
|
||||
fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<bool> {
|
||||
(*self).close_compound(b, i)
|
||||
}
|
||||
|
||||
fn open_embedded(&mut self) -> ReaderResult<()> {
|
||||
|
|
|
@ -268,6 +268,7 @@ impl<N: NestedValue<D>, D: Embeddable> From<isize> for Value<N, D> { fn from(v:
|
|||
impl<N: NestedValue<D>, D: Embeddable> From<u128> for Value<N, D> { fn from(v: u128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } }
|
||||
impl<N: NestedValue<D>, D: Embeddable> From<i128> for Value<N, D> { fn from(v: i128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } }
|
||||
impl<N: NestedValue<D>, D: Embeddable> From<&BigInt> for Value<N, D> { fn from(v: &BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Borrowed(v))) } }
|
||||
impl<N: NestedValue<D>, D: Embeddable> From<BigInt> for Value<N, D> { fn from(v: BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Owned(v))) } }
|
||||
impl<N: NestedValue<D>, D: Embeddable> From<&SignedInteger> for Value<N, D> { fn from(v: &SignedInteger) -> Self { Value::SignedInteger(v.clone()) } }
|
||||
|
||||
impl<N: NestedValue<D>, D: Embeddable> From<&str> for Value<N, D> { fn from(v: &str) -> Self { Value::String(String::from(v)) } }
|
||||
|
@ -1183,3 +1184,43 @@ impl<'de> serde::Deserialize<'de> for IOValue {
|
|||
super::magic::input_value(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct DummyValue<D: Embeddable>(AnnotatedValue<DummyValue<D>, D>);
|
||||
|
||||
impl<D: Embeddable> Debug for DummyValue<D> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("<>")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<D: Embeddable> DummyValue<D> {
|
||||
pub fn new() -> Self {
|
||||
DummyValue(AnnotatedValue::new(Annotations::empty(), Value::Boolean(false)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Embeddable> NestedValue<D> for DummyValue<D> {
|
||||
fn wrap(_anns: Annotations<Self, D>, _v: Value<Self, D>) -> Self {
|
||||
DummyValue::new()
|
||||
}
|
||||
|
||||
fn annotations(&self) -> &Annotations<Self, D> {
|
||||
&self.0.0
|
||||
}
|
||||
|
||||
fn value(&self) -> &Value<Self, D> {
|
||||
&self.0.1
|
||||
}
|
||||
|
||||
fn pieces(self) -> (Annotations<Self, D>, Value<Self, D>) {
|
||||
(self.0.0, self.0.1)
|
||||
}
|
||||
|
||||
fn value_owned(self) -> Value<Self, D> {
|
||||
self.0.1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,12 @@ impl From<u128> for SignedInteger {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<BigInt> for SignedInteger {
|
||||
fn from(v: BigInt) -> Self {
|
||||
Self::from(Cow::Owned(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Cow<'a, BigInt>> for SignedInteger {
|
||||
fn from(v: Cow<'a, BigInt>) -> Self {
|
||||
if let Some(w) = v.to_i128() {
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
pub enum Suspendable<T> {
|
||||
Active(T),
|
||||
Suspended,
|
||||
}
|
||||
|
||||
impl<T> Suspendable<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
Suspendable::Active(t)
|
||||
}
|
||||
|
||||
pub fn suspend(&mut self) -> Self {
|
||||
match self {
|
||||
Suspendable::Active(_) => std::mem::replace(self, Suspendable::Suspended),
|
||||
Suspendable::Suspended =>
|
||||
panic!("Attempt to suspend suspended Suspendable"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resume(&mut self, other: Self) {
|
||||
match self {
|
||||
Suspendable::Suspended =>
|
||||
match other {
|
||||
Suspendable::Active(_) => *self = other,
|
||||
Suspendable::Suspended =>
|
||||
panic!("Attempt to resume from suspended Suspendable"),
|
||||
},
|
||||
Suspendable::Active(_) =>
|
||||
panic!("Attempt to resume non-suspended Suspendable"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take(self) -> T {
|
||||
match self {
|
||||
Suspendable::Active(t) => t,
|
||||
Suspendable::Suspended =>
|
||||
panic!("Attempt to take from suspended Suspendable"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Suspendable<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Suspendable::Suspended => panic!("Suspended Suspendable at deref"),
|
||||
Suspendable::Active(t) => t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Suspendable<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self {
|
||||
Suspendable::Suspended => panic!("Empty Suspendable at deref_mut"),
|
||||
Suspendable::Active(t) => t
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
pub mod reader;
|
||||
pub mod writer;
|
||||
|
||||
pub use reader::TextReader;
|
||||
pub use writer::TextWriter;
|
||||
|
||||
use std::io;
|
||||
|
||||
use super::{DomainParse, Embeddable, IOValue, IOValueDomainCodec, NestedValue, Reader, ViaCodec};
|
||||
|
||||
pub fn from_str<D: Embeddable, N: NestedValue<D>, Dec: DomainParse<D>>(
|
||||
s: &str,
|
||||
decode_embedded: Dec,
|
||||
) -> io::Result<N> {
|
||||
TextReader::new(s, decode_embedded).demand_next(false)
|
||||
}
|
||||
|
||||
pub fn iovalue_from_str(s: &str) -> io::Result<IOValue> {
|
||||
from_str(s, ViaCodec::new(IOValueDomainCodec))
|
||||
}
|
||||
|
||||
pub fn annotated_from_str<D: Embeddable, N: NestedValue<D>, Dec: DomainParse<D>>(
|
||||
s: &str,
|
||||
decode_embedded: Dec,
|
||||
) -> io::Result<N> {
|
||||
TextReader::new(s, decode_embedded).demand_next(true)
|
||||
}
|
||||
|
||||
pub fn annotated_iovalue_from_str(s: &str) -> io::Result<IOValue> {
|
||||
annotated_from_str(s, ViaCodec::new(IOValueDomainCodec))
|
||||
}
|
|
@ -0,0 +1,614 @@
|
|||
use crate::error::Error;
|
||||
use crate::error::ExpectedKind;
|
||||
use crate::error::Received;
|
||||
use crate::error::eof;
|
||||
use crate::error::io_syntax_error;
|
||||
use crate::error::is_eof_error;
|
||||
use crate::error::syntax_error;
|
||||
|
||||
use crate::hex;
|
||||
|
||||
use crate::value::CompoundClass;
|
||||
use crate::value::DomainParse;
|
||||
use crate::value::DummyValue;
|
||||
use crate::value::Embeddable;
|
||||
use crate::value::IOValue;
|
||||
use crate::value::IOValueDomainCodec;
|
||||
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::ViaCodec;
|
||||
use crate::value::boundary as B;
|
||||
use crate::value::reader::BinarySource;
|
||||
use crate::value::reader::ReaderResult;
|
||||
use crate::value::repr::Annotations;
|
||||
|
||||
use num::bigint::BigInt;
|
||||
|
||||
use std::io;
|
||||
use std::iter::FromIterator;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct TextReader<'a, D: Embeddable, Dec: DomainParse<D>> {
|
||||
buf: &'a str,
|
||||
pos: usize,
|
||||
dec: Dec,
|
||||
phantom: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<'a, D: Embeddable, Dec: DomainParse<D>> TextReader<'a, D, Dec> {
|
||||
pub fn new(buf: &'a str, dec: Dec) -> Self {
|
||||
TextReader {
|
||||
buf,
|
||||
pos: 0,
|
||||
dec,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn remaining_input(&self) -> &str {
|
||||
&self.buf[self.pos ..]
|
||||
}
|
||||
|
||||
fn peek(&self) -> ReaderResult<char> {
|
||||
if self.pos >= self.buf.len() {
|
||||
Err(eof())
|
||||
} else {
|
||||
Ok(self.buf[self.pos ..].chars().next().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn drop(&mut self, count: usize) {
|
||||
self.pos += count;
|
||||
}
|
||||
|
||||
fn undrop(&mut self, count: usize) {
|
||||
self.pos -= count;
|
||||
}
|
||||
|
||||
fn next_char(&mut self) -> ReaderResult<char> {
|
||||
let c = self.peek()?;
|
||||
self.drop(c.len_utf8());
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
fn skip_whitespace(&mut self) {
|
||||
while let Ok(c) = self.peek() {
|
||||
if !c.is_whitespace() && c != ',' {
|
||||
break;
|
||||
}
|
||||
self.drop(c.len_utf8())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is a duplicate of fn expected in PackedReader.
|
||||
fn expected<N: NestedValue<D>>(&mut self, k: ExpectedKind) -> Error {
|
||||
match Reader::<D, N>::demand_next(self, true) {
|
||||
Ok(v) => Error::Expected(k, Received::ReceivedOtherValue(format!("{:?}", v))),
|
||||
Err(e) => e.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn gather_annotations<N: NestedValue<D>>(&mut self) -> ReaderResult<Vec<N>> {
|
||||
let mut vs = Vec::new();
|
||||
loop {
|
||||
self.skip_whitespace();
|
||||
match self.peek()? {
|
||||
';' => { self.drop(1); vs.push(N::new(self.comment_line()?)) }
|
||||
'@' => { self.drop(1); vs.push(self.demand_next(true)?) }
|
||||
_ => return Ok(vs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_annotations(&mut self) -> ReaderResult<()> {
|
||||
loop {
|
||||
self.skip_whitespace();
|
||||
match self.peek()? {
|
||||
';' => { self.drop(1); self.comment_line()?; },
|
||||
'@' => { self.drop(1); Reader::<D, DummyValue<D>>::skip_value(self)?; },
|
||||
_ => return Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_iovalue(&mut self, read_annotations: bool) -> io::Result<IOValue> {
|
||||
let mut r = TextReader::new(self.remaining_input(), ViaCodec::new(IOValueDomainCodec));
|
||||
let v = r.demand_next(read_annotations)?;
|
||||
self.pos += r.pos;
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn comment_line(&mut self) -> io::Result<String> {
|
||||
let mut s = String::new();
|
||||
loop {
|
||||
match self.next_char()? {
|
||||
'\r' | '\n' => return Ok(s),
|
||||
c => s.push(c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_intpart<N: NestedValue<D>>(&mut self, mut s: String, c: char) -> io::Result<N> {
|
||||
match c {
|
||||
'0' => {
|
||||
s.push(c);
|
||||
self.read_fracexp(s)
|
||||
}
|
||||
_ => {
|
||||
self.read_digit1(&mut s, c)?;
|
||||
self.read_fracexp(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_fracexp<N: NestedValue<D>>(&mut self, mut s: String) -> io::Result<N> {
|
||||
match self.peek()? {
|
||||
'.' => {
|
||||
s.push(self.next_char()?);
|
||||
let c = self.next_char()?;
|
||||
self.read_digit1(&mut s, c)?;
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
self.read_exp(s)
|
||||
}
|
||||
|
||||
fn read_exp<N: NestedValue<D>>(&mut self, mut s: String) -> io::Result<N> {
|
||||
match self.peek()? {
|
||||
'e' | 'E' => {
|
||||
s.push(self.next_char()?);
|
||||
self.read_sign_and_exp(s)
|
||||
}
|
||||
_ => self.finish_number(s)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_sign_and_exp<N: NestedValue<D>>(&mut self, mut s: String) -> io::Result<N> {
|
||||
match self.peek()? {
|
||||
'+' | '-' => s.push(self.next_char()?),
|
||||
_ => (),
|
||||
}
|
||||
let c = self.next_char()?;
|
||||
self.read_digit1(&mut s, c)?;
|
||||
self.finish_number(s)
|
||||
}
|
||||
|
||||
fn finish_number<N: NestedValue<D>>(&mut self, s: String) -> io::Result<N> {
|
||||
if let Ok(n) = s.parse::<BigInt>() {
|
||||
return Ok(N::new(n));
|
||||
}
|
||||
match self.peek()? {
|
||||
'f' | 'F' => {
|
||||
self.drop(1);
|
||||
Ok(N::new(s.parse::<f32>().map_err(
|
||||
|_| io_syntax_error(&format!(
|
||||
"Invalid single-precision number: {:?}", s)))?))
|
||||
}
|
||||
_ =>
|
||||
Ok(N::new(s.parse::<f64>().map_err(
|
||||
|_| io_syntax_error(&format!(
|
||||
"Invalid double-precision number: {:?}", s)))?))
|
||||
}
|
||||
}
|
||||
|
||||
fn read_digit1(&mut self, s: &mut String, c: char) -> io::Result<()>
|
||||
{
|
||||
if !c.is_digit(10) {
|
||||
return Err(io_syntax_error("Incomplete number"));
|
||||
}
|
||||
s.push(c);
|
||||
while self.peek()?.is_digit(10) {
|
||||
s.push(self.next_char()?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_stringlike<X, H, Acc, Element, R>(
|
||||
&mut self,
|
||||
mut seed: R,
|
||||
acc: Acc,
|
||||
xform_item: X,
|
||||
terminator: char,
|
||||
hexescape: char,
|
||||
hexescaper: H,
|
||||
) -> io::Result<R>
|
||||
where
|
||||
X: Fn(char) -> Element,
|
||||
H: Fn(&mut Self) -> io::Result<Element>,
|
||||
Acc: Fn(&mut R, Element) -> (),
|
||||
{
|
||||
loop {
|
||||
match self.next_char()? {
|
||||
c if c == terminator => return Ok(seed),
|
||||
'\\' => match self.next_char()? {
|
||||
c if c == hexescape =>
|
||||
acc(&mut seed, hexescaper(self)?),
|
||||
c if c == terminator || c == '\\' || c == '/' =>
|
||||
acc(&mut seed, xform_item(c)),
|
||||
'b' => acc(&mut seed, xform_item('\x08')),
|
||||
'f' => acc(&mut seed, xform_item('\x0c')),
|
||||
'n' => acc(&mut seed, xform_item('\x0a')),
|
||||
'r' => acc(&mut seed, xform_item('\x0d')),
|
||||
't' => acc(&mut seed, xform_item('\x09')),
|
||||
_ => return Err(io_syntax_error("Invalid escape code")),
|
||||
},
|
||||
c => acc(&mut seed, xform_item(c)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn hexnum(&mut self, count: usize) -> io::Result<u32> {
|
||||
let mut v: u32 = 0;
|
||||
for _ in 0 .. count {
|
||||
let c = self.next_char()?;
|
||||
match c.to_digit(16) {
|
||||
Some(d) =>
|
||||
v = v << 4 | d,
|
||||
None =>
|
||||
return Err(io_syntax_error("Bad hex escape")),
|
||||
}
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn read_string(&mut self, delimiter: char) -> io::Result<String> {
|
||||
self.read_stringlike(
|
||||
String::new(),
|
||||
|s, c| s.push(c),
|
||||
|c| c,
|
||||
delimiter,
|
||||
'u',
|
||||
|r| {
|
||||
let n1 = r.hexnum(4)?;
|
||||
if (0xd800 ..= 0xdbff).contains(&n1) {
|
||||
let mut ok = true;
|
||||
ok = ok && r.next_char()? == '\\';
|
||||
ok = ok && r.next_char()? == 'u';
|
||||
if !ok {
|
||||
Err(io_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;
|
||||
char::from_u32(n).ok_or_else(
|
||||
|| io_syntax_error("Bad code point from surrogate pair"))
|
||||
} else {
|
||||
Err(io_syntax_error("Bad second half of surrogate pair"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char::from_u32(n1).ok_or_else(
|
||||
|| io_syntax_error("Bad code point"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn read_literal_binary<N: NestedValue<D>>(&mut self) -> io::Result<N> {
|
||||
Ok(N::new(&self.read_stringlike(
|
||||
Vec::new(),
|
||||
|bs, b| bs.push(b),
|
||||
|c| c as u8,
|
||||
'"',
|
||||
'x',
|
||||
|r| Ok(r.hexnum(2)? as u8))?[..]))
|
||||
}
|
||||
|
||||
fn read_hex_binary<N: NestedValue<D>>(&mut self) -> io::Result<N> {
|
||||
let mut s = String::new();
|
||||
loop {
|
||||
self.skip_whitespace();
|
||||
let c1 = self.next_char()?;
|
||||
if c1 == '"' {
|
||||
let bs = hex::HexParser::Strict.decode(&s).unwrap();
|
||||
return Ok(N::new(&bs[..]));
|
||||
}
|
||||
let c2 = self.next_char()?;
|
||||
if !(c1.is_digit(16) && c2.is_digit(16)) {
|
||||
return Err(io_syntax_error("Invalid hex binary"));
|
||||
}
|
||||
s.push(c1);
|
||||
s.push(c2);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_base64_binary<N: NestedValue<D>>(&mut self) -> io::Result<N> {
|
||||
let mut s = String::new();
|
||||
loop {
|
||||
self.skip_whitespace();
|
||||
let mut c = self.next_char()?;
|
||||
if c == ']' {
|
||||
let bs = base64::decode_config(&s, base64::STANDARD_NO_PAD)
|
||||
.map_err(|_| io_syntax_error("Invalid base64 character"))?;
|
||||
return Ok(N::new(&bs[..]));
|
||||
}
|
||||
if c == '-' { c = '+'; }
|
||||
if c == '_' { c = '/'; }
|
||||
if c == '=' { continue; }
|
||||
s.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
fn upto<N: NestedValue<D>>(&mut self, delimiter: char, read_annotations: bool) -> io::Result<Vec<N>> {
|
||||
let mut vs = Vec::new();
|
||||
loop {
|
||||
self.skip_whitespace();
|
||||
if self.peek()? == delimiter {
|
||||
self.drop(delimiter.len_utf8());
|
||||
return Ok(vs);
|
||||
}
|
||||
vs.push(Reader::<D, N>::demand_next(self, read_annotations)?);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_dictionary<N: NestedValue<D>>(&mut self, read_annotations: bool) -> io::Result<N> {
|
||||
let mut d = Map::new();
|
||||
loop {
|
||||
self.skip_whitespace();
|
||||
if self.peek()? == '}' {
|
||||
self.drop(1);
|
||||
return Ok(N::new(d));
|
||||
}
|
||||
let k = Reader::<D, N>::demand_next(self, read_annotations)?;
|
||||
self.skip_whitespace();
|
||||
if self.next_char()? != ':' {
|
||||
return Err(io_syntax_error("Missing expected key/value separator"));
|
||||
}
|
||||
let v = Reader::<D, N>::demand_next(self, read_annotations)?;
|
||||
d.insert(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_raw_symbol<N: NestedValue<D>>(&mut self, mut s: String) -> io::Result<N> {
|
||||
loop {
|
||||
let c = match self.peek() {
|
||||
Err(e) if is_eof_error(&e) => ' ',
|
||||
Err(e) => return Err(e)?,
|
||||
Ok(c) if c.is_whitespace() => ' ',
|
||||
Ok(c) => c
|
||||
};
|
||||
match c {
|
||||
'(' | ')' | '{' | '}' | '[' | ']' | '<' | '>' |
|
||||
'"' | ';' | ',' | '@' | '#' | ':' | '|' | ' ' =>
|
||||
return Ok(Value::symbol(&s).wrap()),
|
||||
c => {
|
||||
self.drop(c.len_utf8());
|
||||
s.push(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de, D: Embeddable, N: NestedValue<D>, Dec: DomainParse<D>> Reader<'de, D, N> for TextReader<'a, D, Dec> {
|
||||
fn next(&mut self, read_annotations: bool) -> io::Result<Option<N>> {
|
||||
self.skip_whitespace();
|
||||
let c = match self.next_char() {
|
||||
Ok(c) => c,
|
||||
Err(e) if is_eof_error(&e) => return Ok(None),
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
Ok(Some(match c {
|
||||
'-' => {
|
||||
let c1 = self.next_char()?;
|
||||
self.read_intpart("-".to_owned(), c1)?
|
||||
}
|
||||
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
|
||||
self.read_intpart(String::new(), c)?,
|
||||
'"' =>
|
||||
N::new(self.read_string('"')?),
|
||||
'|' =>
|
||||
Value::symbol(&self.read_string('|')?).wrap(),
|
||||
';' | '@' => {
|
||||
self.undrop(1);
|
||||
if read_annotations {
|
||||
let mut annotations = self.gather_annotations()?;
|
||||
let (existing_annotations, v) =
|
||||
Reader::<D, N>::demand_next(self, read_annotations)?.pieces();
|
||||
annotations.extend_from_slice(existing_annotations.slice());
|
||||
N::wrap(Annotations::new(Some(annotations)), v)
|
||||
} else {
|
||||
self.skip_annotations()?;
|
||||
self.demand_next(read_annotations)?
|
||||
}
|
||||
}
|
||||
':' => {
|
||||
// return Err(io_syntax_error("Unexpected key/value separator between items")),
|
||||
return Err(io_syntax_error(&format!("Unexpected key/value separator between items (pos {:?})", self.pos)));
|
||||
}
|
||||
'#' => match self.next_char()? {
|
||||
'f' => N::new(false),
|
||||
't' => N::new(true),
|
||||
'{' => N::new(Set::from_iter(self.upto('}', read_annotations)?.into_iter())),
|
||||
'"' => self.read_literal_binary()?,
|
||||
'x' => if self.next_char()? == '"' {
|
||||
self.read_hex_binary()?
|
||||
} else {
|
||||
return Err(io_syntax_error("Expected open-quote at start of hex ByteString"));
|
||||
},
|
||||
'[' => self.read_base64_binary()?,
|
||||
'=' => {
|
||||
let bs_val: N = self.demand_next(true)?;
|
||||
if bs_val.annotations().slice().len() > 0 {
|
||||
return Err(io_syntax_error("Annotations not permitted after #="));
|
||||
}
|
||||
match bs_val.value().as_bytestring() {
|
||||
None =>
|
||||
return Err(io_syntax_error("ByteString must follow #=")),
|
||||
Some(bs) =>
|
||||
crate::value::BytesBinarySource::new(bs)
|
||||
.packed(ViaCodec::new(&mut self.dec))
|
||||
.demand_next(read_annotations)?
|
||||
}
|
||||
}
|
||||
'!' => {
|
||||
let v = self.next_iovalue(read_annotations)?;
|
||||
Value::Embedded(self.dec.parse_embedded(&v)?).wrap()
|
||||
}
|
||||
other => return Err(io_syntax_error(&format!("Invalid # syntax: {:?}", other))),
|
||||
},
|
||||
'<' => {
|
||||
let vs = self.upto('>', read_annotations)?;
|
||||
if vs.is_empty() {
|
||||
return Err(io_syntax_error("Missing record label"));
|
||||
}
|
||||
Value::Record(Record(vs)).wrap()
|
||||
}
|
||||
'[' => N::new(self.upto(']', read_annotations)?),
|
||||
'{' => self.read_dictionary(read_annotations)?,
|
||||
'>' => return Err(io_syntax_error("Unexpected >")),
|
||||
']' => return Err(io_syntax_error("Unexpected ]")),
|
||||
'}' => return Err(io_syntax_error("Unexpected }")),
|
||||
other => self.read_raw_symbol(other.to_string())?,
|
||||
}))
|
||||
}
|
||||
|
||||
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<B::Type> {
|
||||
self.skip_annotations()?;
|
||||
if self.peek()? != '<' { return Err(self.expected::<N>(ExpectedKind::Record(arity))); }
|
||||
self.drop(1);
|
||||
let mut b = B::Type::default();
|
||||
Reader::<D, N>::ensure_more_expected(self, &mut b, &B::Item::RecordLabel)?;
|
||||
Ok(b)
|
||||
}
|
||||
|
||||
fn open_sequence_or_set(&mut self) -> ReaderResult<B::Item> {
|
||||
self.skip_annotations()?;
|
||||
let mark = Reader::<D, N>::mark(self)?;
|
||||
match self.next_char()? {
|
||||
'#' => match self.next_char()? {
|
||||
'{' => return Ok(B::Item::SetValue),
|
||||
_ => (),
|
||||
},
|
||||
'[' => return Ok(B::Item::SequenceValue),
|
||||
_ => (),
|
||||
}
|
||||
Reader::<D, N>::restore(self, &mark)?;
|
||||
Err(self.expected::<N>(ExpectedKind::SequenceOrSet))
|
||||
}
|
||||
|
||||
fn open_sequence(&mut self) -> ReaderResult<()> {
|
||||
self.skip_annotations()?;
|
||||
if self.peek()? != '[' { return Err(self.expected::<N>(ExpectedKind::Sequence)); }
|
||||
self.drop(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open_set(&mut self) -> ReaderResult<()> {
|
||||
self.skip_annotations()?;
|
||||
let mark = Reader::<D, N>::mark(self)?;
|
||||
match self.next_char()? {
|
||||
'#' => match self.next_char()? {
|
||||
'{' => return Ok(()),
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
Reader::<D, N>::restore(self, &mark)?;
|
||||
Err(self.expected::<N>(ExpectedKind::Set))
|
||||
}
|
||||
|
||||
fn open_dictionary(&mut self) -> ReaderResult<()> {
|
||||
self.skip_annotations()?;
|
||||
if self.peek()? != '{' { return Err(self.expected::<N>(ExpectedKind::Dictionary)); }
|
||||
self.drop(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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_char()? != ':' {
|
||||
return Err(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()? {
|
||||
'>' | ']' | '}' => {
|
||||
self.drop(1);
|
||||
Ok(true)
|
||||
}
|
||||
_ => {
|
||||
b.shift(Some(i.clone()));
|
||||
Reader::<D, N>::boundary(self, b)?;
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn open_embedded(&mut self) -> ReaderResult<()> {
|
||||
self.skip_annotations()?;
|
||||
let mark = Reader::<D, N>::mark(self)?;
|
||||
match self.next_char()? {
|
||||
'#' => match self.next_char()? {
|
||||
'!' => return Ok(()),
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
Reader::<D, N>::restore(self, &mark)?;
|
||||
Err(self.expected::<N>(ExpectedKind::Embedded))
|
||||
}
|
||||
|
||||
fn close_embedded(&mut self) -> ReaderResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
type Mark = usize;
|
||||
|
||||
fn mark(&mut self) -> io::Result<Self::Mark> {
|
||||
Ok(self.pos)
|
||||
}
|
||||
|
||||
fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> {
|
||||
self.pos = *mark;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_token(&mut self, read_embedded_annotations: bool) -> io::Result<Token<D, N>> {
|
||||
self.skip_annotations()?;
|
||||
let mark = Reader::<D, N>::mark(self)?;
|
||||
Ok(match self.next_char()? {
|
||||
'<' => Token::Compound(CompoundClass::Record),
|
||||
'[' => Token::Compound(CompoundClass::Sequence),
|
||||
'{' => Token::Compound(CompoundClass::Dictionary),
|
||||
'>' => Token::End,
|
||||
']' => Token::End,
|
||||
'}' => Token::End,
|
||||
'#' => match self.next_char()? {
|
||||
'!' => {
|
||||
let v = self.next_iovalue(read_embedded_annotations)?;
|
||||
Token::Embedded(self.dec.parse_embedded(&v)?)
|
||||
}
|
||||
'{' => Token::Compound(CompoundClass::Set),
|
||||
_ => {
|
||||
Reader::<D, N>::restore(self, &mark)?;
|
||||
Token::Atom(self.demand_next(false)?)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
Reader::<D, N>::restore(self, &mark)?;
|
||||
Token::Atom(self.demand_next(false)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn next_annotations_and_token(&mut self) -> io::Result<(Vec<N>, Token<D, N>)> {
|
||||
let annotations = self.gather_annotations()?;
|
||||
Ok((annotations, self.next_token(true)?))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
use crate::value::Writer;
|
||||
use crate::value::suspendable::Suspendable;
|
||||
use crate::value::writer::CompoundWriter;
|
||||
|
||||
use num::bigint::BigInt;
|
||||
|
||||
use std::io;
|
||||
|
||||
use super::super::boundary as B;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum CommaStyle {
|
||||
None,
|
||||
Separating,
|
||||
Terminating,
|
||||
}
|
||||
|
||||
pub struct TextWriter<W: io::Write>(Suspendable<W>, CommaStyle);
|
||||
|
||||
impl std::default::Default for CommaStyle {
|
||||
fn default() -> Self {
|
||||
CommaStyle::None
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: io::Write> TextWriter<W> {
|
||||
pub fn new(w: W) -> Self {
|
||||
TextWriter(Suspendable::new(w), CommaStyle::default())
|
||||
}
|
||||
|
||||
pub fn suspend(&mut self) -> Self {
|
||||
TextWriter(self.0.suspend(), self.1)
|
||||
}
|
||||
|
||||
pub fn resume(&mut self, other: Self) {
|
||||
self.0.resume(other.0)
|
||||
}
|
||||
|
||||
pub fn write_stringlike_char_fallback<F>(
|
||||
&mut self,
|
||||
c: char,
|
||||
f: F,
|
||||
) -> io::Result<()> where
|
||||
F: FnOnce(&mut W, char) -> io::Result<()>
|
||||
{
|
||||
match c {
|
||||
'\\' => write!(self.0, "\\\\"),
|
||||
'\x08' => write!(self.0, "\\b"),
|
||||
'\x0c' => write!(self.0, "\\f"),
|
||||
'\x0a' => write!(self.0, "\\n"),
|
||||
'\x0d' => write!(self.0, "\\r"),
|
||||
'\x09' => write!(self.0, "\\t"),
|
||||
_ => f(&mut self.0, c),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_stringlike_char(&mut self, c: char) -> io::Result<()> {
|
||||
self.write_stringlike_char_fallback(c, |w, c| write!(w, "{}", c))
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: io::Write> CompoundWriter for TextWriter<W> {
|
||||
fn boundary(&mut self, b: &B::Type) -> io::Result<()> {
|
||||
match (b.closing.as_ref(), b.opening.as_ref()) {
|
||||
(None, Some(B::Item::Annotation)) =>
|
||||
write!(self.0, "@"),
|
||||
(Some(_), Some(B::Item::Annotation)) =>
|
||||
write!(self.0, " @"),
|
||||
(Some(B::Item::Annotation), Some(B::Item::AnnotatedValue)) =>
|
||||
write!(self.0, " "),
|
||||
|
||||
(Some(B::Item::DictionaryKey), Some(B::Item::DictionaryValue)) =>
|
||||
write!(self.0, ": "),
|
||||
|
||||
(Some(B::Item::RecordLabel), Some(B::Item::RecordField)) |
|
||||
(Some(B::Item::RecordField), Some(B::Item::RecordField)) =>
|
||||
write!(self.0, " "),
|
||||
|
||||
(Some(B::Item::DictionaryValue), Some(B::Item::DictionaryKey)) |
|
||||
(Some(B::Item::SequenceValue), Some(B::Item::SequenceValue)) |
|
||||
(Some(B::Item::SetValue), Some(B::Item::SetValue)) =>
|
||||
match self.1 {
|
||||
CommaStyle::Separating | CommaStyle::Terminating =>
|
||||
write!(self.0, ", "),
|
||||
CommaStyle::None =>
|
||||
write!(self.0, " "),
|
||||
},
|
||||
|
||||
(Some(B::Item::DictionaryValue), None) |
|
||||
(Some(B::Item::SequenceValue), None) |
|
||||
(Some(B::Item::SetValue), None) =>
|
||||
match self.1 {
|
||||
CommaStyle::Terminating =>
|
||||
write!(self.0, ","),
|
||||
CommaStyle::Separating | CommaStyle::None =>
|
||||
Ok(()),
|
||||
},
|
||||
|
||||
_ =>
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! simple_writer_method {
|
||||
($n:ident, $argty:ty) =>
|
||||
(fn $n (&mut self, v: $argty) -> io::Result<()> {
|
||||
write!(self.0, "{}", v)
|
||||
});
|
||||
}
|
||||
|
||||
impl<W: io::Write> Writer for TextWriter<W> {
|
||||
type AnnWriter = Self;
|
||||
type RecWriter = Self;
|
||||
type SeqWriter = Self;
|
||||
type SetWriter = Self;
|
||||
type DictWriter = Self;
|
||||
type EmbeddedWriter = Self;
|
||||
|
||||
fn start_annotations(&mut self) -> io::Result<Self::AnnWriter> {
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()> {
|
||||
self.resume(ann);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_bool(&mut self, v: bool) -> io::Result<()> {
|
||||
write!(self.0, "{}", if v { "#t" } else { "#f" })
|
||||
}
|
||||
|
||||
fn write_f32(&mut self, v: f32) -> io::Result<()> {
|
||||
write!(self.0, "{:e}f", v)
|
||||
}
|
||||
|
||||
fn write_f64(&mut self, v: f64) -> io::Result<()> {
|
||||
write!(self.0, "{:e}", v)
|
||||
}
|
||||
|
||||
simple_writer_method!(write_i8, i8);
|
||||
simple_writer_method!(write_u8, u8);
|
||||
simple_writer_method!(write_i16, i16);
|
||||
simple_writer_method!(write_u16, u16);
|
||||
simple_writer_method!(write_i32, i32);
|
||||
simple_writer_method!(write_u32, u32);
|
||||
simple_writer_method!(write_i64, i64);
|
||||
simple_writer_method!(write_u64, u64);
|
||||
simple_writer_method!(write_i128, i128);
|
||||
simple_writer_method!(write_u128, u128);
|
||||
simple_writer_method!(write_int, &BigInt);
|
||||
|
||||
fn write_string(&mut self, v: &str) -> io::Result<()> {
|
||||
write!(self.0, "\"")?;
|
||||
for c in v.chars() {
|
||||
match c {
|
||||
'"' => write!(self.0, "\\\"")?,
|
||||
_ => self.write_stringlike_char(c)?,
|
||||
}
|
||||
}
|
||||
write!(self.0, "\"")
|
||||
}
|
||||
|
||||
fn write_bytes(&mut self, v: &[u8]) -> io::Result<()> {
|
||||
write!(self.0, "#[{}]", base64::encode_config(v, base64::STANDARD_NO_PAD))
|
||||
}
|
||||
|
||||
fn write_symbol(&mut self, v: &str) -> io::Result<()> {
|
||||
// FIXME: This regular expression is conservatively correct, but Anglo-chauvinistic.
|
||||
let re = regex::Regex::new("^[a-zA-Z~!$%^&*?_=+/.][-a-zA-Z~!$%^&*?_=+/.0-9]*$").unwrap();
|
||||
if re.is_match(v) {
|
||||
write!(self.0, "{}", v)
|
||||
} else {
|
||||
write!(self.0, "|")?;
|
||||
for c in v.chars() {
|
||||
match c {
|
||||
'|' => write!(self.0, "\\|")?,
|
||||
_ => self.write_stringlike_char(c)?,
|
||||
}
|
||||
}
|
||||
write!(self.0, "|")
|
||||
}
|
||||
}
|
||||
|
||||
fn start_record(&mut self, _field_count: Option<usize>) -> io::Result<Self::RecWriter> {
|
||||
write!(self.0, "<")?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> {
|
||||
self.resume(rec);
|
||||
write!(self.0, ">")
|
||||
}
|
||||
|
||||
fn start_sequence(&mut self, _item_count: Option<usize>) -> io::Result<Self::SeqWriter> {
|
||||
write!(self.0, "[")?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> {
|
||||
self.resume(seq);
|
||||
write!(self.0, "]")
|
||||
}
|
||||
|
||||
fn start_set(&mut self, _item_count: Option<usize>) -> io::Result<Self::SetWriter> {
|
||||
write!(self.0, "#{{")?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> {
|
||||
self.resume(set);
|
||||
write!(self.0, "}}")
|
||||
}
|
||||
|
||||
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> io::Result<Self::DictWriter> {
|
||||
write!(self.0, "{{")?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> {
|
||||
self.resume(dict);
|
||||
write!(self.0, "}}")
|
||||
}
|
||||
|
||||
fn start_embedded(&mut self) -> io::Result<Self::EmbeddedWriter> {
|
||||
write!(self.0, "#!")?;
|
||||
Ok(self.suspend())
|
||||
}
|
||||
|
||||
fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()> {
|
||||
self.resume(ptr);
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,27 +1,22 @@
|
|||
use num::bigint::BigInt;
|
||||
use std::io;
|
||||
use super::DomainEncode;
|
||||
use super::boundary as B;
|
||||
use super::signed_integer::SignedIntegerRepr;
|
||||
use super::repr::{Embeddable, Value, NestedValue, Float, Double};
|
||||
|
||||
pub trait AnnotationWriter: Writer {
|
||||
fn start_annotation(&mut self) -> io::Result<()>;
|
||||
fn start_value(&mut self) -> io::Result<()>;
|
||||
}
|
||||
|
||||
pub trait CompoundWriter: Writer {
|
||||
fn extend(&mut self) -> io::Result<()>;
|
||||
fn delimit(&mut self) -> io::Result<()>;
|
||||
fn boundary(&mut self, b: &B::Type) -> io::Result<()>;
|
||||
}
|
||||
|
||||
pub trait Writer: Sized {
|
||||
type AnnWriter: AnnotationWriter;
|
||||
type AnnWriter: CompoundWriter;
|
||||
type RecWriter: CompoundWriter;
|
||||
type SeqWriter: CompoundWriter;
|
||||
type SetWriter: CompoundWriter;
|
||||
type DictWriter: CompoundWriter;
|
||||
type EmbeddedWriter: Writer;
|
||||
|
||||
fn align(&mut self, natural_chunksize: u64) -> io::Result<()>;
|
||||
|
||||
fn start_annotations(&mut self) -> io::Result<Self::AnnWriter>;
|
||||
fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()>;
|
||||
|
||||
|
@ -46,14 +41,18 @@ pub trait Writer: Sized {
|
|||
fn write_bytes(&mut self, v: &[u8]) -> io::Result<()>;
|
||||
fn write_symbol(&mut self, v: &str) -> io::Result<()>;
|
||||
|
||||
fn start_record(&mut self, field_count: Option<usize>) -> io::Result<Self::SeqWriter>;
|
||||
fn start_record(&mut self, field_count: Option<usize>) -> io::Result<Self::RecWriter>;
|
||||
fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()>;
|
||||
|
||||
fn start_sequence(&mut self, item_count: Option<usize>) -> io::Result<Self::SeqWriter>;
|
||||
fn end_seq(&mut self, seq: Self::SeqWriter) -> io::Result<()>;
|
||||
fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()>;
|
||||
|
||||
fn start_set(&mut self, item_count: Option<usize>) -> io::Result<Self::SetWriter>;
|
||||
fn start_dictionary(&mut self, entry_count: Option<usize>) -> io::Result<Self::SetWriter>;
|
||||
fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()>;
|
||||
|
||||
fn start_dictionary(&mut self, entry_count: Option<usize>) -> io::Result<Self::DictWriter>;
|
||||
fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()>;
|
||||
|
||||
fn start_embedded(&mut self) -> io::Result<Self::EmbeddedWriter>;
|
||||
fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()>;
|
||||
|
||||
|
@ -70,12 +69,17 @@ pub trait Writer: Sized {
|
|||
}
|
||||
Some(anns) => {
|
||||
let mut a = self.start_annotations()?;
|
||||
let mut b = B::Type::default();
|
||||
for ann in anns {
|
||||
a.start_annotation()?;
|
||||
b.shift(Some(B::Item::Annotation));
|
||||
a.boundary(&b)?;
|
||||
a.write(enc, ann)?;
|
||||
}
|
||||
a.start_value()?;
|
||||
b.shift(Some(B::Item::AnnotatedValue));
|
||||
a.boundary(&b)?;
|
||||
a.write_value(enc, v.value())?;
|
||||
b.shift(None);
|
||||
a.boundary(&b)?;
|
||||
self.end_annotations(a)?;
|
||||
}
|
||||
}
|
||||
|
@ -101,43 +105,56 @@ pub trait Writer: Sized {
|
|||
Value::Symbol(s) => self.write_symbol(s),
|
||||
Value::Record(r) => {
|
||||
let mut c = self.start_record(Some(r.arity()))?;
|
||||
c.extend()?;
|
||||
let mut b = B::start(B::Item::RecordLabel);
|
||||
c.boundary(&b)?;
|
||||
c.write(enc, r.label())?;
|
||||
c.delimit()?;
|
||||
for f in r.fields() {
|
||||
c.extend()?;
|
||||
b.shift(Some(B::Item::RecordField));
|
||||
c.boundary(&b)?;
|
||||
c.write(enc, f)?;
|
||||
c.delimit()?;
|
||||
}
|
||||
self.end_seq(c)
|
||||
b.shift(None);
|
||||
c.boundary(&b)?;
|
||||
self.end_record(c)
|
||||
}
|
||||
Value::Sequence(vs) => {
|
||||
let mut c = self.start_sequence(Some(vs.len()))?;
|
||||
let mut b = B::Type::default();
|
||||
for v in vs {
|
||||
c.extend()?;
|
||||
b.shift(Some(B::Item::SequenceValue));
|
||||
c.boundary(&b)?;
|
||||
c.write(enc, v)?;
|
||||
c.delimit()?;
|
||||
}
|
||||
self.end_seq(c)
|
||||
b.shift(None);
|
||||
c.boundary(&b)?;
|
||||
self.end_sequence(c)
|
||||
}
|
||||
Value::Set(vs) => {
|
||||
let mut c = self.start_set(Some(vs.len()))?;
|
||||
let mut b = B::Type::default();
|
||||
for v in vs {
|
||||
c.extend()?;
|
||||
b.shift(Some(B::Item::SetValue));
|
||||
c.boundary(&b)?;
|
||||
c.write(enc, v)?;
|
||||
c.delimit()?;
|
||||
}
|
||||
b.shift(None);
|
||||
c.boundary(&b)?;
|
||||
self.end_set(c)
|
||||
}
|
||||
Value::Dictionary(vs) => {
|
||||
let mut c = self.start_dictionary(Some(vs.len()))?;
|
||||
let mut b = B::Type::default();
|
||||
for (k, v) in vs {
|
||||
c.extend()?;
|
||||
b.shift(Some(B::Item::DictionaryKey));
|
||||
c.boundary(&b)?;
|
||||
c.write(enc, k)?;
|
||||
b.shift(Some(B::Item::DictionaryValue));
|
||||
c.boundary(&b)?;
|
||||
c.write(enc, v)?;
|
||||
c.delimit()?;
|
||||
}
|
||||
self.end_set(c)
|
||||
b.shift(None);
|
||||
c.boundary(&b)?;
|
||||
self.end_dictionary(c)
|
||||
}
|
||||
Value::Embedded(d) => {
|
||||
let mut c = self.start_embedded()?;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use preserves::symbol::Symbol;
|
||||
use preserves::value::{IOValue, Map};
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct TestCases {
|
||||
pub tests: Map<Symbol, TestCase>
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub enum TestCase {
|
||||
Test(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
NondeterministicTest(#[serde(with = "serde_bytes")] Vec<u8>, IOValue),
|
||||
|
|
|
@ -17,12 +17,85 @@ fn decode_all(bytes: &'_ [u8]) -> io::Result<Vec<IOValue>> {
|
|||
BytesBinarySource::new(bytes).packed_iovalues().configured(true).collect()
|
||||
}
|
||||
|
||||
#[test] fn compare_text_with_packed() -> io::Result<()> {
|
||||
use io::prelude::*;
|
||||
let from_text = {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap();
|
||||
let mut contents = String::new();
|
||||
fh.read_to_string(&mut contents)?;
|
||||
let mut d = preserves::value::TextReader::new(&contents, preserves::value::ViaCodec::new(preserves::value::IOValueDomainCodec));
|
||||
d.next_iovalue(true)?
|
||||
};
|
||||
let from_packed = {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap();
|
||||
IOBinarySource::new(&mut fh).packed_iovalues().demand_next(true)?
|
||||
};
|
||||
assert_eq!(from_text, from_packed);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test] fn compare_deserialize_text_with_packed() -> io::Result<()> {
|
||||
use io::prelude::*;
|
||||
let from_text = {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap();
|
||||
let mut contents = String::new();
|
||||
fh.read_to_string(&mut contents)?;
|
||||
let tests: TestCases = preserves::de::from_text(&contents)?;
|
||||
tests
|
||||
};
|
||||
let from_packed = {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap();
|
||||
let tests: TestCases = preserves::de::from_read(&mut fh)?;
|
||||
tests
|
||||
};
|
||||
assert_eq!(from_text, from_packed);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test] fn read_write_read_text() -> io::Result<()> {
|
||||
use io::prelude::*;
|
||||
let from_text = {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap();
|
||||
let mut contents = String::new();
|
||||
fh.read_to_string(&mut contents)?;
|
||||
preserves::value::text::annotated_iovalue_from_str(&contents)?
|
||||
};
|
||||
let roundtripped = {
|
||||
let mut bs = Vec::new();
|
||||
let mut w = preserves::value::TextWriter::new(&mut bs);
|
||||
preserves::ser::to_writer(&mut w, &from_text)?;
|
||||
let s = String::from_utf8(bs).unwrap();
|
||||
preserves::value::text::annotated_iovalue_from_str(&s)?
|
||||
};
|
||||
assert_eq!(from_text, roundtripped);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test] fn deserialize_serialize_deserialize_text() -> io::Result<()> {
|
||||
use io::prelude::*;
|
||||
let from_text = {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap();
|
||||
let mut contents = String::new();
|
||||
fh.read_to_string(&mut contents)?;
|
||||
let tests: TestCases = preserves::de::from_text(&contents)?;
|
||||
tests
|
||||
};
|
||||
let roundtripped = {
|
||||
let mut bs = Vec::new();
|
||||
let mut w = preserves::value::TextWriter::new(&mut bs);
|
||||
preserves::ser::to_writer(&mut w, &from_text)?;
|
||||
let s = String::from_utf8(bs).unwrap();
|
||||
preserves::de::from_text(&s)?
|
||||
};
|
||||
assert_eq!(from_text, roundtripped);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test] fn run() -> io::Result<()> {
|
||||
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap();
|
||||
let mut src = IOBinarySource::new(&mut fh);
|
||||
let mut d = src.packed_iovalues().configured(true);
|
||||
let tests: TestCases = deserialize_from_value(&d.next().unwrap().unwrap()).unwrap();
|
||||
// println!("{:#?}", tests);
|
||||
|
||||
for (Symbol(ref name), ref case) in tests.tests {
|
||||
println!("{:?} ==> {:?}", name, case);
|
||||
|
|
Loading…
Reference in New Issue