diff --git a/implementations/rust/preserves-schema/Cargo.toml b/implementations/rust/preserves-schema/Cargo.toml index f902511..a247ac3 100644 --- a/implementations/rust/preserves-schema/Cargo.toml +++ b/implementations/rust/preserves-schema/Cargo.toml @@ -11,10 +11,9 @@ license = "Apache-2.0" [dependencies] preserves = { path = "../preserves", version = "0.15.0" } -structopt = "0.3.14" -glob = "0.3.0" -regex = "1.5.4" - convert_case = "0.4.0" - +glob = "0.3.0" lazy_static = "1.4.0" +regex = "1.5.4" +structopt = "0.3.14" +thiserror = "1.0" diff --git a/implementations/rust/preserves-schema/src/compiler/codegen.rs b/implementations/rust/preserves-schema/src/compiler/codegen.rs deleted file mode 100644 index d33f4b5..0000000 --- a/implementations/rust/preserves-schema/src/compiler/codegen.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::*; -use crate::syntax::block::Item; -use crate::syntax::block::constructors::*; - -pub fn push_let(body: &mut Vec, name: Item, expr: Item) { - body.push(item(seq!["let ", name, " = ", expr, ";"])) -} - -pub fn push_let_mut(body: &mut Vec, name: Item, expr: Item) { - body.push(item(seq!["let mut ", name, " = ", expr, ";"])) -} diff --git a/implementations/rust/preserves-schema/src/compiler/context.rs b/implementations/rust/preserves-schema/src/compiler/context.rs index 1bb89a1..7101ebf 100644 --- a/implementations/rust/preserves-schema/src/compiler/context.rs +++ b/implementations/rust/preserves-schema/src/compiler/context.rs @@ -1,5 +1,6 @@ use crate::*; use crate::syntax::block::Item; +use crate::syntax::block::escape_string; use crate::syntax::block::constructors::*; use crate::gen::schema::*; @@ -22,6 +23,7 @@ pub enum ModuleContextMode { } pub struct ModuleContext<'m> { + pub module_path: ModulePath, pub config: &'m CompilerConfig, pub literals: Map<_Any, String>, pub typedefs: Vec, @@ -30,9 +32,11 @@ pub struct ModuleContext<'m> { } pub struct FunctionContext<'a, 'm> { + pub error_context: String, pub m: &'a mut ModuleContext<'m>, pub temp_counter: usize, pub captures: Vec, + pub capture_mode: CaptureMode, } pub struct Capture { @@ -41,13 +45,19 @@ pub struct Capture { pub source_expr: String, } +pub enum CaptureMode { + Definite, + Indefinite(Vec), +} + lazy_static! { static ref ID_RE: regex::Regex = regex::Regex::new(r"^[a-zA-Z][a-zA-Z_0-9]*$").unwrap(); } impl<'m> ModuleContext<'m> { - pub fn new(config: &'m CompilerConfig) -> Self { + pub fn new(config: &'m CompilerConfig, module_path: &ModulePath) -> Self { ModuleContext { + module_path: module_path.to_owned(), config: config, literals: Map::new(), typedefs: Vec::new(), @@ -73,8 +83,8 @@ impl<'m> ModuleContext<'m> { self.typedefs.push(i) } - pub fn define_function Item>(&mut self, f: F) { - let i = f(FunctionContext::new(self)); + pub fn define_function Item>(&mut self, error_context: &str, f: F) { + let i = f(FunctionContext::new(self, error_context)); self.functiondefs.push(i) } @@ -111,11 +121,13 @@ impl<'m> ModuleContext<'m> { } impl<'a, 'm> FunctionContext<'a, 'm> { - pub fn new(m: &'a mut ModuleContext<'m>) -> Self { + pub fn new(m: &'a mut ModuleContext<'m>, error_context: &str) -> Self { FunctionContext { + error_context: error_context.to_owned(), m: m, temp_counter: 0, captures: Vec::new(), + capture_mode: CaptureMode::Definite, } } @@ -123,7 +135,12 @@ impl<'a, 'm> FunctionContext<'a, 'm> { self.captures.push(Capture { field_name: field_name, ty: ty, - source_expr: source_expr, + source_expr: match self.capture_mode { + CaptureMode::Definite => + source_expr, + CaptureMode::Indefinite(_) => + format!("{}.ok_or_else(|| {:?})?", source_expr, self.conformance_err_code()), + } }) } @@ -142,6 +159,29 @@ impl<'a, 'm> FunctionContext<'a, 'm> { format!("_tmp{}", i) } + pub fn declare_compound(&self, body: &mut Vec, name: &str, init_expr: Item) { + body.push(item(seq!["let mut ", name.to_owned(), " = ", init_expr, ";"])); + } + + pub fn define_atom(&mut self, body: &mut Vec, name: &str, val_expr: Item) { + body.push(match &mut self.capture_mode { + CaptureMode::Definite => item(seq!["let ", name.to_owned(), " = ", val_expr, ";"]), + CaptureMode::Indefinite(items) => { + items.push(item(seq!["let mut ", name.to_owned(), " = None;"])); + item(seq![name.to_owned(), " = Some(", val_expr, ");"]) + } + }) + } + + pub fn with_indefinite_mode ()>(&mut self, f: F) -> Vec { + let saved_mode = std::mem::replace(&mut self.capture_mode, CaptureMode::Indefinite(Vec::new())); + f(self); + match std::mem::replace(&mut self.capture_mode, saved_mode) { + CaptureMode::Definite => panic!("corrupt capture_mode"), + CaptureMode::Indefinite(declarations) => declarations, + } + } + pub fn branch R>(&mut self, f: F) -> R { let saved_temp_counter = self.temp_counter; let saved_capture_count = self.captures.len(); @@ -150,4 +190,13 @@ impl<'a, 'm> FunctionContext<'a, 'm> { self.captures.truncate(saved_capture_count); result } + + pub fn err_code(&self) -> Item { + return item(seq!["Err", parens![self.conformance_err_code()]]); + } + + pub fn conformance_err_code(&self) -> Item { + return item(seq!["_support::ParseError::conformance_error", parens![ + escape_string(&(self.m.module_path.0.join(".") + "." + &self.error_context))]]); + } } diff --git a/implementations/rust/preserves-schema/src/compiler/mod.rs b/implementations/rust/preserves-schema/src/compiler/mod.rs index 67a9ae0..8c5cc8b 100644 --- a/implementations/rust/preserves-schema/src/compiler/mod.rs +++ b/implementations/rust/preserves-schema/src/compiler/mod.rs @@ -1,9 +1,9 @@ -pub mod types; -pub mod names; pub mod context; +pub mod names; pub mod parsers; +pub mod readers; +pub mod types; pub mod unparsers; -pub mod codegen; use crate::*; use crate::gen::schema::*; @@ -115,7 +115,7 @@ pub fn compile(config: &CompilerConfig) -> io::Result<()> { let module_name = names::render_modname(&module_name); output_path.set_file_name(format!("{}.rs", module_name)); DirBuilder::new().recursive(true).create(output_path.parent().unwrap())?; - let mut m = context::ModuleContext::new(config); + let mut m = context::ModuleContext::new(config, &ModulePath(k.clone())); let mut modes: Vec = vec![context::ModuleContextMode::TargetAny]; @@ -144,6 +144,7 @@ pub fn compile(config: &CompilerConfig) -> io::Result<()> { parsers::gen_definition_parser(&mut m, n, d); unparsers::gen_definition_unparser(&mut m, n, d); } + readers::gen_definition_reader(&mut m, n, d); } //--------------------------------------------------------------------------- @@ -157,6 +158,7 @@ pub fn compile(config: &CompilerConfig) -> io::Result<()> { lines.push("use preserves::value::Domain;".to_owned()); lines.push("use preserves::value::NestedValue;".to_owned()); lines.push(format!("use {}::support as _support;", &config.support_crate)); + lines.push("use _support::Deserialize;".to_owned()); lines.push("".to_owned()); for mode in &modes { diff --git a/implementations/rust/preserves-schema/src/compiler/parsers.rs b/implementations/rust/preserves-schema/src/compiler/parsers.rs index 92c110f..3f68bd1 100644 --- a/implementations/rust/preserves-schema/src/compiler/parsers.rs +++ b/implementations/rust/preserves-schema/src/compiler/parsers.rs @@ -3,13 +3,13 @@ use crate::gen::schema::*; use crate::syntax::block::Item; use crate::syntax::block::constructors::*; -use super::codegen::*; use super::context::{ModuleContextMode, ModuleContext, FunctionContext}; use super::names; use super::types::*; pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { m.define_function( + n, |mut ctxt| { let mut body = vec![]; @@ -22,6 +22,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { names::render_fieldname(n), "_", names::render_fieldname(name)]; let ctorname = item(name![names::render_constructor(n), names::render_constructor(name)]); ctxt.m.define_function( + &(n.to_owned() + "::" + name), |mut ctxt| { let mut body = Vec::new(); let dest = pattern_parser(&mut ctxt, pat, "value", None, &mut body); @@ -33,7 +34,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { }); body.push(item(seq!["if let Ok(r) = ", fname, "(value) { return Ok(r); }"])); } - body.push(item(seq!["Err(_support::ParseError::ConformanceError)"])); + body.push(item(seq![ctxt.err_code()])); } Definition::And { pattern_0, pattern_1, pattern_n } => { let mut ps = vec![&**pattern_0, &**pattern_1]; @@ -108,9 +109,9 @@ fn simple_pattern_parser( SimplePattern::Any => { match ctxt.m.mode { ModuleContextMode::TargetIOValue => - push_let(body, item(dest.to_owned()), item(seq!["_support::decode_embedded", parens![src.to_owned()], "?"])), + ctxt.define_atom(body, &dest, item(seq!["_support::decode_embedded", parens![src.to_owned()], "?"])), ModuleContextMode::TargetAny => - push_let(body, item(dest.to_owned()), item(src.to_owned())), + ctxt.define_atom(body, &dest, item(src.to_owned())), } dest }, @@ -124,26 +125,26 @@ fn simple_pattern_parser( AtomKind::ByteString => "to_bytestring", AtomKind::Symbol => "to_symbol", }; - push_let(body, item(dest.to_owned()), item(seq![src.to_owned(), ".value().", converter, "()?"])); + ctxt.define_atom(body, &dest, item(seq![src.to_owned(), ".value().", converter, "()?"])); dest }, SimplePattern::Embedded { .. } => { match ctxt.m.mode { ModuleContextMode::TargetIOValue => - push_let(body, item(dest.to_owned()), item(seq![ + ctxt.define_atom(body, &dest, item(seq![ "std::sync::Arc::new(_Dom::try_from", parens![seq![src.to_owned(), ".value().to_embedded()?"]], "?)"])), ModuleContextMode::TargetAny => - push_let(body, item(dest.to_owned()), item(seq![ + ctxt.define_atom(body, &dest, item(seq![ parens![seq![src.to_owned(), ".value().to_embedded()?"]]])), } dest }, SimplePattern::Lit { value } => { body.push(item(seq!["if ", src.to_owned(), " != ", ctxt.m.define_literal(value), - " { return Err(_support::ParseError::ConformanceError); }"])); - push_let(body, item(dest.to_owned()), item("()")); + " { return ", ctxt.err_code(), "; }"])); + ctxt.define_atom(body, &dest, item("()")); dest }, SimplePattern::Seqof { pattern } => { @@ -153,7 +154,7 @@ fn simple_pattern_parser( let item_dest = simple_pattern_parser(ctxt, pattern, &tmp, None, &mut inner); inner.push(item(seq![dest.to_owned(), ".push(", store_wrap(true, &field_type(pattern), &item_dest), ");"])); - push_let_mut(body, item(dest.to_owned()), item("std::vec::Vec::new()")); + ctxt.declare_compound(body, &dest, item("std::vec::Vec::new()")); body.push(item(seq!["for ", tmp.to_owned(), " in &", src.to_owned(), brackets![seq![n.to_string() , ".."]], " ", block(inner)])); @@ -165,7 +166,7 @@ fn simple_pattern_parser( let item_dest = simple_pattern_parser(ctxt, pattern, &tmp, None, &mut inner); inner.push(item(seq![dest.to_owned(), ".insert(", store_wrap(true, &field_type(pattern), &item_dest), ");"])); - push_let_mut(body, item(dest.to_owned()), item("preserves::value::Set::new()")); + ctxt.declare_compound(body, &dest, item("preserves::value::Set::new()")); body.push(item(seq!["for ", tmp.to_owned(), " in ", src.to_owned(), ".value().to_set()?", " ", block(inner)])); @@ -181,7 +182,7 @@ fn simple_pattern_parser( dest.to_owned(), ".insert(", store_wrap(true, &field_type(key), &key_dest), ", ", store_wrap(true, &field_type(value), &value_dest), ");"])); - push_let_mut(body, item(dest.to_owned()), item("preserves::value::Map::new()")); + ctxt.declare_compound(body, &dest, item("preserves::value::Map::new()")); body.push(item(seq!["for (", tmp_key.to_owned(), ", ", tmp_value.to_owned(), ")", " in ", src.to_owned(), ".value().to_dictionary()?", " ", block(inner)])); @@ -189,9 +190,9 @@ fn simple_pattern_parser( }, SimplePattern::Ref(r) => { let tf = name![ctxt.m.render_ref(&**r), "try_from"]; - push_let(body, - item(dest.to_owned()), - item(seq![tf, parens![seq![src.to_owned()]], "?"])); + ctxt.define_atom(body, + &dest, + item(seq![tf, parens![seq![src.to_owned()]], "?"])); dest }, } @@ -207,9 +208,7 @@ fn sequenceify( Some(n) => (src.to_owned(), n), None => { let tmp = ctxt.gentempname(); - push_let(body, - item(tmp.to_owned()), - item(seq![src.to_owned(), ".value().to_sequence()?"])); + ctxt.define_atom(body, &tmp, item(seq![src.to_owned(), ".value().to_sequence()?"])); (tmp, 0) } } @@ -228,7 +227,7 @@ fn fixed_sequence_parser( body.push(item(seq!["if ", src.to_owned(), ".len()", if base > 0 { seq![" - ", base.to_string()] } else { seq![] }, " < ", required_count.to_string(), - " { return Err(_support::ParseError::ConformanceError); }"])); + " { return ", ctxt.err_code(), "; }"])); } for p in ps { named_pattern_parser(ctxt, p, &format!("(&{}[{}])", src, i), None, body); @@ -270,7 +269,7 @@ fn pattern_parser( match &**c { CompoundPattern::Rec { label, fields } => { let rtmp = ctxt.gentempname(); - push_let(body, item(rtmp.to_owned()), item(seq![src.to_owned(), ".value().to_record(None)?"])); + ctxt.define_atom(body, &rtmp, item(seq![src.to_owned(), ".value().to_record(None)?"])); named_pattern_parser(ctxt, &**label, &format!("{}.label()", rtmp), None, body); named_pattern_parser(ctxt, &**fields, &format!("{}.fields()", rtmp), Some(0), body); }, @@ -285,12 +284,13 @@ fn pattern_parser( }, CompoundPattern::Dict { entries } => { let dtmp = ctxt.gentempname(); - push_let(body, item(dtmp.to_owned()), item(seq![src.to_owned(), ".value().to_dictionary()?"])); + ctxt.define_atom(body, &dtmp, item(seq![src.to_owned(), ".value().to_dictionary()?"])); for (key_lit, value_pat) in entries.0.iter() { let vtmp = ctxt.gentempname(); - push_let(body, item(vtmp.to_owned()), item(seq![ + let init_expr = item(seq![ dtmp.to_owned(), ".get", parens![ctxt.m.define_literal(key_lit)], - ".ok_or(_support::ParseError::ConformanceError)?"])); + ".ok_or_else(|| ", ctxt.conformance_err_code(), ")?"]); + ctxt.define_atom(body, &vtmp, init_expr); named_pattern_parser(ctxt, &promote(value_pat), &vtmp, None, body); } } diff --git a/implementations/rust/preserves-schema/src/compiler/readers.rs b/implementations/rust/preserves-schema/src/compiler/readers.rs new file mode 100644 index 0000000..d0e2592 --- /dev/null +++ b/implementations/rust/preserves-schema/src/compiler/readers.rs @@ -0,0 +1,412 @@ +use crate::*; +use crate::gen::schema::*; +use crate::syntax::block::Item; +use crate::syntax::block::escape_string; +use crate::syntax::block::escape_bytes; +use crate::syntax::block::constructors::*; + +use preserves::value::AtomClass; +use preserves::value::CompoundClass; +use preserves::value::NestedValue; +use preserves::value::ValueClass; + +use super::context::{ModuleContext, FunctionContext}; +use super::names; +use super::types::*; + +pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) { + m.define_function( + n, + |mut ctxt| { + let mut body = vec![]; + + match d { + Definition::Or { pattern_0, pattern_1, pattern_n } => { + let mut ps = vec![&**pattern_0, &**pattern_1]; + ps.extend(pattern_n); + ctxt.define_atom(&mut body, "_mark", item("r.mark()?")); + for NamedAlternative { variant_label: name, pattern: pat } in ps { + let fname = seq![ctxt.m.target_prefix(), "read_", + names::render_fieldname(n), "_", names::render_fieldname(name)]; + let ctorname = item(name![names::render_constructor(n), names::render_constructor(name)]); + ctxt.m.define_function( + &(n.to_owned() + "::" + name), + |mut ctxt| { + let mut body = Vec::new(); + let dest = pattern_reader(&mut ctxt, pat, false, &mut body); + let dest = dest.as_ref().map(String::as_str); + construct(&ctxt, ctorname, false, &pattern_type(pat), dest, &mut body); + item(seq![ + "fn ", fname.clone(), anglebrackets![ + "'de", + "R: _support::Reader<'de, _Ptr, _Any>"], + "(r: &mut R) -> ", + "std::result::Result<", names::render_constructor(n), ", _support::ParseError> ", + block(body)]) + }); + body.push(item(seq![ + "match ", fname, "(r) { ", + "Err(e) if e.is_conformance_error() => r.restore(&_mark)?, ", + "result => return result }"])); + } + body.push(item(seq![ctxt.err_code()])); + } + Definition::And { pattern_0, pattern_1, pattern_n } => { + let mut ps = vec![&**pattern_0, &**pattern_1]; + ps.extend(pattern_n); + for e in &ps { + named_pattern_reader(&mut ctxt, e, false, &mut body); + } + construct(&ctxt, item(names::render_constructor(n)), true, &record_type(&ps), None, &mut body); + } + Definition::Pattern(p) => { + let dest = pattern_reader(&mut ctxt, p, false, &mut body); + let dest = dest.as_ref().map(String::as_str); + construct(&ctxt, item(names::render_constructor(n)), true, &pattern_type(p), dest, &mut body); + } + } + + item(seq![ + "impl", anglebrackets!["'de", "R: _support::Reader<'de, _Ptr, _Any>"], " ", + "_support::Deserialize", anglebrackets!["'de", "_Ptr", "_Any", "R"], " ", + "for ", names::render_constructor(n), " ", block![ + seq!["fn deserialize(r: &mut R) -> ", + "std::result::Result ", + block(body)]]]) + }); +} + +fn construct( + ctxt: &FunctionContext, + ctorname: Item, + is_struct: bool, + ty: &TSimple, + dest: Option<&str>, + body: &mut Vec, +) { + match ty { + TSimple::Field(TField::Unit) => + body.push(item(seq!["Ok(", ctorname, ")"])), + TSimple::Field(fieldty) => + body.push(item(seq!["Ok(", ctorname, parens![store_wrap(is_struct, fieldty, dest.unwrap())], ")"])), + TSimple::Record(_) => + body.push(item(seq!["Ok(", ctorname, " ", braces( + ctxt.captures.iter().map( + |c| item(seq![c.field_name.clone(), ": ", store_wrap(is_struct, &c.ty, &c.source_expr)])).collect()), + ")"])), + } +} + +fn store_wrap(is_struct: bool, ty: &TField, expr: &str) -> String { + match ty { + TField::Unit + | TField::Array(_) + | TField::Set(_) + | TField::Map(_, _) => expr.to_owned(), + TField::Ref(_) => + if is_struct { + expr.to_owned() + } else { + format!("std::boxed::Box::new({})", expr) + }, + TField::Base(_) => expr.to_owned(), + } +} + +fn group_by(mut items: Vec, mut key: Key) -> Vec<(K, Vec)> +where + K: Ord + Clone, + Key: FnMut(&T) -> K, +{ + let mut result = Vec::new(); + let mut current_key: Option = None; + let mut buf = Vec::new(); + items.sort_by(|a, b| key(a).cmp(&key(b))); + for (k, v) in items.into_iter().map(|t| (key(&t), t)) { + match current_key.cmp(&Some(k.clone())) { + std::cmp::Ordering::Equal => (), + std::cmp::Ordering::Less | + std::cmp::Ordering::Greater => { + if let Some(k) = current_key { + result.push((k, std::mem::take(&mut buf))); + } + current_key = Some(k); + } + } + buf.push(v) + } + if let Some(k) = current_key { + result.push((k.clone(), std::mem::take(&mut buf))); + } + result +} + +type LiteralContinuation = Box) -> ()>; +type LiteralCases = Vec<(_Any, LiteralContinuation)>; +type LiteralSeqCases = Vec<(Vec<_Any>, LiteralContinuation)>; + +fn read_expected_literal_seqs( + ctxt: &mut FunctionContext, + body: &mut Vec, + possibilities: LiteralSeqCases, +) { + let grouped = group_by(possibilities, |(vs, _f)| if vs.is_empty() { + None + } else { + Some(vs[0].clone()) + }); + let mut cases = Vec::new(); + let mut nested: LiteralCases = Vec::new(); + for (head, group) in grouped.into_iter() { + match head { + None => { + let mut inner = Vec::new(); + group.into_iter().next().unwrap().1(ctxt, &mut inner); + cases.push(item(seq!["preserves::value::Token::End => ", block(inner)])); + }, + Some(h) => { + let tails = group.into_iter().map(|(mut vs, f)| { + vs.remove(0); + (vs, f) + }).collect(); + nested.push((h, Box::new(|ctxt: &mut FunctionContext, b: &'_ mut Vec| { + read_expected_literal_seqs(ctxt, b, tails) + }))); + } + } + } + cases.extend(read_expected_literals_cases(ctxt, nested)); + body.push(item(seq!["match r.next_token(false)? ", block(cases)])); +} + +fn read_expected_literals_cases( + ctxt: &mut FunctionContext, + possibilities: LiteralCases, +) -> Vec { + let grouped = group_by(possibilities, |(v, _f)| v.value_class()); + let mut cases = grouped.into_iter().map(|(n, group)| { + match n { + ValueClass::Atomic(cls) => { + let mut subcases = Vec::new(); + for p in group { + let mut inner = Vec::new(); + p.1(ctxt, &mut inner); + subcases.push(item(seq![ + format!("preserves::value::Value::{:?}(w)", cls), + match cls { + AtomClass::Boolean => match p.0.value().to_boolean().unwrap() { + true => " if *w".to_owned(), + false => " if !*w".to_owned(), + }, + AtomClass::Float | + AtomClass::Double => + format!(" if w.0 == {:?}", p.0), + AtomClass::SignedInteger => + format!(" if *w == ({:?}).into()", p.0), + AtomClass::String => + format!(" if w == {}", escape_string(p.0.value().to_string().unwrap())), + AtomClass::ByteString => + format!(" if w == {}", escape_bytes(p.0.value().to_bytestring().unwrap())), + AtomClass::Symbol => + format!(" if w == {}", escape_string(p.0.value().to_symbol().unwrap())), + }, + " => ", + block(inner)])); + } + subcases.push(item(seq!["_ => return ", ctxt.err_code(), "?,"])); + item(seq!["preserves::value::Token::Atom(v) => match v.value() ", block(subcases)]) + } + ValueClass::Compound(CompoundClass::Record) => { + let mut subcases = Vec::new(); + read_expected_literal_seqs(ctxt, &mut subcases, group.into_iter().map(|(v, f)| { + let r = v.value().to_record(None).unwrap(); + (r.0.clone(), f) + }).collect()); + item(seq![ + "preserves::value::Token::Compound(preserves::value::CompoundClass::Record) => ", + block(subcases)]) + } + ValueClass::Compound(CompoundClass::Sequence) => { + let mut subcases = Vec::new(); + read_expected_literal_seqs(ctxt, &mut subcases, group.into_iter().map(|(v, f)| { + let s = v.value().to_sequence().unwrap().clone(); + (s, f) + }).collect()); + item(seq![ + "preserves::value::Token::Compound(preserves::value::CompoundClass::Sequence) => ", + block(subcases)]) + } + ValueClass::Compound(CompoundClass::Set) => { + panic!("Sets in literal constants in Schema not yet supported"); + } + ValueClass::Compound(CompoundClass::Dictionary) => { + panic!("Dictionaries in literal constants in Schema not yet supported"); + } + ValueClass::Embedded => { + panic!("Embedded values in literal constants in Schema not yet supported"); + } + } + }).collect::>(); + cases.push(item(seq!["_ => return ", ctxt.err_code(), "?,"])); + cases +} + +fn read_expected_literals( + ctxt: &mut FunctionContext, + body: &mut Vec, + possibilities: LiteralCases, +) { + let cases = read_expected_literals_cases(ctxt, possibilities); + body.push(item(seq!["match r.next_token(false)? ", block(cases)])); +} + +fn simple_pattern_reader( + ctxt: &mut FunctionContext, + p: &SimplePattern, + in_sequence: bool, + body: &mut Vec, +) -> String { + let dest = ctxt.gentempname(); + match p { + SimplePattern::Any => { + ctxt.define_atom(body, &dest, item("r.demand_next(false)?")); + dest + }, + SimplePattern::Atom { atom_kind: k } => { + let reader = match &**k { + AtomKind::Boolean => "r.next_boolean()?", + AtomKind::Float => "r.next_float()?", + AtomKind::Double => "r.next_double()?", + AtomKind::SignedInteger => "r.next_signedinteger()?", + AtomKind::String => "r.next_str()?.into_owned()", + AtomKind::ByteString => "r.next_bytestring()?.into_owned()", + AtomKind::Symbol => "r.next_symbol()?.into_owned()", + }; + ctxt.define_atom(body, &dest, item(reader.to_owned())); + dest + }, + SimplePattern::Embedded { .. } => { + body.push(item("r.open_embedded()?;")); + ctxt.define_atom(body, &dest, item("r.demand_next(false)?.value().to_embedded()?.clone()")); + body.push(item("r.close_embedded()?;")); + dest + }, + SimplePattern::Lit { value } => { + let f = Box::new(|_ctxt: &mut FunctionContext, _: &'_ mut Vec| ()); + read_expected_literals(ctxt, body, vec![(value.clone(), f)]); + ctxt.define_atom(body, &dest, item("()")); + dest + }, + SimplePattern::Seqof { pattern } => { + if !in_sequence { + body.push(item("r.open_sequence()?;")); + } + let mut inner = Vec::new(); + let item_dest = simple_pattern_reader(ctxt, pattern, false, &mut inner); + inner.push(item(seq![dest.to_owned(), ".push(", + store_wrap(true, &field_type(pattern), &item_dest), ");"])); + ctxt.declare_compound(body, &dest, item("std::vec::Vec::new()")); + body.push(item(seq!["while !(r.close_compound()?) ", block(inner)])); + dest + }, + SimplePattern::Setof { pattern } => { + body.push(item("r.open_set()?;")); + let mut inner = Vec::new(); + let item_dest = simple_pattern_reader(ctxt, pattern, false, &mut inner); + inner.push(item(seq![dest.to_owned(), ".insert(", + store_wrap(true, &field_type(pattern), &item_dest), ");"])); + ctxt.declare_compound(body, &dest, item("preserves::value::Set::new()")); + body.push(item(seq!["while !(r.close_compound()?) ", block(inner)])); + dest + }, + SimplePattern::Dictof { key, value } => { + body.push(item("r.open_dictionary()?;")); + let mut inner = Vec::new(); + let key_dest = simple_pattern_reader(ctxt, key, false, &mut inner); + let value_dest = simple_pattern_reader(ctxt, value, false, &mut inner); + inner.push(item(seq![ + dest.to_owned(), ".insert(", + store_wrap(true, &field_type(key), &key_dest), ", ", + store_wrap(true, &field_type(value), &value_dest), ");"])); + ctxt.declare_compound(body, &dest, item("preserves::value::Map::new()")); + body.push(item(seq!["while !(r.close_compound()?) ", block(inner)])); + dest + }, + SimplePattern::Ref(r) => { + let tf = name![ctxt.m.render_ref(&**r), "deserialize"]; + ctxt.define_atom(body, &dest, item(seq![tf, "(r)?"])); + dest + }, + } +} + +fn named_pattern_reader( + ctxt: &mut FunctionContext, + p: &NamedPattern, + in_sequence: bool, + body: &mut Vec, +) { + match p { + NamedPattern::Anonymous(p) => { + pattern_reader(ctxt, p, in_sequence, body); + }, + NamedPattern::Named(b) => { + let Binding { name, pattern} = &**b; + let dest = simple_pattern_reader(ctxt, pattern, in_sequence, body); + let capture_ty = field_type(pattern); + ctxt.capture(names::render_fieldname(name), capture_ty, dest); + } + } +} + +fn pattern_reader( + ctxt: &mut FunctionContext, + p: &Pattern, + in_sequence: bool, + body: &mut Vec, +) -> Option { + match p { + Pattern::SimplePattern(s) => + Some(simple_pattern_reader(ctxt, s, in_sequence, body)), + Pattern::CompoundPattern(c) => { + match &**c { + CompoundPattern::Rec { label, fields } => { + body.push(item("r.open_record(None)?;")); + named_pattern_reader(ctxt, &**label, false, body); + named_pattern_reader(ctxt, &**fields, true, body); + }, + CompoundPattern::Tuple { patterns } => { + if !in_sequence { + body.push(item("r.open_sequence()?;")); + } + for p in patterns { named_pattern_reader(ctxt, p, false, body); } + body.push(item("r.ensure_complete()?;")); + }, + CompoundPattern::TuplePrefix { fixed, variable } => { + if !in_sequence { + body.push(item("r.open_sequence()?;")); + } + for p in fixed { named_pattern_reader(ctxt, p, false, body); } + named_pattern_reader(ctxt, &promote(variable), true, body); + }, + CompoundPattern::Dict { entries } => { + body.push(item("r.open_dictionary()?;")); + let mut inner = Vec::new(); + body.extend(ctxt.with_indefinite_mode(|ctxt| { + read_expected_literals(ctxt, &mut inner, entries.0.iter().map(move |(key_lit, value_pat)| { + let value_pat = value_pat.clone(); + let f: LiteralContinuation = Box::new( + move |ctxt: &mut FunctionContext, innerinner: &mut Vec| { + named_pattern_reader(ctxt, &promote(&value_pat), false, innerinner); + innerinner.push(item("continue;")); + }); + (key_lit.clone(), f) + }).collect()); + })); + body.push(item(seq!["while !(r.close_compound()?) ", block(inner)])); + } + } + None + }, + } +} diff --git a/implementations/rust/preserves-schema/src/compiler/unparsers.rs b/implementations/rust/preserves-schema/src/compiler/unparsers.rs index 36f7654..2fab59a 100644 --- a/implementations/rust/preserves-schema/src/compiler/unparsers.rs +++ b/implementations/rust/preserves-schema/src/compiler/unparsers.rs @@ -6,7 +6,6 @@ use crate::syntax::block::{Emittable, Item}; use std::cell::Cell; use std::rc::Rc; -use super::codegen::*; use super::context::{ModuleContextMode, ModuleContext, FunctionContext}; use super::names; use super::types::*; @@ -52,6 +51,7 @@ fn normal_src(src: String, is_struct: bool) -> ValueContext { pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) { m.define_function( + n, |mut ctxt| { let mut body = Vec::new(); @@ -70,13 +70,13 @@ pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) { let mut ps = vec![&**pattern_0, &**pattern_1]; ps.extend(pattern_n); let (patpat, vc) = destruct(&mut ctxt, item(names::render_constructor(n)), true, &record_type(&ps)); - push_let(&mut body, item(patpat), item("value")); + body.push(item(seq!["let ", patpat, " = value;"])); body.push(item(seq!["preserves::value::merge(vec!", brackets(ps.iter().map( |p| named_pattern_unparser(&mut ctxt, p, &vc)).collect()), ")"])); } Definition::Pattern(p) => { let (patpat, vc) = destruct(&mut ctxt, item(names::render_constructor(n)), true, &pattern_type(p)); - push_let(&mut body, item(patpat), item("value")); + body.push(item(seq!["let ", patpat, " = value;"])); body.push(pattern_unparser(&mut ctxt, p, &vc)); } } @@ -217,11 +217,11 @@ fn pattern_unparser( CompoundPattern::Rec { label, fields } => { let rtmp = ctxt.gentempname(); let mut body = Vec::new(); - push_let_mut(&mut body, - item(rtmp.to_owned()), - item(seq!["preserves::value::Record(vec![", - named_pattern_unparser(ctxt, label, &normal_none(vc.is_struct)), - "])"])); + let init_expr = item(seq![ + "preserves::value::Record(vec![", + named_pattern_unparser(ctxt, label, &normal_none(vc.is_struct)), + "])"]); + ctxt.declare_compound(&mut body, &rtmp, init_expr); named_pattern_unparser(ctxt, fields, &ValueContext { src: None, sink: ValueSink::Fields(Rc::new(Cell::new(Some(FieldsSink { @@ -247,9 +247,9 @@ fn pattern_unparser( }) }, CompoundPattern::Dict { entries } => { - let dtmp = item(ctxt.gentempname()); + let dtmp = ctxt.gentempname(); let mut body = Vec::new(); - push_let_mut(&mut body, dtmp.clone(), item("preserves::value::Map::new()")); + ctxt.declare_compound(&mut body, &dtmp, item("preserves::value::Map::new()")); for (key_lit, value_pat) in entries.0.iter() { body.push(item(seq![dtmp.clone(), ".insert", parens![ seq![parens![ctxt.m.define_literal(key_lit)], ".clone()"], @@ -271,13 +271,13 @@ fn sequenceify<'a>( ValueContext { sink: ValueSink::Fields(fields_sink), .. } => (**fields_sink).take().unwrap(), _ => { - let rtmp = item(ctxt.gentempname()); + let rtmp = ctxt.gentempname(); let mut body = Vec::new(); - push_let_mut(&mut body, rtmp.clone(), item("vec![]")); + ctxt.declare_compound(&mut body, &rtmp, item("std::vec::Vec::new()")); FieldsSink { finish: item(seq![ "preserves::value::Value::Sequence", parens![rtmp.clone()], ".wrap()"]), - vec_expr: rtmp, + vec_expr: item(rtmp), body: body, } } diff --git a/implementations/rust/preserves-schema/src/gen/mod.rs b/implementations/rust/preserves-schema/src/gen/mod.rs index 1ce7e17..7a50786 100644 --- a/implementations/rust/preserves-schema/src/gen/mod.rs +++ b/implementations/rust/preserves-schema/src/gen/mod.rs @@ -1 +1 @@ -pub mod schema; +pub mod schema; \ No newline at end of file diff --git a/implementations/rust/preserves-schema/src/gen/schema.rs b/implementations/rust/preserves-schema/src/gen/schema.rs index 4eea3d6..153a7f7 100644 --- a/implementations/rust/preserves-schema/src/gen/schema.rs +++ b/implementations/rust/preserves-schema/src/gen/schema.rs @@ -5,6 +5,7 @@ use std::convert::TryFrom; use preserves::value::Domain; use preserves::value::NestedValue; use crate::support as _support; +use _support::Deserialize; mod _any_ { use super::_Any; @@ -173,43 +174,43 @@ pub struct Version; impl preserves::value::Domain for Version {} fn _any_parse_atom_kind_boolean(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_0_BOOLEAN { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_0_BOOLEAN { return Err(_support::ParseError::conformance_error("schema.AtomKind::Boolean")); } let _tmp0 = (); Ok(AtomKind::Boolean) } fn _any_parse_atom_kind_float(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_1_FLOAT { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_1_FLOAT { return Err(_support::ParseError::conformance_error("schema.AtomKind::Float")); } let _tmp0 = (); Ok(AtomKind::Float) } fn _any_parse_atom_kind_double(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_2_DOUBLE { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_2_DOUBLE { return Err(_support::ParseError::conformance_error("schema.AtomKind::Double")); } let _tmp0 = (); Ok(AtomKind::Double) } fn _any_parse_atom_kind_signed_integer(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_3_SIGNED_INTEGER { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_3_SIGNED_INTEGER { return Err(_support::ParseError::conformance_error("schema.AtomKind::SignedInteger")); } let _tmp0 = (); Ok(AtomKind::SignedInteger) } fn _any_parse_atom_kind_string(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_4_STRING { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_4_STRING { return Err(_support::ParseError::conformance_error("schema.AtomKind::String")); } let _tmp0 = (); Ok(AtomKind::String) } fn _any_parse_atom_kind_byte_string(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_5_BYTE_STRING { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_5_BYTE_STRING { return Err(_support::ParseError::conformance_error("schema.AtomKind::ByteString")); } let _tmp0 = (); Ok(AtomKind::ByteString) } fn _any_parse_atom_kind_symbol(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_6_SYMBOL { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_6_SYMBOL { return Err(_support::ParseError::conformance_error("schema.AtomKind::Symbol")); } let _tmp0 = (); Ok(AtomKind::Symbol) } @@ -224,7 +225,7 @@ impl std::convert::TryFrom<&_Any> for AtomKind { if let Ok(r) = _any_parse_atom_kind_string(value) { return Ok(r); } if let Ok(r) = _any_parse_atom_kind_byte_string(value) { return Ok(r); } if let Ok(r) = _any_parse_atom_kind_symbol(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.AtomKind")) } } @@ -242,13 +243,111 @@ impl std::convert::From<&AtomKind> for _Any { } } +fn _any_read_atom_kind_boolean<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "Boolean" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Boolean"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Boolean"))?, + } + let _tmp0 = (); + Ok(AtomKind::Boolean) +} + +fn _any_read_atom_kind_float<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "Float" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Float"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Float"))?, + } + let _tmp0 = (); + Ok(AtomKind::Float) +} + +fn _any_read_atom_kind_double<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "Double" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Double"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Double"))?, + } + let _tmp0 = (); + Ok(AtomKind::Double) +} + +fn _any_read_atom_kind_signed_integer<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "SignedInteger" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::SignedInteger"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::SignedInteger"))?, + } + let _tmp0 = (); + Ok(AtomKind::SignedInteger) +} + +fn _any_read_atom_kind_string<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "String" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::String"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::String"))?, + } + let _tmp0 = (); + Ok(AtomKind::String) +} + +fn _any_read_atom_kind_byte_string<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "ByteString" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::ByteString"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::ByteString"))?, + } + let _tmp0 = (); + Ok(AtomKind::ByteString) +} + +fn _any_read_atom_kind_symbol<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "Symbol" => {} + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Symbol"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.AtomKind::Symbol"))?, + } + let _tmp0 = (); + Ok(AtomKind::Symbol) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for AtomKind { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_atom_kind_boolean(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_atom_kind_float(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_atom_kind_double(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_atom_kind_signed_integer(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_atom_kind_string(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_atom_kind_byte_string(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_atom_kind_symbol(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.AtomKind")) + } +} + impl std::convert::TryFrom<&_Any> for Binding { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_7_NAMED { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_7_NAMED { return Err(_support::ParseError::conformance_error("schema.Binding")); } let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.Binding")); } let _tmp2 = (&_tmp0.fields()[0]).value().to_symbol()?; let _tmp3 = SimplePattern::try_from((&_tmp0.fields()[1]))?; Ok(Binding {name: _tmp2.clone(), pattern: _tmp3}) @@ -267,13 +366,31 @@ impl std::convert::From<&Binding> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Binding { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "named" => {} + _ => return Err(_support::ParseError::conformance_error("schema.Binding"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Binding"))?, + } + let _tmp0 = (); + let _tmp1 = r.next_symbol()?.into_owned(); + let _tmp2 = SimplePattern::deserialize(r)?; + r.ensure_complete()?; + Ok(Binding {name: _tmp1, pattern: _tmp2}) + } +} + impl std::convert::TryFrom<&_Any> for Bundle { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_8_BUNDLE { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_8_BUNDLE { return Err(_support::ParseError::conformance_error("schema.Bundle")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.Bundle")); } let _tmp2 = Modules::try_from((&_tmp0.fields()[0]))?; Ok(Bundle {modules: _tmp2}) } @@ -290,11 +407,28 @@ impl std::convert::From<&Bundle> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Bundle { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "bundle" => {} + _ => return Err(_support::ParseError::conformance_error("schema.Bundle"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Bundle"))?, + } + let _tmp0 = (); + let _tmp1 = Modules::deserialize(r)?; + r.ensure_complete()?; + Ok(Bundle {modules: _tmp1}) + } +} + fn _any_parse_compound_pattern_rec(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_9_REC { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_9_REC { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::rec")); } let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::rec")); } let _tmp2 = NamedPattern::try_from((&_tmp0.fields()[0]))?; let _tmp3 = NamedPattern::try_from((&_tmp0.fields()[1]))?; Ok(CompoundPattern::Rec {label: std::boxed::Box::new(_tmp2), fields: std::boxed::Box::new(_tmp3)}) @@ -302,9 +436,9 @@ fn _any_parse_compound_pattern_rec(value: &_Any) -> std::result::Result std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_10_TUPLE { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_10_TUPLE { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuple")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuple")); } let _tmp3 = (&_tmp0.fields()[0]).value().to_sequence()?; let mut _tmp2 = std::vec::Vec::new(); for _tmp4 in &_tmp3[0..] {let _tmp5 = NamedPattern::try_from(_tmp4)?; _tmp2.push(_tmp5);} @@ -313,9 +447,9 @@ fn _any_parse_compound_pattern_tuple(value: &_Any) -> std::result::Result std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_11_TUPLE_PREFIX { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_11_TUPLE_PREFIX { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuplePrefix")); } let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuplePrefix")); } let _tmp3 = (&_tmp0.fields()[0]).value().to_sequence()?; let mut _tmp2 = std::vec::Vec::new(); for _tmp4 in &_tmp3[0..] {let _tmp5 = NamedPattern::try_from(_tmp4)?; _tmp2.push(_tmp5);} @@ -325,9 +459,9 @@ fn _any_parse_compound_pattern_tuple_prefix(value: &_Any) -> std::result::Result fn _any_parse_compound_pattern_dict(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_12_DICT { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_12_DICT { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::dict")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::dict")); } let _tmp2 = DictionaryEntries::try_from((&_tmp0.fields()[0]))?; Ok(CompoundPattern::Dict {entries: std::boxed::Box::new(_tmp2)}) } @@ -339,7 +473,7 @@ impl std::convert::TryFrom<&_Any> for CompoundPattern { if let Ok(r) = _any_parse_compound_pattern_tuple(value) { return Ok(r); } if let Ok(r) = _any_parse_compound_pattern_tuple_prefix(value) { return Ok(r); } if let Ok(r) = _any_parse_compound_pattern_dict(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.CompoundPattern")) } } @@ -356,7 +490,7 @@ impl std::convert::From<&CompoundPattern> for _Any { let mut _tmp1 = preserves::value::Record(vec![(&*_any_::LIT_10_TUPLE).clone()]); _tmp1.fields_vec_mut().push( { - let mut _tmp2 = vec![]; + let mut _tmp2 = std::vec::Vec::new(); for _tmp3 in _tmp0 {_tmp2.push(_Any::from(_tmp3));} preserves::value::Value::Sequence(_tmp2).wrap() } @@ -367,7 +501,7 @@ impl std::convert::From<&CompoundPattern> for _Any { let mut _tmp2 = preserves::value::Record(vec![(&*_any_::LIT_11_TUPLE_PREFIX).clone()]); _tmp2.fields_vec_mut().push( { - let mut _tmp3 = vec![]; + let mut _tmp3 = std::vec::Vec::new(); for _tmp4 in _tmp0 {_tmp3.push(_Any::from(_tmp4));} preserves::value::Value::Sequence(_tmp3).wrap() } @@ -384,13 +518,90 @@ impl std::convert::From<&CompoundPattern> for _Any { } } +fn _any_read_compound_pattern_rec<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "rec" => {} + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::rec"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::rec"))?, + } + let _tmp0 = (); + let _tmp1 = NamedPattern::deserialize(r)?; + let _tmp2 = NamedPattern::deserialize(r)?; + r.ensure_complete()?; + Ok(CompoundPattern::Rec {label: std::boxed::Box::new(_tmp1), fields: std::boxed::Box::new(_tmp2)}) +} + +fn _any_read_compound_pattern_tuple<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "tuple" => {} + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuple"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuple"))?, + } + let _tmp0 = (); + r.open_sequence()?; + let mut _tmp1 = std::vec::Vec::new(); + while !(r.close_compound()?) {let _tmp2 = NamedPattern::deserialize(r)?; _tmp1.push(_tmp2);} + r.ensure_complete()?; + Ok(CompoundPattern::Tuple {patterns: _tmp1}) +} + +fn _any_read_compound_pattern_tuple_prefix<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "tuplePrefix" => {} + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuplePrefix"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuplePrefix"))?, + } + let _tmp0 = (); + r.open_sequence()?; + let mut _tmp1 = std::vec::Vec::new(); + while !(r.close_compound()?) {let _tmp2 = NamedPattern::deserialize(r)?; _tmp1.push(_tmp2);} + let _tmp3 = NamedSimplePattern::deserialize(r)?; + r.ensure_complete()?; + Ok(CompoundPattern::TuplePrefix {fixed: _tmp1, variable: std::boxed::Box::new(_tmp3)}) +} + +fn _any_read_compound_pattern_dict<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "dict" => {} + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::dict"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.CompoundPattern::dict"))?, + } + let _tmp0 = (); + let _tmp1 = DictionaryEntries::deserialize(r)?; + r.ensure_complete()?; + Ok(CompoundPattern::Dict {entries: std::boxed::Box::new(_tmp1)}) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for CompoundPattern { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_compound_pattern_rec(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_compound_pattern_tuple(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_compound_pattern_tuple_prefix(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_compound_pattern_dict(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.CompoundPattern")) + } +} + fn _any_parse_definition_or(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_13_OR { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_13_OR { return Err(_support::ParseError::conformance_error("schema.Definition::or")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.Definition::or")); } let _tmp2 = (&_tmp0.fields()[0]).value().to_sequence()?; - if _tmp2.len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp2.len() < 2 { return Err(_support::ParseError::conformance_error("schema.Definition::or")); } let _tmp3 = NamedAlternative::try_from((&_tmp2[0]))?; let _tmp4 = NamedAlternative::try_from((&_tmp2[1]))?; let mut _tmp5 = std::vec::Vec::new(); @@ -404,11 +615,11 @@ fn _any_parse_definition_or(value: &_Any) -> std::result::Result std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_14_AND { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_14_AND { return Err(_support::ParseError::conformance_error("schema.Definition::and")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.Definition::and")); } let _tmp2 = (&_tmp0.fields()[0]).value().to_sequence()?; - if _tmp2.len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp2.len() < 2 { return Err(_support::ParseError::conformance_error("schema.Definition::and")); } let _tmp3 = NamedPattern::try_from((&_tmp2[0]))?; let _tmp4 = NamedPattern::try_from((&_tmp2[1]))?; let mut _tmp5 = std::vec::Vec::new(); @@ -431,7 +642,7 @@ impl std::convert::TryFrom<&_Any> for Definition { if let Ok(r) = _any_parse_definition_or(value) { return Ok(r); } if let Ok(r) = _any_parse_definition_and(value) { return Ok(r); } if let Ok(r) = _any_parse_definition_pattern(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.Definition")) } } @@ -442,7 +653,7 @@ impl std::convert::From<&Definition> for _Any { let mut _tmp3 = preserves::value::Record(vec![(&*_any_::LIT_13_OR).clone()]); _tmp3.fields_vec_mut().push( { - let mut _tmp4 = vec![]; + let mut _tmp4 = std::vec::Vec::new(); _tmp4.push(_Any::from(_tmp0.as_ref())); _tmp4.push(_Any::from(_tmp1.as_ref())); for _tmp5 in _tmp2 {_tmp4.push(_Any::from(_tmp5));} @@ -455,7 +666,7 @@ impl std::convert::From<&Definition> for _Any { let mut _tmp3 = preserves::value::Record(vec![(&*_any_::LIT_14_AND).clone()]); _tmp3.fields_vec_mut().push( { - let mut _tmp4 = vec![]; + let mut _tmp4 = std::vec::Vec::new(); _tmp4.push(_Any::from(_tmp0.as_ref())); _tmp4.push(_Any::from(_tmp1.as_ref())); for _tmp5 in _tmp2 {_tmp4.push(_Any::from(_tmp5));} @@ -469,6 +680,67 @@ impl std::convert::From<&Definition> for _Any { } } +fn _any_read_definition_or<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "or" => {} + _ => return Err(_support::ParseError::conformance_error("schema.Definition::or"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Definition::or"))?, + } + let _tmp0 = (); + r.open_sequence()?; + let _tmp1 = NamedAlternative::deserialize(r)?; + let _tmp2 = NamedAlternative::deserialize(r)?; + let mut _tmp3 = std::vec::Vec::new(); + while !(r.close_compound()?) {let _tmp4 = NamedAlternative::deserialize(r)?; _tmp3.push(_tmp4);} + r.ensure_complete()?; + Ok(Definition::Or { + pattern_0: std::boxed::Box::new(_tmp1), + pattern_1: std::boxed::Box::new(_tmp2), + pattern_n: _tmp3 + }) +} + +fn _any_read_definition_and<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "and" => {} + _ => return Err(_support::ParseError::conformance_error("schema.Definition::and"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Definition::and"))?, + } + let _tmp0 = (); + r.open_sequence()?; + let _tmp1 = NamedPattern::deserialize(r)?; + let _tmp2 = NamedPattern::deserialize(r)?; + let mut _tmp3 = std::vec::Vec::new(); + while !(r.close_compound()?) {let _tmp4 = NamedPattern::deserialize(r)?; _tmp3.push(_tmp4);} + r.ensure_complete()?; + Ok(Definition::And { + pattern_0: std::boxed::Box::new(_tmp1), + pattern_1: std::boxed::Box::new(_tmp2), + pattern_n: _tmp3 + }) +} + +fn _any_read_definition_pattern<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = Pattern::deserialize(r)?; + Ok(Definition::Pattern(std::boxed::Box::new(_tmp0))) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Definition { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_definition_or(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_definition_and(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_definition_pattern(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.Definition")) + } +} + impl std::convert::TryFrom<&_Any> for Definitions { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { @@ -489,6 +761,19 @@ impl std::convert::From<&Definitions> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Definitions { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_dictionary()?; + let mut _tmp0 = preserves::value::Map::new(); + while !(r.close_compound()?) { + let _tmp1 = r.next_symbol()?.into_owned(); + let _tmp2 = Definition::deserialize(r)?; + _tmp0.insert(_tmp1, _tmp2); + } + Ok(Definitions(_tmp0)) + } +} + impl std::convert::TryFrom<&_Any> for DictionaryEntries { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { @@ -509,13 +794,26 @@ impl std::convert::From<&DictionaryEntries> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for DictionaryEntries { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_dictionary()?; + let mut _tmp0 = preserves::value::Map::new(); + while !(r.close_compound()?) { + let _tmp1 = r.demand_next(false)?; + let _tmp2 = NamedSimplePattern::deserialize(r)?; + _tmp0.insert(_tmp1, _tmp2); + } + Ok(DictionaryEntries(_tmp0)) + } +} + fn _any_parse_embedded_type_name_ref(value: &_Any) -> std::result::Result { let _tmp0 = Ref::try_from(value)?; Ok(EmbeddedTypeName::Ref(std::boxed::Box::new(_tmp0))) } fn _any_parse_embedded_type_name_false(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_15_FALSE { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_15_FALSE { return Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName::false")); } let _tmp0 = (); Ok(EmbeddedTypeName::False) } @@ -525,7 +823,7 @@ impl std::convert::TryFrom<&_Any> for EmbeddedTypeName { fn try_from(value: &_Any) -> std::result::Result { if let Ok(r) = _any_parse_embedded_type_name_ref(value) { return Ok(r); } if let Ok(r) = _any_parse_embedded_type_name_false(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName")) } } @@ -538,6 +836,32 @@ impl std::convert::From<&EmbeddedTypeName> for _Any { } } +fn _any_read_embedded_type_name_ref<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = Ref::deserialize(r)?; + Ok(EmbeddedTypeName::Ref(std::boxed::Box::new(_tmp0))) +} + +fn _any_read_embedded_type_name_false<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Boolean(w) if !*w => {} + _ => return Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName::false"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName::false"))?, + } + let _tmp0 = (); + Ok(EmbeddedTypeName::False) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for EmbeddedTypeName { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_embedded_type_name_ref(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_embedded_type_name_false(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName")) + } +} + impl std::convert::TryFrom<&_Any> for ModulePath { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { @@ -552,13 +876,22 @@ impl std::convert::From<&ModulePath> for _Any { fn from(value: &ModulePath) -> Self { let ModulePath(_tmp0) = value; { - let mut _tmp1 = vec![]; + let mut _tmp1 = std::vec::Vec::new(); for _tmp2 in _tmp0 {_tmp1.push(preserves::value::Value::symbol(_tmp2).wrap());} preserves::value::Value::Sequence(_tmp1).wrap() } } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for ModulePath { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_sequence()?; + let mut _tmp0 = std::vec::Vec::new(); + while !(r.close_compound()?) {let _tmp1 = r.next_symbol()?.into_owned(); _tmp0.push(_tmp1);} + Ok(ModulePath(_tmp0)) + } +} + impl std::convert::TryFrom<&_Any> for Modules { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { @@ -579,11 +912,24 @@ impl std::convert::From<&Modules> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Modules { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_dictionary()?; + let mut _tmp0 = preserves::value::Map::new(); + while !(r.close_compound()?) { + let _tmp1 = ModulePath::deserialize(r)?; + let _tmp2 = Schema::deserialize(r)?; + _tmp0.insert(_tmp1, _tmp2); + } + Ok(Modules(_tmp0)) + } +} + impl std::convert::TryFrom<&_Any> for NamedAlternative { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_sequence()?; - if _tmp0.len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.len() < 2 { return Err(_support::ParseError::conformance_error("schema.NamedAlternative")); } let _tmp1 = (&_tmp0[0]).value().to_string()?; let _tmp2 = Pattern::try_from((&_tmp0[1]))?; Ok(NamedAlternative {variant_label: _tmp1.clone(), pattern: _tmp2}) @@ -594,7 +940,7 @@ impl std::convert::From<&NamedAlternative> for _Any { fn from(value: &NamedAlternative) -> Self { let NamedAlternative {variant_label: _tmp0, pattern: _tmp1} = value; { - let mut _tmp2 = vec![]; + let mut _tmp2 = std::vec::Vec::new(); _tmp2.push(preserves::value::Value::from(_tmp0).wrap()); _tmp2.push(_Any::from(_tmp1)); preserves::value::Value::Sequence(_tmp2).wrap() @@ -602,6 +948,16 @@ impl std::convert::From<&NamedAlternative> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for NamedAlternative { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_sequence()?; + let _tmp0 = r.next_str()?.into_owned(); + let _tmp1 = Pattern::deserialize(r)?; + r.ensure_complete()?; + Ok(NamedAlternative {variant_label: _tmp0, pattern: _tmp1}) + } +} + fn _any_parse_named_pattern_named(value: &_Any) -> std::result::Result { let _tmp0 = Binding::try_from(value)?; Ok(NamedPattern::Named(std::boxed::Box::new(_tmp0))) @@ -617,7 +973,7 @@ impl std::convert::TryFrom<&_Any> for NamedPattern { fn try_from(value: &_Any) -> std::result::Result { if let Ok(r) = _any_parse_named_pattern_named(value) { return Ok(r); } if let Ok(r) = _any_parse_named_pattern_anonymous(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.NamedPattern")) } } @@ -630,6 +986,25 @@ impl std::convert::From<&NamedPattern> for _Any { } } +fn _any_read_named_pattern_named<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = Binding::deserialize(r)?; + Ok(NamedPattern::Named(std::boxed::Box::new(_tmp0))) +} + +fn _any_read_named_pattern_anonymous<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = Pattern::deserialize(r)?; + Ok(NamedPattern::Anonymous(std::boxed::Box::new(_tmp0))) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for NamedPattern { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_named_pattern_named(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_named_pattern_anonymous(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.NamedPattern")) + } +} + fn _any_parse_named_simple_pattern_named(value: &_Any) -> std::result::Result { let _tmp0 = Binding::try_from(value)?; Ok(NamedSimplePattern::Named(std::boxed::Box::new(_tmp0))) @@ -645,7 +1020,7 @@ impl std::convert::TryFrom<&_Any> for NamedSimplePattern { fn try_from(value: &_Any) -> std::result::Result { if let Ok(r) = _any_parse_named_simple_pattern_named(value) { return Ok(r); } if let Ok(r) = _any_parse_named_simple_pattern_anonymous(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.NamedSimplePattern")) } } @@ -658,6 +1033,25 @@ impl std::convert::From<&NamedSimplePattern> for _Any { } } +fn _any_read_named_simple_pattern_named<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = Binding::deserialize(r)?; + Ok(NamedSimplePattern::Named(std::boxed::Box::new(_tmp0))) +} + +fn _any_read_named_simple_pattern_anonymous<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = SimplePattern::deserialize(r)?; + Ok(NamedSimplePattern::Anonymous(std::boxed::Box::new(_tmp0))) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for NamedSimplePattern { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_named_simple_pattern_named(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_named_simple_pattern_anonymous(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.NamedSimplePattern")) + } +} + fn _any_parse_pattern_simple_pattern(value: &_Any) -> std::result::Result { let _tmp0 = SimplePattern::try_from(value)?; Ok(Pattern::SimplePattern(std::boxed::Box::new(_tmp0))) @@ -673,7 +1067,7 @@ impl std::convert::TryFrom<&_Any> for Pattern { fn try_from(value: &_Any) -> std::result::Result { if let Ok(r) = _any_parse_pattern_simple_pattern(value) { return Ok(r); } if let Ok(r) = _any_parse_pattern_compound_pattern(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.Pattern")) } } @@ -686,13 +1080,32 @@ impl std::convert::From<&Pattern> for _Any { } } +fn _any_read_pattern_simple_pattern<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = SimplePattern::deserialize(r)?; + Ok(Pattern::SimplePattern(std::boxed::Box::new(_tmp0))) +} + +fn _any_read_pattern_compound_pattern<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = CompoundPattern::deserialize(r)?; + Ok(Pattern::CompoundPattern(std::boxed::Box::new(_tmp0))) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Pattern { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_pattern_simple_pattern(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_pattern_compound_pattern(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.Pattern")) + } +} + impl std::convert::TryFrom<&_Any> for Ref { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_16_REF { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_16_REF { return Err(_support::ParseError::conformance_error("schema.Ref")); } let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.Ref")); } let _tmp2 = ModulePath::try_from((&_tmp0.fields()[0]))?; let _tmp3 = (&_tmp0.fields()[1]).value().to_symbol()?; Ok(Ref {module: _tmp2, name: _tmp3.clone()}) @@ -711,19 +1124,37 @@ impl std::convert::From<&Ref> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Ref { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "ref" => {} + _ => return Err(_support::ParseError::conformance_error("schema.Ref"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Ref"))?, + } + let _tmp0 = (); + let _tmp1 = ModulePath::deserialize(r)?; + let _tmp2 = r.next_symbol()?.into_owned(); + r.ensure_complete()?; + Ok(Ref {module: _tmp1, name: _tmp2}) + } +} + impl std::convert::TryFrom<&_Any> for Schema { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_17_SCHEMA { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_17_SCHEMA { return Err(_support::ParseError::conformance_error("schema.Schema")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.Schema")); } let _tmp2 = (&_tmp0.fields()[0]).value().to_dictionary()?; - let _tmp3 = _tmp2.get(&*_any_::LIT_18_DEFINITIONS).ok_or(_support::ParseError::ConformanceError)?; + let _tmp3 = _tmp2.get(&*_any_::LIT_18_DEFINITIONS).ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?; let _tmp4 = Definitions::try_from(_tmp3)?; - let _tmp5 = _tmp2.get(&*_any_::LIT_19_EMBEDDED_TYPE).ok_or(_support::ParseError::ConformanceError)?; + let _tmp5 = _tmp2.get(&*_any_::LIT_19_EMBEDDED_TYPE).ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?; let _tmp6 = EmbeddedTypeName::try_from(_tmp5)?; - let _tmp7 = _tmp2.get(&*_any_::LIT_20_VERSION).ok_or(_support::ParseError::ConformanceError)?; + let _tmp7 = _tmp2.get(&*_any_::LIT_20_VERSION).ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?; let _tmp8 = Version::try_from(_tmp7)?; Ok(Schema {definitions: _tmp4, embedded_type: _tmp6, version: _tmp8}) } @@ -748,62 +1179,97 @@ impl std::convert::From<&Schema> for _Any { } } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Schema { + fn deserialize(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "schema" => {} + _ => return Err(_support::ParseError::conformance_error("schema.Schema"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Schema"))?, + } + let _tmp0 = (); + r.open_dictionary()?; + let mut _tmp1 = None; + let mut _tmp2 = None; + let mut _tmp3 = None; + while !(r.close_compound()?) { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "definitions" => {_tmp1 = Some(Definitions::deserialize(r)?); continue;} + preserves::value::Value::Symbol(w) if w == "embeddedType" => {_tmp2 = Some(EmbeddedTypeName::deserialize(r)?); continue;} + preserves::value::Value::Symbol(w) if w == "version" => {_tmp3 = Some(Version::deserialize(r)?); continue;} + _ => return Err(_support::ParseError::conformance_error("schema.Schema"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Schema"))?, + } + } + r.ensure_complete()?; + Ok(Schema { + definitions: _tmp1.ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?, + embedded_type: _tmp2.ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?, + version: _tmp3.ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))? + }) + } +} + fn _any_parse_simple_pattern_any(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_21_ANY { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_21_ANY { return Err(_support::ParseError::conformance_error("schema.SimplePattern::any")); } let _tmp0 = (); Ok(SimplePattern::Any) } fn _any_parse_simple_pattern_atom(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_22_ATOM { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_22_ATOM { return Err(_support::ParseError::conformance_error("schema.SimplePattern::atom")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::atom")); } let _tmp2 = AtomKind::try_from((&_tmp0.fields()[0]))?; Ok(SimplePattern::Atom {atom_kind: std::boxed::Box::new(_tmp2)}) } fn _any_parse_simple_pattern_embedded(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_23_EMBEDDED { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_23_EMBEDDED { return Err(_support::ParseError::conformance_error("schema.SimplePattern::embedded")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::embedded")); } let _tmp2 = SimplePattern::try_from((&_tmp0.fields()[0]))?; Ok(SimplePattern::Embedded {interface: std::boxed::Box::new(_tmp2)}) } fn _any_parse_simple_pattern_lit(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_24_LIT { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_24_LIT { return Err(_support::ParseError::conformance_error("schema.SimplePattern::lit")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::lit")); } let _tmp2 = (&_tmp0.fields()[0]); Ok(SimplePattern::Lit {value: _tmp2.clone()}) } fn _any_parse_simple_pattern_seqof(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_25_SEQOF { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_25_SEQOF { return Err(_support::ParseError::conformance_error("schema.SimplePattern::seqof")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::seqof")); } let _tmp2 = SimplePattern::try_from((&_tmp0.fields()[0]))?; Ok(SimplePattern::Seqof {pattern: std::boxed::Box::new(_tmp2)}) } fn _any_parse_simple_pattern_setof(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_26_SETOF { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_26_SETOF { return Err(_support::ParseError::conformance_error("schema.SimplePattern::setof")); } let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::setof")); } let _tmp2 = SimplePattern::try_from((&_tmp0.fields()[0]))?; Ok(SimplePattern::Setof {pattern: std::boxed::Box::new(_tmp2)}) } fn _any_parse_simple_pattern_dictof(value: &_Any) -> std::result::Result { let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &*_any_::LIT_27_DICTOF { return Err(_support::ParseError::ConformanceError); } + if _tmp0.label() != &*_any_::LIT_27_DICTOF { return Err(_support::ParseError::conformance_error("schema.SimplePattern::dictof")); } let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::ConformanceError); } + if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::dictof")); } let _tmp2 = SimplePattern::try_from((&_tmp0.fields()[0]))?; let _tmp3 = SimplePattern::try_from((&_tmp0.fields()[1]))?; Ok(SimplePattern::Dictof {key: std::boxed::Box::new(_tmp2), value: std::boxed::Box::new(_tmp3)}) @@ -825,7 +1291,7 @@ impl std::convert::TryFrom<&_Any> for SimplePattern { if let Ok(r) = _any_parse_simple_pattern_setof(value) { return Ok(r); } if let Ok(r) = _any_parse_simple_pattern_dictof(value) { return Ok(r); } if let Ok(r) = _any_parse_simple_pattern_ref(value) { return Ok(r); } - Err(_support::ParseError::ConformanceError) + Err(_support::ParseError::conformance_error("schema.SimplePattern")) } } @@ -869,10 +1335,133 @@ impl std::convert::From<&SimplePattern> for _Any { } } +fn _any_read_simple_pattern_any<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "any" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::any"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::any"))?, + } + let _tmp0 = (); + Ok(SimplePattern::Any) +} + +fn _any_read_simple_pattern_atom<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "atom" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::atom"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::atom"))?, + } + let _tmp0 = (); + let _tmp1 = AtomKind::deserialize(r)?; + r.ensure_complete()?; + Ok(SimplePattern::Atom {atom_kind: std::boxed::Box::new(_tmp1)}) +} + +fn _any_read_simple_pattern_embedded<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "embedded" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::embedded"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::embedded"))?, + } + let _tmp0 = (); + let _tmp1 = SimplePattern::deserialize(r)?; + r.ensure_complete()?; + Ok(SimplePattern::Embedded {interface: std::boxed::Box::new(_tmp1)}) +} + +fn _any_read_simple_pattern_lit<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "lit" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::lit"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::lit"))?, + } + let _tmp0 = (); + let _tmp1 = r.demand_next(false)?; + r.ensure_complete()?; + Ok(SimplePattern::Lit {value: _tmp1}) +} + +fn _any_read_simple_pattern_seqof<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "seqof" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::seqof"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::seqof"))?, + } + let _tmp0 = (); + let _tmp1 = SimplePattern::deserialize(r)?; + r.ensure_complete()?; + Ok(SimplePattern::Seqof {pattern: std::boxed::Box::new(_tmp1)}) +} + +fn _any_read_simple_pattern_setof<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "setof" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::setof"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::setof"))?, + } + let _tmp0 = (); + let _tmp1 = SimplePattern::deserialize(r)?; + r.ensure_complete()?; + Ok(SimplePattern::Setof {pattern: std::boxed::Box::new(_tmp1)}) +} + +fn _any_read_simple_pattern_dictof<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + r.open_record(None)?; + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::Symbol(w) if w == "dictof" => {} + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::dictof"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.SimplePattern::dictof"))?, + } + let _tmp0 = (); + let _tmp1 = SimplePattern::deserialize(r)?; + let _tmp2 = SimplePattern::deserialize(r)?; + r.ensure_complete()?; + Ok(SimplePattern::Dictof {key: std::boxed::Box::new(_tmp1), value: std::boxed::Box::new(_tmp2)}) +} + +fn _any_read_simple_pattern_ref<'de, R: _support::Reader<'de, _Ptr, _Any>>(r: &mut R) -> std::result::Result { + let _tmp0 = Ref::deserialize(r)?; + Ok(SimplePattern::Ref(std::boxed::Box::new(_tmp0))) +} + +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for SimplePattern { + fn deserialize(r: &mut R) -> std::result::Result { + let _mark = r.mark()?; + match _any_read_simple_pattern_any(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_atom(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_embedded(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_lit(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_seqof(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_setof(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_dictof(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + match _any_read_simple_pattern_ref(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } + Err(_support::ParseError::conformance_error("schema.SimplePattern")) + } +} + impl std::convert::TryFrom<&_Any> for Version { type Error = _support::ParseError; fn try_from(value: &_Any) -> std::result::Result { - if value != &*_any_::LIT_28_1 { return Err(_support::ParseError::ConformanceError); } + if value != &*_any_::LIT_28_1 { return Err(_support::ParseError::conformance_error("schema.Version")); } let _tmp0 = (); Ok(Version) } @@ -882,3 +1471,16 @@ impl std::convert::From<&Version> for _Any { fn from(value: &Version) -> Self {let Version = value; (&*_any_::LIT_28_1).clone()} } +impl<'de, R: _support::Reader<'de, _Ptr, _Any>> _support::Deserialize<'de, _Ptr, _Any, R> for Version { + fn deserialize(r: &mut R) -> std::result::Result { + match r.next_token(false)? { + preserves::value::Token::Atom(v) => match v.value() { + preserves::value::Value::SignedInteger(w) if *w == (1).into() => {} + _ => return Err(_support::ParseError::conformance_error("schema.Version"))?, + } + _ => return Err(_support::ParseError::conformance_error("schema.Version"))?, + } + let _tmp0 = (); + Ok(Version) + } +} diff --git a/implementations/rust/preserves-schema/src/support/mod.rs b/implementations/rust/preserves-schema/src/support/mod.rs index bddfd3e..0f2bb22 100644 --- a/implementations/rust/preserves-schema/src/support/mod.rs +++ b/implementations/rust/preserves-schema/src/support/mod.rs @@ -1,5 +1,7 @@ pub use lazy_static::lazy_static; +pub use preserves::value::Reader; + use preserves::value::ArcValue; use preserves::value::Domain; use preserves::value::Embeddable; @@ -13,6 +15,15 @@ use std::convert::TryFrom; use std::io; use std::sync::Arc; +use thiserror::Error; + +pub trait Deserialize<'de, D: Embeddable, N: NestedValue, R: Reader<'de, D, N>> +where + Self: Sized +{ + fn deserialize(r: &mut R) -> Result; +} + pub fn decode_lit>(bs: &[u8]) -> io::Result { preserves::value::packed::from_bytes(bs, NoEmbeddedDomainCodec) } @@ -36,46 +47,35 @@ where &mut |d| Ok(Value::Embedded(IOValue::from(d)))).unwrap() } -#[derive(Debug)] +#[derive(Error, Debug)] pub enum ParseError { - ConformanceError, - IO(io::Error), - Preserves(preserves::error::Error), + #[error("Input not conformant with Schema: {0}")] + ConformanceError(&'static str), + #[error(transparent)] + Preserves(#[from] preserves::error::Error), } -const INPUT_NOT_CONFORMANT: &str = "Input not conformant with Schema"; - -impl std::fmt::Display for ParseError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - ParseError::ConformanceError => write!(f, "{}", INPUT_NOT_CONFORMANT), - ParseError::IO(e) => e.fmt(f), - ParseError::Preserves(e) => e.fmt(f), - } - } -} - -impl std::error::Error for ParseError {} - impl From for ParseError { fn from(v: io::Error) -> Self { - ParseError::IO(v) - } -} - -impl From for ParseError { - fn from(v: preserves::error::Error) -> Self { - ParseError::Preserves(v) + preserves::error::Error::from(v).into() } } impl From for io::Error { fn from(v: ParseError) -> Self { match v { - ParseError::ConformanceError => - io::Error::new(io::ErrorKind::InvalidData, INPUT_NOT_CONFORMANT), - ParseError::IO(e) => e, + ParseError::ConformanceError(_) => io::Error::new(io::ErrorKind::InvalidData, v), ParseError::Preserves(e) => e.into(), } } } + +impl ParseError { + pub fn conformance_error(context: &'static str) -> Self { + ParseError::ConformanceError(context) + } + + pub fn is_conformance_error(&self) -> bool { + return if let ParseError::ConformanceError(_) = self { true } else { false } + } +} diff --git a/implementations/rust/preserves-schema/src/syntax/block.rs b/implementations/rust/preserves-schema/src/syntax/block.rs index 25ed061..f5f58a0 100644 --- a/implementations/rust/preserves-schema/src/syntax/block.rs +++ b/implementations/rust/preserves-schema/src/syntax/block.rs @@ -1,3 +1,4 @@ +use std::fmt::Write; use std::str; pub const DEFAULT_WIDTH: usize = 80; @@ -171,6 +172,39 @@ impl std::fmt::Debug for Grouping { //--------------------------------------------------------------------------- +pub fn escape_string(s: &str) -> String { + let mut buf = String::new(); + buf.push('"'); + for c in s.chars() { + match c { + '\\' => buf.push_str("\\\\"), + '"' => buf.push_str("\\\""), + _ if c >= ' ' && c <= '~' => buf.push(c), + _ => write!(&mut buf, "\\u{{{:x}}}", c as i32).expect("no IO errors building a string"), + } + } + buf.push('"'); + buf +} + +pub fn escape_bytes(bs: &[u8]) -> String { + let mut buf = String::new(); + buf.push_str("b\""); + for b in bs { + let c = *b as char; + match c { + '\\' => buf.push_str("\\\\"), + '"' => buf.push_str("\\\""), + _ if c >= ' ' && c <= '~' => buf.push(c), + _ => write!(&mut buf, "\\x{{{:02x}}}", b).expect("no IO errors building a string"), + } + } + buf.push('"'); + buf +} + +//--------------------------------------------------------------------------- + pub mod constructors { use super::Sequence; use super::Grouping; diff --git a/implementations/rust/preserves/src/de.rs b/implementations/rust/preserves/src/de.rs index 9faca1d..f2702d0 100644 --- a/implementations/rust/preserves/src/de.rs +++ b/implementations/rust/preserves/src/de.rs @@ -2,6 +2,7 @@ use serde::Deserialize; use serde::de::{Visitor, SeqAccess, MapAccess, EnumAccess, VariantAccess, DeserializeSeed}; use std::borrow::Cow; +use std::io; use std::marker::PhantomData; use super::value::{IOValue, IOValueDomainCodec, PackedReader}; @@ -24,7 +25,7 @@ where from_reader(&mut PackedReader::new(&mut BytesBinarySource::new(bytes), IOValueDomainCodec)) } -pub fn from_read<'de, 'r, IOR: std::io::Read, T>(read: &'r mut IOR) -> +pub fn from_read<'de, 'r, IOR: io::Read + io::Seek, T>(read: &'r mut IOR) -> Result where T: Deserialize<'de> diff --git a/implementations/rust/preserves/src/value/mod.rs b/implementations/rust/preserves/src/value/mod.rs index 7d64231..dacdf77 100644 --- a/implementations/rust/preserves/src/value/mod.rs +++ b/implementations/rust/preserves/src/value/mod.rs @@ -21,8 +21,11 @@ pub use reader::BytesBinarySource; pub use reader::ConfiguredReader; pub use reader::IOBinarySource; pub use reader::Reader; +pub use reader::Token; pub use repr::AnnotatedValue; pub use repr::ArcValue; +pub use repr::AtomClass; +pub use repr::CompoundClass; pub use repr::Domain; pub use repr::Double; pub use repr::Embeddable; @@ -36,6 +39,7 @@ pub use repr::Record; pub use repr::Set; pub use repr::UnwrappedIOValue; pub use repr::Value; +pub use repr::ValueClass; pub use ser::Serializer; pub use ser::to_value; pub use writer::Writer; diff --git a/implementations/rust/preserves/src/value/packed/reader.rs b/implementations/rust/preserves/src/value/packed/reader.rs index 24adc8e..749ab65 100644 --- a/implementations/rust/preserves/src/value/packed/reader.rs +++ b/implementations/rust/preserves/src/value/packed/reader.rs @@ -11,6 +11,7 @@ use std::marker::PhantomData; use super::constants::Tag; use super::super::{ + CompoundClass, DomainDecode, Embeddable, Map, @@ -20,6 +21,7 @@ use super::super::{ Value, reader::{ + Token, BinarySource, ConfiguredReader, Reader, @@ -39,6 +41,13 @@ impl<'de, 'src, D: Embeddable, N: NestedValue, Dec: DomainDecode, S: Binar BinarySource<'de> for PackedReader<'de, 'src, D, N, Dec, S> { + type Mark = S::Mark; + fn mark(&mut self) -> io::Result { + self.source.mark() + } + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { + self.source.restore(mark) + } fn skip(&mut self) -> io::Result<()> { self.source.skip() } @@ -222,6 +231,24 @@ impl<'de, 'src, D: Embeddable, N: NestedValue, Dec: DomainDecode, S: Binar _ => Err(self.expected(ExpectedKind::SignedInteger)) } } + + fn gather_annotations(&mut self) -> io::Result> { + let mut annotations = vec![self.demand_next(true)?]; + while Tag::try_from(self.peek()?)? == Tag::Annotation { + self.skip()?; + annotations.push(self.demand_next(true)?); + } + Ok(annotations) + } + + fn skip_annotations(&mut self) -> io::Result<()> { + self.skip_value()?; + while Tag::try_from(self.peek()?)? == Tag::Annotation { + self.skip()?; + self.skip_value()?; + } + Ok(()) + } } impl<'de, 'src, D: Embeddable, N: NestedValue, Dec: DomainDecode, S: BinarySource<'de>> @@ -249,20 +276,12 @@ impl<'de, 'src, D: Embeddable, N: NestedValue, Dec: DomainDecode, S: Binar } Tag::Annotation => { if read_annotations { - let mut annotations = vec![self.demand_next(read_annotations)?]; - while Tag::try_from(self.peek()?)? == Tag::Annotation { - self.skip()?; - annotations.push(self.demand_next(read_annotations)?); - } + let mut annotations = self.gather_annotations()?; let (existing_annotations, v) = self.demand_next(read_annotations)?.pieces(); annotations.extend_from_slice(existing_annotations.slice()); N::wrap(Annotations::new(Some(annotations)), v) } else { - self.skip_value()?; - while Tag::try_from(self.peek()?)? == Tag::Annotation { - self.skip()?; - self.skip_value()?; - } + self.skip_annotations()?; self.demand_next(read_annotations)? } } @@ -373,6 +392,64 @@ impl<'de, 'src, D: Embeddable, N: NestedValue, Dec: DomainDecode, S: Binar Ok(()) } + type Mark = S::Mark; + + fn mark(&mut self) -> io::Result { + self.source.mark() + } + + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { + self.source.restore(mark) + } + + fn next_token(&mut self, read_embedded_annotations: bool) -> io::Result> { + loop { + return Ok(match Tag::try_from(self.peek()?)? { + Tag::Embedded => { + self.skip()?; + Token::Embedded(self.decode_embedded.decode_embedded( + self.source, + read_embedded_annotations)?) + } + Tag::False | + Tag::True | + Tag::Float | + Tag::Double | + Tag::SmallInteger(_) | + Tag::MediumInteger(_) | + Tag::SignedInteger | + Tag::String | + Tag::ByteString | + Tag::Symbol => + Token::Atom(self.demand_next(false)?), + + Tag::Record => { self.skip()?; Token::Compound(CompoundClass::Record) } + Tag::Sequence => { self.skip()?; Token::Compound(CompoundClass::Sequence) } + Tag::Set => { self.skip()?; Token::Compound(CompoundClass::Set) } + Tag::Dictionary => { self.skip()?; Token::Compound(CompoundClass::Dictionary) } + + Tag::End => { self.skip()?; Token::End } + + Tag::Annotation => { + self.skip()?; + self.skip_annotations()?; + continue + } + }) + } + } + + fn next_annotations_and_token(&mut self) -> io::Result<(Vec, Token)> { + match Tag::try_from(self.peek()?)? { + Tag::Annotation => { + self.skip()?; + let annotations = self.gather_annotations()?; + Ok((annotations, self.next_token(true)?)) + } + _ => Ok((Vec::new(), self.next_token(true)?)), + } + } + fn next_boolean(&mut self) -> ReaderResult { match self.peek_next_nonannotation_tag()? { Tag::False => { self.skip()?; Ok(false) } @@ -381,6 +458,26 @@ impl<'de, 'src, D: Embeddable, N: NestedValue, Dec: DomainDecode, S: Binar } } + fn next_signedinteger(&mut self) -> ReaderResult { + let tag = self.peek_next_nonannotation_tag()?; + match tag { + Tag::SmallInteger(v) => { + self.skip()?; + Ok(SignedInteger::from(v as i32)) + } + Tag::MediumInteger(count) => { + self.skip()?; + Ok(self.read_signed_integer(count.into())?) + } + Tag::SignedInteger => { + self.skip()?; + let count = self.varint()?; + Ok(self.read_signed_integer(count)?) + } + _ => Err(self.expected(ExpectedKind::SignedInteger)) + } + } + fn next_i8(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i8()) } fn next_i16(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i16()) } fn next_i32(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i32()) } diff --git a/implementations/rust/preserves/src/value/reader.rs b/implementations/rust/preserves/src/value/reader.rs index 3c05f24..b0d659e 100644 --- a/implementations/rust/preserves/src/value/reader.rs +++ b/implementations/rust/preserves/src/value/reader.rs @@ -4,10 +4,25 @@ use std::borrow::Cow; use std::io; use std::marker::PhantomData; -use super::{DomainDecode, Embeddable, IOValue, IOValueDomainCodec, NestedValue}; +use super::DomainDecode; +use super::Double; +use super::Embeddable; +use super::Float; +use super::IOValue; +use super::IOValueDomainCodec; +use super::NestedValue; +use super::CompoundClass; +use super::signed_integer::SignedInteger; pub type ReaderResult = std::result::Result; +pub enum Token> { + Embedded(D), + Atom(N), + Compound(CompoundClass), + End, +} + pub trait Reader<'de, D: Embeddable, N: NestedValue> { fn next(&mut self, read_annotations: bool) -> io::Result>; fn open_record(&mut self, arity: Option) -> ReaderResult<()>; @@ -19,6 +34,13 @@ pub trait Reader<'de, D: Embeddable, N: NestedValue> { fn open_embedded(&mut self) -> ReaderResult<()>; fn close_embedded(&mut self) -> ReaderResult<()>; + type Mark; + fn mark(&mut self) -> io::Result; + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()>; + + fn next_token(&mut self, read_embedded_annotations: bool) -> io::Result>; + fn next_annotations_and_token(&mut self) -> io::Result<(Vec, Token)>; + //--------------------------------------------------------------------------- fn skip_value(&mut self) -> io::Result<()> { @@ -31,7 +53,22 @@ pub trait Reader<'de, D: Embeddable, N: NestedValue> { self.next(read_annotations)?.ok_or_else(io_eof) } - fn next_boolean(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_boolean() } + fn next_boolean(&mut self) -> ReaderResult { + self.demand_next(false)?.value().to_boolean() + } + + fn next_float(&mut self) -> ReaderResult { + Ok(self.demand_next(false)?.value().to_float()?.to_owned()) + } + + fn next_double(&mut self) -> ReaderResult { + Ok(self.demand_next(false)?.value().to_double()?.to_owned()) + } + + fn next_signedinteger(&mut self) -> ReaderResult { + Ok(self.demand_next(false)?.value().to_signedinteger()?.to_owned()) + } + fn next_i8(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_i8() } fn next_u8(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_u8() } fn next_i16(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_i16() } @@ -156,10 +193,32 @@ impl<'r, 'de, D: Embeddable, N: NestedValue, R: Reader<'de, D, N>> fn close_embedded(&mut self) -> ReaderResult<()> { (*self).close_embedded() } + + type Mark = R::Mark; + + fn mark(&mut self) -> io::Result { + (*self).mark() + } + + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { + (*self).restore(mark) + } + + fn next_token(&mut self, read_embedded_annotations: bool) -> io::Result> { + (*self).next_token(read_embedded_annotations) + } + + fn next_annotations_and_token(&mut self) -> io::Result<(Vec, Token)> { + (*self).next_annotations_and_token() + } } pub trait BinarySource<'de>: Sized { + type Mark; + fn mark(&mut self) -> io::Result; + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()>; + fn skip(&mut self) -> io::Result<()>; fn peek(&mut self) -> io::Result; fn readbytes(&mut self, count: usize) -> io::Result>; @@ -179,18 +238,30 @@ pub trait BinarySource<'de>: Sized { } } -pub struct IOBinarySource<'a, R: io::Read> { +pub struct IOBinarySource<'a, R: io::Read + io::Seek> { pub read: &'a mut R, pub buf: Option, } -impl<'a, R: io::Read> IOBinarySource<'a, R> { +impl<'a, R: io::Read + io::Seek> IOBinarySource<'a, R> { pub fn new(read: &'a mut R) -> Self { IOBinarySource { read, buf: None } } } -impl<'de, 'a, R: io::Read> BinarySource<'de> for IOBinarySource<'a, R> { +impl<'de, 'a, R: io::Read + io::Seek> BinarySource<'de> for IOBinarySource<'a, R> { + type Mark = u64; + + fn mark(&mut self) -> io::Result { + Ok(self.read.stream_position()? - (if self.buf.is_some() { 1 } else { 0 })) + } + + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { + self.read.seek(io::SeekFrom::Start(*mark))?; + self.buf = None; + Ok(()) + } + fn skip(&mut self) -> io::Result<()> { if self.buf.is_none() { unreachable!(); } self.buf = None; @@ -239,6 +310,17 @@ impl<'de> BytesBinarySource<'de> { } impl<'de> BinarySource<'de> for BytesBinarySource<'de> { + type Mark = usize; + + fn mark(&mut self) -> io::Result { + Ok(self.index) + } + + fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { + self.index = *mark; + Ok(()) + } + fn skip(&mut self) -> io::Result<()> { if self.index >= self.bytes.len() { unreachable!(); } self.index += 1; diff --git a/implementations/rust/preserves/src/value/repr.rs b/implementations/rust/preserves/src/value/repr.rs index cfd667f..a1a5b19 100644 --- a/implementations/rust/preserves/src/value/repr.rs +++ b/implementations/rust/preserves/src/value/repr.rs @@ -42,6 +42,10 @@ pub trait NestedValue: Sized + Debug + Clone + Eq + Hash + Ord { fn pieces(self) -> (Annotations, Value); fn value_owned(self) -> Value; + fn value_class(&self) -> ValueClass { + self.value().value_class() + } + fn debug_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for ann in self.annotations().slice() { write!(f, "@{:?} ", ann)?; @@ -85,6 +89,35 @@ pub enum Value where N: NestedValue, D: Embeddable { Embedded(D), } +/// The kinds of `Value` from the specification. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum ValueClass { + Atomic(AtomClass), + Compound(CompoundClass), + Embedded, +} + +/// The kinds of `Atom` from the specification. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum AtomClass { + Boolean, + Float, + Double, + SignedInteger, + String, + ByteString, + Symbol, +} + +/// The kinds of `Compound` from the specification. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum CompoundClass { + Record, + Sequence, + Set, + Dictionary, +} + /// Single-precision IEEE 754 Value #[derive(Clone, Debug)] pub struct Float(pub f32); @@ -299,6 +332,23 @@ impl, D: Embeddable> Value { N::wrap(Annotations::empty(), self) } + fn value_class(&self) -> ValueClass { + match self { + Value::Boolean(_) => ValueClass::Atomic(AtomClass::Boolean), + Value::Float(_) => ValueClass::Atomic(AtomClass::Float), + Value::Double(_) => ValueClass::Atomic(AtomClass::Double), + Value::SignedInteger(_) => ValueClass::Atomic(AtomClass::SignedInteger), + Value::String(_) => ValueClass::Atomic(AtomClass::String), + Value::ByteString(_) => ValueClass::Atomic(AtomClass::ByteString), + Value::Symbol(_) => ValueClass::Atomic(AtomClass::Symbol), + Value::Record(_) => ValueClass::Compound(CompoundClass::Record), + Value::Sequence(_) => ValueClass::Compound(CompoundClass::Sequence), + Value::Set(_) => ValueClass::Compound(CompoundClass::Set), + Value::Dictionary(_) => ValueClass::Compound(CompoundClass::Dictionary), + Value::Embedded(_) => ValueClass::Embedded, + } + } + fn expected(&self, k: ExpectedKind) -> Error { Error::Expected(k, Received::ReceivedOtherValue(format!("{:?}", self.clone().wrap()))) }