From 1798e646152f89fadcdec5e49aa91e0888e89ed1 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sun, 28 Jan 2024 15:18:08 +0100 Subject: [PATCH] Remove split-out Rust implementation --- Makefile | 1 - README.md | 16 +- git-hooks/pre-commit | 8 - implementations/README.md | 6 +- implementations/rust/.gitignore | 3 - implementations/rust/Cargo.toml | 15 - implementations/rust/Makefile | 41 - implementations/rust/README.md | 13 + .../rust/examples/schema-no-build/Cargo.toml | 10 - .../rust/examples/schema-no-build/src/main.rs | 27 - .../rust/preserves-path/Cargo.toml | 23 - implementations/rust/preserves-path/build.rs | 18 - implementations/rust/preserves-path/path.bin | 7 - .../rust/preserves-path/src/context.rs | 52 - .../rust/preserves-path/src/error.rs | 17 - .../rust/preserves-path/src/lib.rs | 24 - .../rust/preserves-path/src/parse.rs | 322 --- .../rust/preserves-path/src/predicate.rs | 68 - .../rust/preserves-path/src/step.rs | 504 ----- .../rust/preserves-schema-macros/Cargo.toml | 23 - .../rust/preserves-schema-macros/src/lib.rs | 227 -- .../rust/preserves-schema/Cargo.toml | 22 - .../rust/preserves-schema/Makefile | 10 - .../rust/preserves-schema/README.md | 6 - .../rust/preserves-schema/doc/example.md | 112 - .../doc/what-is-preserves-schema.md | 16 - .../src/bin/preserves-schema-rs.rs | 64 - .../preserves-schema/src/compiler/context.rs | 377 ---- .../preserves-schema/src/compiler/cycles.rs | 46 - .../rust/preserves-schema/src/compiler/mod.rs | 636 ------ .../preserves-schema/src/compiler/names.rs | 13 - .../preserves-schema/src/compiler/parsers.rs | 467 ---- .../preserves-schema/src/compiler/readers.rs | 652 ------ .../preserves-schema/src/compiler/types.rs | 461 ---- .../src/compiler/unparsers.rs | 440 ---- .../rust/preserves-schema/src/gen/mod.rs | 261 --- .../rust/preserves-schema/src/gen/schema.rs | 1941 ----------------- .../rust/preserves-schema/src/lib.rs | 98 - .../preserves-schema/src/support/interpret.rs | 297 --- .../rust/preserves-schema/src/support/mod.rs | 168 -- .../rust/preserves-schema/src/syntax/block.rs | 538 ----- .../rust/preserves-schema/src/syntax/mod.rs | 3 - .../rust/preserves-tools/Cargo.toml | 21 - .../preserves-tools/src/bin/preserves-tool.rs | 548 ----- implementations/rust/preserves/Cargo.toml | 31 - implementations/rust/preserves/Makefile | 25 - implementations/rust/preserves/README.md | 23 - .../rust/preserves/benches/.gitignore | 1 - .../rust/preserves/benches/codec.rs | 170 -- .../rust/preserves/benches/testdata.bin.gz | Bin 72659 -> 0 bytes .../doc/cheatsheet-binary-plaintext.md | 31 - .../doc/cheatsheet-text-plaintext.md | 48 - .../rust/preserves/doc/value-grammar.md | 17 - .../rust/preserves/doc/what-is-preserves.md | 12 - .../rust/preserves/examples/Makefile | 10 - .../rust/preserves/examples/extensibility.rs | 57 - .../rust/preserves/examples/known-data.bin | 2 - .../rust/preserves/examples/known-data.txt | 7 - .../rust/preserves/examples/unknown-data.bin | 2 - .../rust/preserves/examples/unknown-data.txt | 8 - implementations/rust/preserves/src/de.rs | 479 ---- implementations/rust/preserves/src/error.rs | 165 -- implementations/rust/preserves/src/hex.rs | 188 -- implementations/rust/preserves/src/lib.rs | 810 ------- implementations/rust/preserves/src/ser.rs | 458 ---- implementations/rust/preserves/src/set.rs | 42 - implementations/rust/preserves/src/symbol.rs | 65 - .../rust/preserves/src/value/boundary.rs | 48 - .../rust/preserves/src/value/de.rs | 465 ---- .../rust/preserves/src/value/domain.rs | 148 -- .../rust/preserves/src/value/magic.rs | 64 - .../rust/preserves/src/value/merge.rs | 74 - .../rust/preserves/src/value/mod.rs | 116 - .../preserves/src/value/packed/constants.rs | 86 - .../rust/preserves/src/value/packed/mod.rs | 54 - .../rust/preserves/src/value/packed/reader.rs | 616 ------ .../rust/preserves/src/value/packed/writer.rs | 583 ----- .../rust/preserves/src/value/reader.rs | 567 ----- .../rust/preserves/src/value/repr.rs | 1877 ---------------- .../rust/preserves/src/value/ser.rs | 377 ---- .../preserves/src/value/signed_integer.rs | 265 --- .../rust/preserves/src/value/suspendable.rs | 62 - .../rust/preserves/src/value/text/mod.rs | 50 - .../rust/preserves/src/value/text/reader.rs | 715 ------ .../rust/preserves/src/value/text/writer.rs | 379 ---- .../rust/preserves/src/value/writer.rs | 232 -- .../rust/preserves/tests/samples/mod.rs | 19 - .../rust/preserves/tests/samples_tests.rs | 214 -- implementations/rust/release.toml | 5 - preserves-schema.md | 2 +- 90 files changed, 25 insertions(+), 18266 deletions(-) delete mode 100644 implementations/rust/.gitignore delete mode 100644 implementations/rust/Cargo.toml delete mode 100644 implementations/rust/Makefile create mode 100644 implementations/rust/README.md delete mode 100644 implementations/rust/examples/schema-no-build/Cargo.toml delete mode 100644 implementations/rust/examples/schema-no-build/src/main.rs delete mode 100644 implementations/rust/preserves-path/Cargo.toml delete mode 100644 implementations/rust/preserves-path/build.rs delete mode 100644 implementations/rust/preserves-path/path.bin delete mode 100644 implementations/rust/preserves-path/src/context.rs delete mode 100644 implementations/rust/preserves-path/src/error.rs delete mode 100644 implementations/rust/preserves-path/src/lib.rs delete mode 100644 implementations/rust/preserves-path/src/parse.rs delete mode 100644 implementations/rust/preserves-path/src/predicate.rs delete mode 100644 implementations/rust/preserves-path/src/step.rs delete mode 100644 implementations/rust/preserves-schema-macros/Cargo.toml delete mode 100644 implementations/rust/preserves-schema-macros/src/lib.rs delete mode 100644 implementations/rust/preserves-schema/Cargo.toml delete mode 100644 implementations/rust/preserves-schema/Makefile delete mode 100644 implementations/rust/preserves-schema/README.md delete mode 100644 implementations/rust/preserves-schema/doc/example.md delete mode 100644 implementations/rust/preserves-schema/doc/what-is-preserves-schema.md delete mode 100644 implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/context.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/cycles.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/mod.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/names.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/parsers.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/readers.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/types.rs delete mode 100644 implementations/rust/preserves-schema/src/compiler/unparsers.rs delete mode 100644 implementations/rust/preserves-schema/src/gen/mod.rs delete mode 100644 implementations/rust/preserves-schema/src/gen/schema.rs delete mode 100644 implementations/rust/preserves-schema/src/lib.rs delete mode 100644 implementations/rust/preserves-schema/src/support/interpret.rs delete mode 100644 implementations/rust/preserves-schema/src/support/mod.rs delete mode 100644 implementations/rust/preserves-schema/src/syntax/block.rs delete mode 100644 implementations/rust/preserves-schema/src/syntax/mod.rs delete mode 100644 implementations/rust/preserves-tools/Cargo.toml delete mode 100644 implementations/rust/preserves-tools/src/bin/preserves-tool.rs delete mode 100644 implementations/rust/preserves/Cargo.toml delete mode 100644 implementations/rust/preserves/Makefile delete mode 100644 implementations/rust/preserves/README.md delete mode 100644 implementations/rust/preserves/benches/.gitignore delete mode 100644 implementations/rust/preserves/benches/codec.rs delete mode 100644 implementations/rust/preserves/benches/testdata.bin.gz delete mode 100644 implementations/rust/preserves/doc/cheatsheet-binary-plaintext.md delete mode 100644 implementations/rust/preserves/doc/cheatsheet-text-plaintext.md delete mode 100644 implementations/rust/preserves/doc/value-grammar.md delete mode 100644 implementations/rust/preserves/doc/what-is-preserves.md delete mode 100644 implementations/rust/preserves/examples/Makefile delete mode 100644 implementations/rust/preserves/examples/extensibility.rs delete mode 100644 implementations/rust/preserves/examples/known-data.bin delete mode 100644 implementations/rust/preserves/examples/known-data.txt delete mode 100644 implementations/rust/preserves/examples/unknown-data.bin delete mode 100644 implementations/rust/preserves/examples/unknown-data.txt delete mode 100644 implementations/rust/preserves/src/de.rs delete mode 100644 implementations/rust/preserves/src/error.rs delete mode 100644 implementations/rust/preserves/src/hex.rs delete mode 100644 implementations/rust/preserves/src/lib.rs delete mode 100644 implementations/rust/preserves/src/ser.rs delete mode 100644 implementations/rust/preserves/src/set.rs delete mode 100644 implementations/rust/preserves/src/symbol.rs delete mode 100644 implementations/rust/preserves/src/value/boundary.rs delete mode 100644 implementations/rust/preserves/src/value/de.rs delete mode 100644 implementations/rust/preserves/src/value/domain.rs delete mode 100644 implementations/rust/preserves/src/value/magic.rs delete mode 100644 implementations/rust/preserves/src/value/merge.rs delete mode 100644 implementations/rust/preserves/src/value/mod.rs delete mode 100644 implementations/rust/preserves/src/value/packed/constants.rs delete mode 100644 implementations/rust/preserves/src/value/packed/mod.rs delete mode 100644 implementations/rust/preserves/src/value/packed/reader.rs delete mode 100644 implementations/rust/preserves/src/value/packed/writer.rs delete mode 100644 implementations/rust/preserves/src/value/reader.rs delete mode 100644 implementations/rust/preserves/src/value/repr.rs delete mode 100644 implementations/rust/preserves/src/value/ser.rs delete mode 100644 implementations/rust/preserves/src/value/signed_integer.rs delete mode 100644 implementations/rust/preserves/src/value/suspendable.rs delete mode 100644 implementations/rust/preserves/src/value/text/mod.rs delete mode 100644 implementations/rust/preserves/src/value/text/reader.rs delete mode 100644 implementations/rust/preserves/src/value/text/writer.rs delete mode 100644 implementations/rust/preserves/src/value/writer.rs delete mode 100644 implementations/rust/preserves/tests/samples/mod.rs delete mode 100644 implementations/rust/preserves/tests/samples_tests.rs delete mode 100644 implementations/rust/release.toml diff --git a/Makefile b/Makefile index b98e45d..33ceaf5 100644 --- a/Makefile +++ b/Makefile @@ -22,4 +22,3 @@ test-all: (cd implementations/javascript; npm test) (cd implementations/python; make test) (cd implementations/racket/preserves; make testonly) - (cd implementations/rust; cargo test) diff --git a/README.md b/README.md index 2fd1875..f0d45d9 100644 --- a/README.md +++ b/README.md @@ -38,14 +38,14 @@ automatic, perfect-fidelity conversion between syntaxes. #### Implementations of the data model, plus Preserves textual and binary transfer syntax -| Language[^pre-alpha-implementations] | Code | Package | Docs | -|-----------------------|------------------------------------------------------------------------------|--------------------------------------------------------------------------------|-------------------------------------------| -| Nim | [git.syndicate-lang.org](https://git.syndicate-lang.org/ehmry/preserves-nim) | | | -| Python | [preserves.dev]({{page.projecttree}}/implementations/python/) | [`pip install preserves`](https://pypi.org/project/preserves/) | [docs](python/latest/) | -| Racket | [preserves.dev]({{page.projecttree}}/implementations/racket/preserves/) | [`raco pkg install preserves`](https://pkgs.racket-lang.org/package/preserves) | | -| Rust | [preserves.dev]({{page.projecttree}}/implementations/rust/) | [`cargo add preserves`](https://crates.io/crates/preserves) | [docs](https://docs.rs/preserves/latest/) | -| Squeak Smalltalk | [SqueakSource](https://squeaksource.com/Preserves.html) | `Installer ss project: 'Preserves';`
`  install: 'Preserves'` | | -| TypeScript/JavaScript | [preserves.dev]({{page.projecttree}}/implementations/javascript/) | [`yarn add @preserves/core`](https://www.npmjs.com/package/@preserves/core) | | +| Language[^pre-alpha-implementations] | Code | Package | Docs | +|--------------------------------------|------------------------------------------------------------------------------|--------------------------------------------------------------------------------|-------------------------------------------| +| Nim | [git.syndicate-lang.org](https://git.syndicate-lang.org/ehmry/preserves-nim) | | | +| Python | [preserves.dev]({{page.projecttree}}/implementations/python/) | [`pip install preserves`](https://pypi.org/project/preserves/) | [docs](python/latest/) | +| Racket | [preserves.dev]({{page.projecttree}}/implementations/racket/preserves/) | [`raco pkg install preserves`](https://pkgs.racket-lang.org/package/preserves) | | +| Rust | [preserves.dev](https://gitlab.com/preserves/preserves-rs/) | [`cargo add preserves`](https://crates.io/crates/preserves) | [docs](https://docs.rs/preserves/latest/) | +| Squeak Smalltalk | [SqueakSource](https://squeaksource.com/Preserves.html) | `Installer ss project: 'Preserves';`
`  install: 'Preserves'` | | +| TypeScript/JavaScript | [preserves.dev]({{page.projecttree}}/implementations/javascript/) | [`yarn add @preserves/core`](https://www.npmjs.com/package/@preserves/core) | | [^pre-alpha-implementations]: Pre-alpha implementations also exist for [C]({{page.projecttree}}/implementations/c/) and diff --git a/git-hooks/pre-commit b/git-hooks/pre-commit index 1da8323..4037e41 100755 --- a/git-hooks/pre-commit +++ b/git-hooks/pre-commit @@ -31,7 +31,6 @@ fi # Ensure that various copies of schema.prs, schema.bin, path.bin, # samples.pr and samples.bin are in fact identical. ${COMMAND} path/path.bin implementations/python/preserves/path.prb -${COMMAND} path/path.bin implementations/rust/preserves-path/path.bin ${COMMAND} schema/schema.bin implementations/python/preserves/schema.prb ${COMMAND} schema/schema.prs implementations/racket/preserves/preserves-schema/schema.prs @@ -40,11 +39,4 @@ ${COMMAND} tests/samples.bin implementations/python/tests/samples.bin ${COMMAND} tests/samples.pr implementations/python/tests/samples.pr ${COMMAND} tests/samples.pr implementations/racket/preserves/preserves/tests/samples.pr -${COMMAND} _includes/what-is-preserves.md implementations/rust/preserves/doc/what-is-preserves.md -${COMMAND} _includes/cheatsheet-binary-plaintext.md implementations/rust/preserves/doc/cheatsheet-binary-plaintext.md -${COMMAND} _includes/cheatsheet-text-plaintext.md implementations/rust/preserves/doc/cheatsheet-text-plaintext.md -${COMMAND} _includes/value-grammar.md implementations/rust/preserves/doc/value-grammar.md - -${COMMAND} _includes/what-is-preserves-schema.md implementations/rust/preserves-schema/doc/what-is-preserves-schema.md - [ -z "$failed" ] diff --git a/implementations/README.md b/implementations/README.md index c0d0399..98908c9 100644 --- a/implementations/README.md +++ b/implementations/README.md @@ -13,9 +13,9 @@ Here you may find: - [racket](racket/), an implementation for Racket 7.x and newer (though older Rackets may also work with it). - - [rust](rust/), an implementation for Rust that interoperates with - serde. - Other implementations are also available: + - [Preserves for Rust](https://gitlab.com/preserves/preserves-rs/), an implementation for Rust + that interoperates with serde. + - [Preserves for Squeak Smalltalk](https://squeaksource.com/Preserves.html) diff --git a/implementations/rust/.gitignore b/implementations/rust/.gitignore deleted file mode 100644 index 7c6e654..0000000 --- a/implementations/rust/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -Cargo.lock -scratch/ -target/ diff --git a/implementations/rust/Cargo.toml b/implementations/rust/Cargo.toml deleted file mode 100644 index 60af6ee..0000000 --- a/implementations/rust/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[workspace] -exclude = [ - "examples/schema-no-build", - ] - -members = [ - "preserves", - "preserves-path", - "preserves-schema", - "preserves-schema-macros", - "preserves-tools", - ] - -[profile.bench] -debug = true diff --git a/implementations/rust/Makefile b/implementations/rust/Makefile deleted file mode 100644 index 4432efb..0000000 --- a/implementations/rust/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# Use cargo release to manage publication and versions etc. -# -# cargo install cargo-release - -all: - cargo build --all-targets - -doc: - cargo doc --workspace - -x86_64-binary: x86_64-binary-release - -x86_64-binary-release: - cross build --target=x86_64-unknown-linux-musl --release --all-targets - -armv7-binary: armv7-binary-release - -armv7-binary-release: - cross build --target=armv7-unknown-linux-musleabihf --release --all-targets - -aarch64-binary: aarch64-binary-release - -aarch64-binary-release: - cross build --target=aarch64-unknown-linux-musl --release --all-targets - -test: - cargo test - -test-all: - cargo test --all-targets - -ws-bump: - cargo workspaces version \ - --no-global-tag \ - --individual-tag-prefix 'rust-%n@' \ - --allow-branch 'main' \ - --ignore-changes '../*' - -ws-publish: - cargo workspaces publish \ - --from-git diff --git a/implementations/rust/README.md b/implementations/rust/README.md new file mode 100644 index 0000000..d375542 --- /dev/null +++ b/implementations/rust/README.md @@ -0,0 +1,13 @@ +# Split out to separate repository + +The Rust implementation of Preserves has been split out into a separate git repository, +. + +The final released versions that were here were + + - `preserves` v4.992.2, + - `preserves-schema` v5.992.0, + - `preserves-tools` v4.992.2, and + - `preserves-path` v5.992.0. + +Subsequent releases live in the other repository. diff --git a/implementations/rust/examples/schema-no-build/Cargo.toml b/implementations/rust/examples/schema-no-build/Cargo.toml deleted file mode 100644 index 68d7a70..0000000 --- a/implementations/rust/examples/schema-no-build/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "schema-no-build" -version = "0.1.0" -edition = "2021" - -[dependencies] -lazy_static = "1" -preserves = { path = "../../preserves" } -preserves-schema = { path = "../../preserves-schema" } -preserves-schema-macros = { path = "../../preserves-schema-macros" } diff --git a/implementations/rust/examples/schema-no-build/src/main.rs b/implementations/rust/examples/schema-no-build/src/main.rs deleted file mode 100644 index a12f8e7..0000000 --- a/implementations/rust/examples/schema-no-build/src/main.rs +++ /dev/null @@ -1,27 +0,0 @@ -use preserves::value::IOValue; -use preserves_schema_macros::compile_preserves_schemas; - -compile_preserves_schemas!( - crate::schemas, - load("/../../../../path/path.bin"), - external_module(EntityRef = crate::demo_entity_ref), -); - -pub mod demo_entity_ref { - use preserves::value::IOValue; - pub type Cap = IOValue; -} - -preserves_schema::define_language!(language(): Language { - demo: crate::schemas::Language, -}); - -fn main() { - use crate::schemas::path::*; - use preserves::value::NestedValue; - use preserves_schema::support::Unparse; - println!("Hello, world! {:?}", (Filter::Compare { - op: Box::new(Comparison::Eq), - literal: IOValue::new(123), - }).unparse(language())); -} diff --git a/implementations/rust/preserves-path/Cargo.toml b/implementations/rust/preserves-path/Cargo.toml deleted file mode 100644 index 52b2862..0000000 --- a/implementations/rust/preserves-path/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "preserves-path" -version = "5.993.0" -authors = ["Tony Garnock-Jones "] -edition = "2018" -description = "Implementation of preserves-path, a query language for Preserves documents." -homepage = "https://preserves.dev/" -repository = "https://gitlab.com/preserves/preserves" -license = "Apache-2.0" - -[build-dependencies] -preserves-schema = { path = "../preserves-schema", version = "5.993.0"} - -[dependencies] -preserves = { path = "../preserves", version = "4.993.0"} -preserves-schema = { path = "../preserves-schema", version = "5.993.0"} - -num = "0.4" -regex = "1.5" -thiserror = "1.0" - -[package.metadata.workspaces] -independent = true diff --git a/implementations/rust/preserves-path/build.rs b/implementations/rust/preserves-path/build.rs deleted file mode 100644 index 7db9063..0000000 --- a/implementations/rust/preserves-path/build.rs +++ /dev/null @@ -1,18 +0,0 @@ -use preserves_schema::compiler::*; - -use std::io::Error; -use std::path::PathBuf; - -fn main() -> Result<(), Error> { - let buildroot = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); - - let mut gen_dir = buildroot.clone(); - gen_dir.push("src/schemas"); - - let mut c = CompilerConfig::new("crate::schemas".to_owned()); - - let inputs = expand_inputs(&vec!["path.bin".to_owned()])?; - c.load_schemas_and_bundles(&inputs, &vec![])?; - - compile(&c, &mut CodeCollector::files(gen_dir)) -} diff --git a/implementations/rust/preserves-path/path.bin b/implementations/rust/preserves-path/path.bin deleted file mode 100644 index d1c1b1a..0000000 --- a/implementations/rust/preserves-path/path.bin +++ /dev/null @@ -1,7 +0,0 @@ -´³schema·³version°³ definitions·³Axis´³orµµ±values´³rec´³lit³values„´³tupleµ„„„„µ± descendants´³rec´³lit³ descendants„´³tupleµ„„„„µ±at´³rec´³lit³at„´³tupleµ´³named³key³any„„„„„µ±label´³rec´³lit³label„´³tupleµ„„„„µ±keys´³rec´³lit³keys„´³tupleµ„„„„µ±length´³rec´³lit³length„´³tupleµ„„„„µ± annotations´³rec´³lit³ annotations„´³tupleµ„„„„µ±embedded´³rec´³lit³embedded„´³tupleµ„„„„µ±parse´³rec´³lit³parse„´³tupleµ´³named³module´³seqof´³atom³Symbol„„„´³named³name´³atom³Symbol„„„„„„µ±unparse´³rec´³lit³unparse„´³tupleµ´³named³module´³seqof´³atom³Symbol„„„´³named³name´³atom³Symbol„„„„„„„„³Step´³orµµ±Axis´³refµ„³Axis„„µ±Filter´³refµ„³Filter„„µ±Function´³refµ„³Function„„„„³Filter´³orµµ±nop´³rec´³lit³nop„´³tupleµ„„„„µ±compare´³rec´³lit³compare„´³tupleµ´³named³op´³refµ„³ -Comparison„„´³named³literal³any„„„„„µ±regex´³rec´³lit³regex„´³tupleµ´³named³regex´³atom³String„„„„„„µ±test´³rec´³lit³test„´³tupleµ´³named³pred´³refµ„³ Predicate„„„„„„µ±real´³rec´³lit³real„´³tupleµ„„„„µ±int´³rec´³lit³int„´³tupleµ„„„„µ±kind´³rec´³lit³kind„´³tupleµ´³named³kind´³refµ„³ ValueKind„„„„„„„„³Function´³rec´³lit³count„´³tupleµ´³named³selector´³refµ„³Selector„„„„„³Selector´³seqof´³refµ„³Step„„³ Predicate´³orµµ±Selector´³refµ„³Selector„„µ±not´³rec´³lit³not„´³tupleµ´³named³pred´³refµ„³ Predicate„„„„„„µ±or´³rec´³lit³or„´³tupleµ´³named³preds´³seqof´³refµ„³ Predicate„„„„„„„µ±and´³rec´³lit³and„´³tupleµ´³named³preds´³seqof´³refµ„³ Predicate„„„„„„„„„³ ValueKind´³orµµ±Boolean´³lit³Boolean„„µ±Double´³lit³Double„„µ± SignedInteger´³lit³ SignedInteger„„µ±String´³lit³String„„µ± -ByteString´³lit³ -ByteString„„µ±Symbol´³lit³Symbol„„µ±Record´³lit³Record„„µ±Sequence´³lit³Sequence„„µ±Set´³lit³Set„„µ± -Dictionary´³lit³ -Dictionary„„µ±Embedded´³lit³Embedded„„„„³ -Comparison´³orµµ±eq´³lit³eq„„µ±ne´³lit³ne„„µ±lt´³lit³lt„„µ±ge´³lit³ge„„µ±gt´³lit³gt„„µ±le´³lit³le„„„„„³ embeddedType€„„ \ No newline at end of file diff --git a/implementations/rust/preserves-path/src/context.rs b/implementations/rust/preserves-path/src/context.rs deleted file mode 100644 index 8afad8f..0000000 --- a/implementations/rust/preserves-path/src/context.rs +++ /dev/null @@ -1,52 +0,0 @@ -use preserves::value::IOValue; - -use preserves_schema::compiler::load_schema_or_bundle; -use preserves_schema::gen::schema::Definition; - -use std::io; - -#[derive(Default)] -pub struct Env(pub preserves_schema::support::interpret::Env); - -pub struct Context<'a> { - pub env: &'a Env, - path: Vec, -} - -impl<'a> Context<'a> { - pub fn new(env: &'a Env) -> Self { - Context { - env, - path: Vec::new(), - } - } - - pub fn with_path_step R>(&mut self, v: &IOValue, f: F) -> R { - self.path.push(v.clone()); - let result = f(self); - self.path.pop(); - result - } -} - -impl Env { - pub fn new() -> Self { - Default::default() - } - - pub fn load_bundle(&mut self, filename: &std::path::PathBuf) -> io::Result { - load_schema_or_bundle(&mut self.0, filename) - } - - pub fn lookup_definition( - &self, - module: &Vec, - name: &str, - ) -> Option<&Definition> { - self.0.get(module).and_then(|s| s.definitions.0.get(name)) - } - - pub fn to_context(&self) -> Context { - Context::new(self) - } -} diff --git a/implementations/rust/preserves-path/src/error.rs b/implementations/rust/preserves-path/src/error.rs deleted file mode 100644 index 7e0afc5..0000000 --- a/implementations/rust/preserves-path/src/error.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::io; - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum CompilationError { - #[error(transparent)] - IoError(#[from] io::Error), - #[error("Cannot mix binary operators")] - MixedOperators, - #[error("Invalid step")] - InvalidStep, - #[error("Undefined schema definition name: {0}")] - UndefinedSchemaDefinitionName(String), - #[error(transparent)] - RegexError(#[from] regex::Error), -} diff --git a/implementations/rust/preserves-path/src/lib.rs b/implementations/rust/preserves-path/src/lib.rs deleted file mode 100644 index 43e705c..0000000 --- a/implementations/rust/preserves-path/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -pub mod context; -pub mod error; -pub mod parse; -pub mod predicate; - -pub mod schemas { - include!(concat!(env!("OUT_DIR"), "/src/schemas/mod.rs")); -} - -pub mod step; - -pub use context::Context; -pub use context::Env; - -pub use error::CompilationError; - -pub use parse::parse_predicate; -pub use parse::parse_selector; - -pub use schemas::path::Predicate; -pub use schemas::path::Selector; -pub use schemas::path::Step; - -pub use step::Node; diff --git a/implementations/rust/preserves-path/src/parse.rs b/implementations/rust/preserves-path/src/parse.rs deleted file mode 100644 index 2741524..0000000 --- a/implementations/rust/preserves-path/src/parse.rs +++ /dev/null @@ -1,322 +0,0 @@ -use crate::context::Env; -use crate::schemas::path; -use crate::step::Node; -use crate::CompilationError; - -use preserves::value::BinarySource; -use preserves::value::BytesBinarySource; -use preserves::value::IOValue; -use preserves::value::NestedValue; -use preserves::value::Reader; - -use std::iter::Iterator; - -#[derive(Debug)] -enum Binop { - Union, - Intersection, -} - -fn split_values_by_symbol<'a>(tokens: &'a [IOValue], separator: &str) -> Vec<&'a [IOValue]> { - tokens - .split(|t| matches!(t.value().as_symbol(), Some(s) if s == separator)) - .collect() -} - -fn split_binop(tokens: &[IOValue]) -> Result<(Vec<&[IOValue]>, Option), CompilationError> { - let union_pieces = split_values_by_symbol(&tokens, "+"); - let intersection_pieces = split_values_by_symbol(&tokens, "&"); - match (union_pieces.len(), intersection_pieces.len()) { - (1, 1) => Ok((union_pieces, None)), - (_, 1) => Ok((union_pieces, Some(Binop::Union))), - (1, _) => Ok((intersection_pieces, Some(Binop::Intersection))), - _ => Err(CompilationError::MixedOperators), - } -} - -pub fn parse_selector(env: &Env, tokens: &[IOValue]) -> Result { - let mut steps = Vec::new(); - let mut tokens = tokens; - while let Some((s, remaining)) = parse_step(env, tokens)? { - steps.push(s); - tokens = remaining; - } - Ok(path::Selector(steps)) -} - -pub fn parse_predicate(env: &Env, tokens: &[IOValue]) -> Result { - let (pieces, binop) = split_binop(tokens)?; - match binop { - None => parse_non_binop(env, &pieces[0]), - Some(o) => { - let preds = pieces - .into_iter() - .map(|ts| parse_non_binop(env, &ts)) - .collect::>()?; - Ok(match o { - Binop::Union => path::Predicate::Or { preds }, - Binop::Intersection => path::Predicate::And { preds }, - }) - } - } -} - -fn parse_non_binop(env: &Env, tokens: &[IOValue]) -> Result { - if !tokens.is_empty() { - let t = tokens[0].value(); - - if let Some("!") = t.as_symbol().map(|s| s.as_str()) { - return Ok(path::Predicate::Not { - pred: Box::new(parse_non_binop(env, &tokens[1..])?), - }); - } - } - - Ok(path::Predicate::Selector(Box::new(parse_selector( - env, tokens, - )?))) -} - -fn parse_schema_definition_name( - env: &Env, - token: &IOValue, -) -> Result<(Vec, String), CompilationError> { - let defpath = token - .value() - .to_symbol() - .map_err(|_| CompilationError::InvalidStep)?; - let mut module: Vec = defpath.split('.').map(|s| s.to_string()).collect(); - let name = module - .pop() - .expect("at least one element in the Schema name"); - match env.lookup_definition(&module, &name) { - Some(_) => Ok((module, name)), - None => Err(CompilationError::UndefinedSchemaDefinitionName(format!( - "{:?}", - token - ))), - } -} - -fn parse_step<'a>( - env: &Env, - tokens: &'a [IOValue], -) -> Result, CompilationError> { - if tokens.is_empty() { - return Ok(None); - } - - let remainder = &tokens[1..]; - - if tokens[0].value().is_sequence() { - return Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Test { - pred: Box::new(parse_predicate( - env, - tokens[0].value().as_sequence().unwrap(), - )?), - })), - remainder, - ))); - } - - match tokens[0].value().as_record(None) { - None => (), - Some(r) => match r.label().value().as_symbol() { - None => return Err(CompilationError::InvalidStep), - Some(t) => match t.as_str() { - "count" => { - return Ok(Some(( - path::Step::Function(Box::new(path::Function { - selector: parse_selector(env, r.fields())?, - })), - remainder, - ))) - } - _ => return Err(CompilationError::InvalidStep), - }, - }, - } - - match tokens[0].value().as_symbol() { - None => return Err(CompilationError::InvalidStep), - Some(t) => match t.as_str() { - "/" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Values)), - remainder, - ))), - "//" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Descendants)), - remainder, - ))), - "." => { - let (key, remainder) = pop_step_arg(remainder)?; - Ok(Some(( - path::Step::Axis(Box::new(path::Axis::At { key })), - remainder, - ))) - } - ".^" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Label)), - remainder, - ))), - ".keys" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Keys)), - remainder, - ))), - ".length" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Length)), - remainder, - ))), - ".annotations" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Annotations)), - remainder, - ))), - ".embedded" => Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Embedded)), - remainder, - ))), - "%" => { - let (defpath, remainder) = pop_step_arg(remainder)?; - let (module, name) = parse_schema_definition_name(env, &defpath)?; - Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Parse { module, name })), - remainder, - ))) - } - "%-" => { - let (defpath, remainder) = pop_step_arg(remainder)?; - let (module, name) = parse_schema_definition_name(env, &defpath)?; - Ok(Some(( - path::Step::Axis(Box::new(path::Axis::Unparse { module, name })), - remainder, - ))) - } - "*" => Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Nop)), - remainder, - ))), - "eq" | "=" => parse_comparison(remainder, path::Comparison::Eq), - "ne" | "!=" => parse_comparison(remainder, path::Comparison::Ne), - "lt" => parse_comparison(remainder, path::Comparison::Lt), - "gt" => parse_comparison(remainder, path::Comparison::Gt), - "le" => parse_comparison(remainder, path::Comparison::Le), - "ge" => parse_comparison(remainder, path::Comparison::Ge), - "re" | "=r" => { - let (regex_val, remainder) = pop_step_arg(remainder)?; - let regex = regex_val - .value() - .to_string() - .map_err(|_| CompilationError::InvalidStep)? - .clone(); - let _ = regex::Regex::new(®ex)?; - Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Regex { regex })), - remainder, - ))) - } - "^" => { - let (literal, remainder) = pop_step_arg(remainder)?; - Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Test { - pred: Box::new(path::Predicate::Selector(Box::new(path::Selector(vec![ - path::Step::Axis(Box::new(path::Axis::Label)), - path::Step::Filter(Box::new(path::Filter::Compare { - op: Box::new(path::Comparison::Eq), - literal, - })), - ])))), - })), - remainder, - ))) - } - - "~real" => Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Real)), - remainder, - ))), - "~int" => Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Int)), - remainder, - ))), - - "bool" => Ok(Some(( - path::Step::from(path::ValueKind::Boolean), - remainder, - ))), - "double" => Ok(Some((path::Step::from(path::ValueKind::Double), remainder))), - "int" => Ok(Some(( - path::Step::from(path::ValueKind::SignedInteger), - remainder, - ))), - "string" => Ok(Some((path::Step::from(path::ValueKind::String), remainder))), - "bytes" => Ok(Some(( - path::Step::from(path::ValueKind::ByteString), - remainder, - ))), - "symbol" => Ok(Some((path::Step::from(path::ValueKind::Symbol), remainder))), - "rec" => Ok(Some((path::Step::from(path::ValueKind::Record), remainder))), - "seq" => Ok(Some(( - path::Step::from(path::ValueKind::Sequence), - remainder, - ))), - "set" => Ok(Some((path::Step::from(path::ValueKind::Set), remainder))), - "dict" => Ok(Some(( - path::Step::from(path::ValueKind::Dictionary), - remainder, - ))), - "embedded" => Ok(Some(( - path::Step::from(path::ValueKind::Embedded), - remainder, - ))), - - _ => Err(CompilationError::InvalidStep), - }, - } -} - -impl From for path::Step { - fn from(k: path::ValueKind) -> Self { - path::Step::Filter(Box::new(path::Filter::Kind { kind: Box::new(k) })) - } -} - -fn pop_step_arg(tokens: &[IOValue]) -> Result<(IOValue, &[IOValue]), CompilationError> { - if tokens.is_empty() { - return Err(CompilationError::InvalidStep); - } - Ok((tokens[0].clone(), &tokens[1..])) -} - -fn parse_comparison( - tokens: &[IOValue], - op: path::Comparison, -) -> Result, CompilationError> { - let (literal, remainder) = pop_step_arg(tokens)?; - Ok(Some(( - path::Step::Filter(Box::new(path::Filter::Compare { - op: Box::new(op), - literal, - })), - remainder, - ))) -} - -impl path::Selector { - pub fn from_str(env: &Env, s: &str) -> Result { - parse_selector( - env, - &(BytesBinarySource::new(s.as_bytes()) - .text_iovalues() - .configured(false) - .collect::, _>>()?), - ) - } -} - -impl Node { - pub fn from_str(env: &Env, s: &str) -> Result { - let expr = path::Selector::from_str(env, s)?; - expr.compile() - } -} diff --git a/implementations/rust/preserves-path/src/predicate.rs b/implementations/rust/preserves-path/src/predicate.rs deleted file mode 100644 index 09b5ef0..0000000 --- a/implementations/rust/preserves-path/src/predicate.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::context::Context; -use crate::schemas::path; -use crate::step::BoolCollector; -use crate::step::Node; -use crate::step::StepMaker; -use crate::CompilationError; - -use preserves::value::IOValue; - -pub trait Predicate: std::fmt::Debug { - fn test(&mut self, ctxt: &mut Context, value: &IOValue) -> bool; -} - -#[derive(Debug)] -pub enum CompiledPredicate { - Selector(Node), - Not(Box), - Or(Vec), - And(Vec), -} - -impl path::Predicate { - pub fn compile(&self) -> Result { - match self { - path::Predicate::Selector(b) => Ok(CompiledPredicate::Selector( - (&**b).connect(BoolCollector::new())?, - )), - path::Predicate::Not { pred } => { - Ok(CompiledPredicate::Not(Box::new((&**pred).compile()?))) - } - path::Predicate::Or { preds } => Ok(CompiledPredicate::Or( - preds.iter().map(Self::compile).collect::>()?, - )), - path::Predicate::And { preds } => Ok(CompiledPredicate::And( - preds.iter().map(Self::compile).collect::>()?, - )), - } - } - - pub fn exec(&self, ctxt: &mut Context, value: &IOValue) -> Result { - Ok(self.compile()?.test(ctxt, value)) - } -} - -impl Predicate for CompiledPredicate { - fn test(&mut self, ctxt: &mut Context, value: &IOValue) -> bool { - match self { - CompiledPredicate::Selector(n) => n.test(ctxt, value), - CompiledPredicate::Not(p) => !p.test(ctxt, value), - CompiledPredicate::Or(ps) => { - for p in ps.iter_mut() { - if p.test(ctxt, value) { - return true; - } - } - return false; - } - CompiledPredicate::And(ps) => { - for p in ps.iter_mut() { - if !p.test(ctxt, value) { - return false; - } - } - return true; - } - } - } -} diff --git a/implementations/rust/preserves-path/src/step.rs b/implementations/rust/preserves-path/src/step.rs deleted file mode 100644 index 9322649..0000000 --- a/implementations/rust/preserves-path/src/step.rs +++ /dev/null @@ -1,504 +0,0 @@ -// Selectors operate on IOValues because the AST includes keys of IOValue type. -// If we could make Schemas produce generics... - -use crate::context::Context; -use crate::predicate::CompiledPredicate; -use crate::predicate::Predicate; -use crate::schemas::path; -use crate::CompilationError; - -use num::bigint::BigInt; -use num::traits::cast::FromPrimitive; -use num::traits::cast::ToPrimitive; - -use preserves::value::AtomClass; -use preserves::value::CompoundClass; -use preserves::value::IOValue; -use preserves::value::NestedValue; -use preserves::value::Value; -use preserves::value::ValueClass; - -use preserves_schema::support::interpret; - -use std::cell::RefCell; -use std::iter::Iterator; -use std::rc::Rc; - -pub trait StepMaker { - fn connect(&self, step: Node) -> Result; -} - -pub trait Step: std::fmt::Debug { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue); - fn finish(&mut self); - fn reset(&mut self) -> Vec; -} - -macro_rules! delegate_finish_and_reset { - ($self:ident, $target:expr) => { - fn finish(&mut $self) { $target.finish() } - fn reset(&mut $self) -> Vec { $target.reset() } - } -} - -#[derive(Clone, Debug)] -pub struct Node(pub Rc>); - -#[derive(Debug)] -struct AxisStep { - step: Node, - axis: path::Axis, -} - -#[derive(Debug)] -struct CompareStep { - op: path::Comparison, - literal: IOValue, - step: Node, -} - -#[derive(Debug)] -struct RegexStep { - regex: regex::Regex, - step: Node, -} - -#[derive(Debug)] -struct TestStep { - pred: CompiledPredicate, - step: Node, -} - -#[derive(Debug)] -struct RealStep { - step: Node, -} - -#[derive(Debug)] -struct IntStep { - step: Node, -} - -#[derive(Debug)] -struct VecCollector { - accumulator: Vec, -} - -#[derive(Debug)] -pub struct BoolCollector { - seen_value: bool, -} - -#[derive(Debug)] -struct KindStep { - kind: ValueClass, - step: Node, -} - -#[derive(Debug)] -pub struct CountCollector { - count: usize, -} - -#[derive(Debug)] -struct CountStep { - step: Node, - counter: Node, -} - -impl Node { - fn new(s: S) -> Self { - Node(Rc::new(RefCell::new(s))) - } - - pub fn test(&self, ctxt: &mut Context, value: &IOValue) -> bool { - !self.exec(ctxt, value).is_empty() - } - - pub fn accept(&self, ctxt: &mut Context, value: &IOValue) { - self.0.borrow_mut().accept(ctxt, value) - } - - pub fn finish(&self) { - self.0.borrow_mut().finish() - } - - pub fn reset(&self) -> Vec { - self.0.borrow_mut().reset() - } - - pub fn exec(&self, ctxt: &mut Context, value: &IOValue) -> Vec { - self.accept(ctxt, value); - self.finish(); - self.reset() - } -} - -impl StepMaker for path::Selector { - fn connect(&self, step: Node) -> Result { - self.0.connect(step) - } -} - -impl StepMaker for Vec { - fn connect(&self, mut step: Node) -> Result { - for s in self.iter().rev() { - step = s.connect(step)?; - } - Ok(step) - } -} - -impl StepMaker for path::Step { - fn connect(&self, step: Node) -> Result { - match self { - path::Step::Axis(b) => (&**b).connect(step), - path::Step::Filter(b) => (&**b).connect(step), - path::Step::Function(b) => (&**b).connect(step), - } - } -} - -impl StepMaker for path::Axis { - fn connect(&self, step: Node) -> Result { - Ok(Node::new(AxisStep { - step, - axis: self.clone(), - })) - } -} - -fn descendants(ctxt: &mut Context, step: &mut Node, v: &IOValue) { - step.accept(ctxt, v); - for c in v.value().children() { - ctxt.with_path_step(&c, |ctxt| descendants(ctxt, step, &c)); - } -} - -impl Step for AxisStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - ctxt.with_path_step(value, |ctxt| match &self.axis { - path::Axis::Values => { - for c in value.value().children() { - self.step.accept(ctxt, &c) - } - } - path::Axis::Descendants => descendants(ctxt, &mut self.step, value), - path::Axis::At { key } => match value.value() { - Value::String(s) | Value::Symbol(s) => step_index( - ctxt, - s.chars(), - &key, - |c| IOValue::new(String::from(c)), - &mut self.step, - ), - Value::Record(r) => { - step_index(ctxt, r.fields().iter(), &key, |v| v.clone(), &mut self.step) - } - Value::Sequence(vs) => { - step_index(ctxt, vs.iter(), &key, |v| v.clone(), &mut self.step) - } - Value::Dictionary(d) => { - if let Some(v) = d.get(&key) { - self.step.accept(ctxt, v) - } - } - _ => (), - }, - path::Axis::Label => { - if let Some(r) = value.value().as_record(None) { - self.step.accept(ctxt, r.label()) - } - } - path::Axis::Keys => match value.value() { - Value::String(s) | Value::Symbol(s) => step_keys(ctxt, s.len(), &mut self.step), - Value::ByteString(bs) => step_keys(ctxt, bs.len(), &mut self.step), - Value::Record(r) => step_keys(ctxt, r.arity(), &mut self.step), - Value::Sequence(vs) => step_keys(ctxt, vs.len(), &mut self.step), - Value::Dictionary(d) => { - for k in d.keys() { - self.step.accept(ctxt, k) - } - } - _ => (), - }, - path::Axis::Length => match value.value() { - Value::String(s) | Value::Symbol(s) => { - self.step.accept(ctxt, &IOValue::new(s.len())) - } - Value::ByteString(bs) => self.step.accept(ctxt, &IOValue::new(bs.len())), - Value::Record(r) => self.step.accept(ctxt, &IOValue::new(r.arity())), - Value::Sequence(vs) => self.step.accept(ctxt, &IOValue::new(vs.len())), - Value::Dictionary(d) => self.step.accept(ctxt, &IOValue::new(d.len())), - _ => self.step.accept(ctxt, &IOValue::new(0)), - }, - path::Axis::Annotations => { - for c in value.annotations().slice() { - self.step.accept(ctxt, &c) - } - } - path::Axis::Embedded => { - if let Some(d) = value.value().as_embedded() { - self.step.accept(ctxt, d) - } - } - path::Axis::Parse { module, name } => { - if let Some(p) = - interpret::Context::new(&ctxt.env.0).dynamic_parse(module, name, value) - { - self.step.accept(ctxt, &p) - } - } - path::Axis::Unparse { module, name } => { - if let Some(p) = - interpret::Context::new(&ctxt.env.0).dynamic_unparse(module, name, value) - { - self.step.accept(ctxt, &p) - } - } - }) - } - - delegate_finish_and_reset!(self, self.step); -} - -fn step_index, F: FnOnce(T) -> IOValue>( - ctxt: &mut Context, - mut vs: Ts, - key: &IOValue, - f: F, - step: &mut Node, -) { - if let Some(i) = key.value().as_usize() { - match vs.nth(i) { - None => (), - Some(v) => step.accept(ctxt, &f(v)), - } - } -} - -fn step_keys(ctxt: &mut Context, count: usize, step: &mut Node) { - for i in 0..count { - step.accept(ctxt, &IOValue::new(i)) - } -} - -impl StepMaker for path::Filter { - fn connect(&self, step: Node) -> Result { - match self { - path::Filter::Nop => Ok(step), - path::Filter::Compare { op, literal } => Ok(Node::new(CompareStep { - op: (**op).clone(), - literal: literal.clone(), - step, - })), - path::Filter::Regex { regex } => Ok(Node::new(RegexStep { - regex: regex::Regex::new(regex)?, - step, - })), - path::Filter::Test { pred } => Ok(Node::new(TestStep { - pred: (&**pred).compile()?, - step, - })), - path::Filter::Real => Ok(Node::new(RealStep { step })), - path::Filter::Int => Ok(Node::new(IntStep { step })), - path::Filter::Kind { kind } => Ok(Node::new(KindStep { - kind: match &**kind { - path::ValueKind::Boolean => ValueClass::Atomic(AtomClass::Boolean), - path::ValueKind::Double => ValueClass::Atomic(AtomClass::Double), - path::ValueKind::SignedInteger => ValueClass::Atomic(AtomClass::SignedInteger), - path::ValueKind::String => ValueClass::Atomic(AtomClass::String), - path::ValueKind::ByteString => ValueClass::Atomic(AtomClass::ByteString), - path::ValueKind::Symbol => ValueClass::Atomic(AtomClass::Symbol), - path::ValueKind::Record => ValueClass::Compound(CompoundClass::Record), - path::ValueKind::Sequence => ValueClass::Compound(CompoundClass::Sequence), - path::ValueKind::Set => ValueClass::Compound(CompoundClass::Set), - path::ValueKind::Dictionary => ValueClass::Compound(CompoundClass::Dictionary), - path::ValueKind::Embedded => ValueClass::Embedded, - }, - step, - })), - } - } -} - -impl Step for CompareStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - if match self.op { - path::Comparison::Eq => value == &self.literal, - path::Comparison::Ne => value != &self.literal, - path::Comparison::Lt => value < &self.literal, - path::Comparison::Ge => value >= &self.literal, - path::Comparison::Gt => value > &self.literal, - path::Comparison::Le => value <= &self.literal, - } { - self.step.accept(ctxt, value) - } - } - - delegate_finish_and_reset!(self, self.step); -} - -impl Step for RegexStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - match value.value() { - Value::String(s) | Value::Symbol(s) => { - if self.regex.is_match(s) { - self.step.accept(ctxt, value) - } - } - _ => (), - } - } - - delegate_finish_and_reset!(self, self.step); -} - -impl Step for TestStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - if self.pred.test(ctxt, value) { - self.step.accept(ctxt, value) - } - } - - delegate_finish_and_reset!(self, self.step); -} - -impl Step for RealStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - match value.value() { - Value::SignedInteger(i) => { - if let Some(r) = BigInt::from(i).to_f64() { - self.step.accept(ctxt, &IOValue::new(r)) - } - } - Value::Double(_) => self.step.accept(ctxt, value), - _ => (), - } - } - - delegate_finish_and_reset!(self, self.step); -} - -impl Step for IntStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - match value.value() { - Value::SignedInteger(_) => self.step.accept(ctxt, value), - Value::Double(d) => { - if let Some(i) = BigInt::from_f64(f64::from(*d)) { - self.step.accept(ctxt, &IOValue::new(i)) - } - } - _ => (), - } - } - - delegate_finish_and_reset!(self, self.step); -} - -impl VecCollector { - fn new() -> Node { - Node::new(VecCollector { - accumulator: Vec::new(), - }) - } -} - -impl Step for VecCollector { - fn accept(&mut self, _ctxt: &mut Context, value: &IOValue) { - self.accumulator.push(value.clone()) - } - - fn finish(&mut self) {} - - fn reset(&mut self) -> Vec { - std::mem::take(&mut self.accumulator) - } -} - -impl BoolCollector { - pub fn new() -> Node { - Node::new(BoolCollector { seen_value: false }) - } -} - -impl Step for BoolCollector { - fn accept(&mut self, _ctxt: &mut Context, _value: &IOValue) { - self.seen_value = true - } - - fn finish(&mut self) {} - - fn reset(&mut self) -> Vec { - let result = if self.seen_value { - vec![IOValue::new(true)] - } else { - vec![] - }; - self.seen_value = false; - result - } -} - -impl Step for KindStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - if value.value_class() == self.kind { - self.step.accept(ctxt, value) - } - } - - delegate_finish_and_reset!(self, self.step); -} - -impl path::Selector { - pub fn compile(&self) -> Result { - self.connect(VecCollector::new()) - } - - pub fn exec( - &self, - ctxt: &mut Context, - value: &IOValue, - ) -> Result, CompilationError> { - Ok(self.compile()?.exec(ctxt, value)) - } -} - -impl StepMaker for path::Function { - fn connect(&self, step: Node) -> Result { - // For now, there's just one function: `count`. - Ok(Node::new(CountStep { - step, - counter: self.selector.connect(CountCollector::new())?, - })) - } -} - -impl CountCollector { - pub fn new() -> Node { - Node::new(CountCollector { count: 0 }) - } -} - -impl Step for CountCollector { - fn accept(&mut self, _ctxt: &mut Context, _value: &IOValue) { - self.count += 1 - } - - fn finish(&mut self) {} - - fn reset(&mut self) -> Vec { - let result = vec![IOValue::new(self.count)]; - self.count = 0; - result - } -} - -impl Step for CountStep { - fn accept(&mut self, ctxt: &mut Context, value: &IOValue) { - let count = &self.counter.exec(ctxt, value)[0]; - self.step.accept(ctxt, count) - } - - delegate_finish_and_reset!(self, self.step); -} diff --git a/implementations/rust/preserves-schema-macros/Cargo.toml b/implementations/rust/preserves-schema-macros/Cargo.toml deleted file mode 100644 index 867fd67..0000000 --- a/implementations/rust/preserves-schema-macros/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "preserves-schema-macros" -version = "0.993.0" -authors = ["Tony Garnock-Jones "] -edition = "2018" -description = "Implementation of Preserves Schema code generation macros for Rust." -homepage = "https://preserves.dev/" -repository = "https://gitlab.com/preserves/preserves" -license = "Apache-2.0" - -[lib] -proc-macro = true - -[dependencies] -preserves = { path = "../preserves", version = "4.993.0" } -preserves-schema = { path = "../preserves-schema", version = "5.993.0" } - -proc-macro2 = { version = "1", features = ["span-locations"] } -quote = "1" -syn = { version = "2", features = ["parsing", "extra-traits", "full"] } - -[package.metadata.workspaces] -independent = true diff --git a/implementations/rust/preserves-schema-macros/src/lib.rs b/implementations/rust/preserves-schema-macros/src/lib.rs deleted file mode 100644 index 1d9beb6..0000000 --- a/implementations/rust/preserves-schema-macros/src/lib.rs +++ /dev/null @@ -1,227 +0,0 @@ -use preserves::value::Map; -use preserves_schema::compiler::*; -use preserves_schema::compiler::types::Purpose; -use preserves_schema::gen::schema::Schema; -use proc_macro2::Span; -use quote::ToTokens; -use quote::quote; -use std::fmt::Display; -use syn::LitStr; -use syn::Token; -use syn::parenthesized; -use syn::parse::Parser; -use syn::punctuated::Punctuated; - -mod kw { - use syn::custom_keyword; - custom_keyword!(load); - custom_keyword!(cross_reference); - custom_keyword!(external_module); -} - -#[derive(Debug)] -enum Instruction { - Namespace(String), - Load(LitStr), - CrossReference { - namespace: String, - bundle_path: LitStr, - }, - ExternalModule { - module_path: ModulePath, - namespace: String, - } -} - -fn syn_path_string(p: syn::Path) -> String { - p.to_token_stream().to_string().replace(&[' ', '\t', '\n', '\r'], "") -} - -fn syn_litstr_resolve(s: &syn::LitStr) -> String { - let s: String = s.value(); - match s.chars().nth(0) { - Some('/') => s.into(), - Some('<') => match &s[1..].split_once('>') { - Some((envvar, remainder)) => match std::env::var(envvar) { - Ok(p) => p + "/" + remainder, - Err(_) => panic!("No such environment variable: {:?}", s), - } - None => panic!("Invalid relative path syntax: {:?}", s), - }, - _ => panic!("Invalid path syntax: {:?}", s) - } -} - -impl syn::parse::Parse for Instruction { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let lookahead = input.lookahead1(); - if lookahead.peek(kw::load) { - let _: kw::load = input.parse()?; - let content; - let _ = parenthesized!(content in input); - let bundle_path: syn::LitStr = content.parse()?; - Ok(Instruction::Load(bundle_path)) - } else if lookahead.peek(kw::cross_reference) { - let _: kw::cross_reference = input.parse()?; - let content; - let _ = parenthesized!(content in input); - let namespace: syn::Path = content.parse()?; - let _: Token![=] = content.parse()?; - let bundle_path: syn::LitStr = content.parse()?; - Ok(Instruction::CrossReference { - namespace: syn_path_string(namespace), - bundle_path, - }) - } else if lookahead.peek(kw::external_module) { - let _: kw::external_module = input.parse()?; - let content; - let _ = parenthesized!(content in input); - let module_path = Punctuated::::parse_separated_nonempty(&content)?; - let _: Token![=] = content.parse()?; - let namespace: syn::Path = content.parse()?; - Ok(Instruction::ExternalModule { - module_path: module_path.into_iter().map(|p| p.to_string()).collect(), - namespace: syn_path_string(namespace), - }) - } else { - let ns: syn::Path = input.parse()?; - Ok(Instruction::Namespace(syn_path_string(ns))) - } - } -} - -struct ModuleTree { - own_body: String, - children: Map, -} - -impl Default for ModuleTree { - fn default() -> Self { - ModuleTree { - own_body: String::new(), - children: Map::default(), - } - } -} - -impl ModuleTree { - fn build(outputs: Map, String>) -> Self { - let mut mt = ModuleTree::default(); - for (p, c) in outputs.into_iter() { - match p { - None => mt.own_body = c, - Some(k) => { - let mut r = &mut mt; - for e in k { r = mt.children.entry(names::render_modname(&e)).or_default(); } - r.own_body = c; - } - } - } - mt - } -} - -impl Display for ModuleTree { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.own_body)?; - for (label, mt) in self.children.iter() { - write!(f, "\npub mod {} {{ ", label)?; - mt.fmt(f)?; - write!(f, "}}")?; - } - Ok(()) - } -} - -#[proc_macro] -pub fn compile_preserves_schemas(src: proc_macro::TokenStream) -> proc_macro::TokenStream { - let instructions = Punctuated::::parse_terminated - .parse(src) - .expect("valid sequence of compile_preserves_schemas instructions"); - - let mut namespace = None::; - let mut bundles_to_load = Vec::::new(); - let mut bundles_to_xref = Vec::::new(); - let mut external_modules = Vec::::new(); - - for i in instructions.into_iter() { - match i { - Instruction::Namespace(n) => { - if namespace.is_some() { - panic!("Only one namespace is permitted") - } - namespace = Some(n) - } - Instruction::Load(p) => bundles_to_load.push(p), - Instruction::ExternalModule { module_path, namespace } => { - external_modules.push(ExternalModule::new(module_path, &namespace)); - } - Instruction::CrossReference { namespace, bundle_path } => { - let mut bundle = Map::::new(); - let is_schema = load_schema_or_bundle(&mut bundle, &syn_litstr_resolve(&bundle_path).into()) - .expect("Invalid schema/bundle binary"); - bundles_to_xref.push(bundle_path); - for (k, _v) in bundle.into_iter() { - external_modules.push(if is_schema { - ExternalModule::new(k, &namespace) - } else { - let ns = namespace.clone(); - let mut pieces = vec![ns.clone()]; - pieces.extend( - k.iter().map(|p| names::render_modname(&p)).collect::>()); - ExternalModule::new(k, &pieces.join("::")) - .set_fallback_language_types( - move |v| vec![format!("{}::Language<{}>", ns, v)].into_iter().collect()) - }); - } - } - } - } - - let namespace = namespace.expect("Missing namespace"); - - let mut dependency_paths = Vec::::new(); - - let mut c = CompilerConfig::new(namespace.clone()); - for b in bundles_to_load.into_iter() { - dependency_paths.push(syn::LitStr::new(&syn_litstr_resolve(&b), Span::call_site())); - load_schema_or_bundle_with_purpose(&mut c.bundle, &syn_litstr_resolve(&b).into(), Purpose::Codegen) - .expect(&b.value()); - } - for b in bundles_to_xref.into_iter() { - dependency_paths.push(syn::LitStr::new(&syn_litstr_resolve(&b), Span::call_site())); - load_schema_or_bundle_with_purpose(&mut c.bundle, &syn_litstr_resolve(&b).into(), Purpose::Xref) - .expect(&b.value()); - } - for m in external_modules.into_iter() { - c.add_external_module(m); - } - - let mut outputs = Map::, String>::new(); - let mut collector = CodeCollector { - emit_mod_declarations: false, - collect_module: CodeModuleCollector::Custom { - collect_output: &mut |p, c| { - outputs.insert(p.cloned(), c.to_owned()); - Ok(()) - }, - }, - }; - compile(&c, &mut collector).expect("Compilation failed"); - - let top_module_source = format!( - "pub mod {} {{ {} }}", - names::render_modname(namespace.split("::").last().unwrap()), - ModuleTree::build(outputs)); - let top_module: syn::Item = syn::parse_str(&top_module_source) - .expect("Invalid generated code"); - - quote!{ - // TODO: this is ugly, but makes the code depend on the actual schema bundle: - // See https://doc.rust-lang.org/nightly/proc_macro/tracked_path/fn.path.html - // and https://github.com/rust-lang/rust/issues/99515 - #( const _: &'static [u8] = include_bytes!(#dependency_paths); )* - - #top_module - }.into() -} diff --git a/implementations/rust/preserves-schema/Cargo.toml b/implementations/rust/preserves-schema/Cargo.toml deleted file mode 100644 index 5f295eb..0000000 --- a/implementations/rust/preserves-schema/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "preserves-schema" -version = "5.993.0" -authors = ["Tony Garnock-Jones "] -edition = "2018" -description = "Implementation of Preserves Schema code generation and support for Rust." -homepage = "https://preserves.dev/" -repository = "https://gitlab.com/preserves/preserves" -license = "Apache-2.0" - -[dependencies] -preserves = { path = "../preserves", version = "4.993.0"} - -convert_case = "0.4.0" -glob = "0.3.0" -lazy_static = "1.4.0" -regex = "1.5" -structopt = "0.3.14" -thiserror = "1.0" - -[package.metadata.workspaces] -independent = true diff --git a/implementations/rust/preserves-schema/Makefile b/implementations/rust/preserves-schema/Makefile deleted file mode 100644 index 4363381..0000000 --- a/implementations/rust/preserves-schema/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: - @echo please use cargo - -regenerate: - cargo run -- \ - --prefix crate::gen \ - --support-crate crate \ - --rustfmt-skip \ - -o $(CURDIR)/src/gen \ - ../../../schema/schema.bin diff --git a/implementations/rust/preserves-schema/README.md b/implementations/rust/preserves-schema/README.md deleted file mode 100644 index 5392f8c..0000000 --- a/implementations/rust/preserves-schema/README.md +++ /dev/null @@ -1,6 +0,0 @@ -```shell -cargo add preserves preserves-schema -``` - -This crate ([`preserves-schema` on crates.io](https://crates.io/crates/preserves-schema)) is an -implementation of [Preserves Schema](https://preserves.dev/preserves-schema.html) for Rust. diff --git a/implementations/rust/preserves-schema/doc/example.md b/implementations/rust/preserves-schema/doc/example.md deleted file mode 100644 index 8520813..0000000 --- a/implementations/rust/preserves-schema/doc/example.md +++ /dev/null @@ -1,112 +0,0 @@ -# Example - -[preserves-schemac]: https://preserves.dev/doc/preserves-schemac.html -[preserves-schema-rs]: https://preserves.dev/doc/preserves-schema-rs.html - -Preserves schemas are written in a syntax that (ab)uses [Preserves text -syntax][preserves::value::text] as a kind of S-expression. Schema source code looks like this: - -```preserves-schema -version 1 . -Present = . -Says = . -UserStatus = . -Status = =here / . -TimeStamp = string . -``` - -Conventionally, schema source code is stored in `*.prs` files. In this example, the source code -above is placed in `simpleChatProtocol.prs`. - -The Rust code generator for schemas requires not source code, but instances of the [Preserves -metaschema](https://preserves.dev/preserves-schema.html#appendix-metaschema). To compile schema -source code to metaschema instances, use [preserves-schemac][]: - -```shell -yarn global add @preserves/schema -preserves-schemac .:simpleChatProtocol.prs > simpleChatProtocol.prb -``` - -Binary-syntax metaschema instances are conventionally stored in `*.prb` files. If you have a -whole directory tree of `*.prs` files, you can supply just "`.`" without the "`:`"-prefixed -fileglob part.[^converting-metaschema-to-text] See the [preserves-schemac documentation][preserves-schemac]. - -[^converting-metaschema-to-text]: - Converting the `simpleChatProtocol.prb` file to Preserves text syntax lets us read the - metaschema instance corresponding to the source code: - ```shell - cat simpleChatProtocol.prb | preserves-tool convert - ``` - The result: - ```preserves - > - ]>> - Says: > - > - ]>> - Status: - ] - [ - "away" - > - ]>> - ] - ]> - TimeStamp: - UserStatus: > - > - ]>> - } - embeddedType: #f - version: 1 - }> - }> - ``` - -#### Generating Rust code from a schema - -Generate Rust definitions corresponding to a metaschema instance with [preserves-schema-rs][]. -The best way to use it is to integrate it into your `build.rs` (see [the -docs][preserves-schema-rs]), but you can also use it as a standalone command-line tool. - -The following command generates a directory `./rs/chat` containing rust sources for a module -that expects to be called `chat` in Rust code: - -```shell -preserves-schema-rs --output-dir rs/chat --prefix chat simpleChatProtocol.prb -``` - -Representative excerpts from one of the generated files, `./rs/chat/simple_chat_protocol.rs`: - -```rust,noplayground -pub struct Present { - pub username: std::string::String -} -pub struct Says { - pub who: std::string::String, - pub what: std::string::String -} -pub struct UserStatus { - pub username: std::string::String, - pub status: Status -} -pub enum Status { - Here, - Away { - since: std::boxed::Box - } -} -pub struct TimeStamp(pub std::string::String); -``` diff --git a/implementations/rust/preserves-schema/doc/what-is-preserves-schema.md b/implementations/rust/preserves-schema/doc/what-is-preserves-schema.md deleted file mode 100644 index 20c47d0..0000000 --- a/implementations/rust/preserves-schema/doc/what-is-preserves-schema.md +++ /dev/null @@ -1,16 +0,0 @@ -A Preserves schema connects Preserves `Value`s to host-language data -structures. Each definition within a schema can be processed by a -compiler to produce - - - a simple host-language *type definition*; - - - a partial *parsing* function from `Value`s to instances of the - produced type; and - - - a total *serialization* function from instances of the type to - `Value`s. - -Every parsed `Value` retains enough information to always be able to -be serialized again, and every instance of a host-language data -structure contains, by construction, enough information to be -successfully serialized. diff --git a/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs b/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs deleted file mode 100644 index 65bd366..0000000 --- a/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! Command-line Rust code generator for Preserves Schema. See the documentation at -//! . - -use std::io::Error; -use std::io::ErrorKind; -use std::path::PathBuf; -use structopt::StructOpt; - -use preserves_schema::compiler::CodeCollector; -use preserves_schema::compiler::CompilerConfig; -use preserves_schema::compiler::ExternalModule; -use preserves_schema::compiler::compile; -use preserves_schema::compiler::expand_inputs; - -#[derive(Clone, StructOpt, Debug)] -struct CommandLine { - #[structopt(short, long)] - output_dir: PathBuf, - - #[structopt(short, long)] - prefix: String, - - #[structopt(long)] - support_crate: Option, - - #[structopt(long)] - module: Vec, - - #[structopt(long)] - xref: Vec, - - #[structopt(long)] - rustfmt_skip: bool, - - input_glob: Vec, -} - -fn main() -> Result<(), Error> { - let args = CommandLine::from_args(); - let mut config = CompilerConfig::new(args.prefix); - for alias in args.module { - let (modulepath_str, target) = { - let pieces: Vec<&str> = alias.split('=').collect(); - if pieces.len() != 2 { - return Err(Error::new( - ErrorKind::InvalidData, - format!("Invalid module alias: {:?}", alias), - )); - } - (pieces[0], pieces[1]) - }; - let modulepath: Vec = modulepath_str.split('.').map(str::to_owned).collect(); - config.add_external_module(ExternalModule::new(modulepath, target)); - } - if let Some(c) = args.support_crate { - config.support_crate = c; - } - config.rustfmt_skip = args.rustfmt_skip; - config.load_schemas_and_bundles( - &expand_inputs(&args.input_glob)?, - &expand_inputs(&args.xref)?, - )?; - compile(&config, &mut CodeCollector::files(args.output_dir)) -} diff --git a/implementations/rust/preserves-schema/src/compiler/context.rs b/implementations/rust/preserves-schema/src/compiler/context.rs deleted file mode 100644 index 4e8725d..0000000 --- a/implementations/rust/preserves-schema/src/compiler/context.rs +++ /dev/null @@ -1,377 +0,0 @@ -use crate::gen::schema::*; -use crate::syntax::block::constructors::*; -use crate::syntax::block::escape_string; -use crate::syntax::block::Item; -use crate::*; - -use convert_case::{Case, Casing}; - -use lazy_static::lazy_static; - -use preserves::value::IOValue; -use preserves::value::Map; -use preserves::value::NestedValue; -use preserves::value::Value; - -use super::names; -use super::types; -use super::types::Purpose; -use super::CompilerConfig; - -pub struct BundleContext<'b> { - pub config: &'b CompilerConfig, - pub types: Map, - pub literals: Map, -} - -#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] -pub enum ModuleContextMode { - TargetModule, - TargetToplevel, - TargetGeneric, -} - -pub struct ModuleContext<'m, 'b> { - pub bundle: &'m mut BundleContext<'b>, - pub module_path: ModulePath, - pub schema: &'m Schema, - pub typedefs: Vec, - pub functiondefs: Vec, - pub mode: ModuleContextMode, -} - -pub struct FunctionContext<'a, 'm, 'b> { - pub error_context: String, - pub m: &'a mut ModuleContext<'m, 'b>, - pub temp_counter: usize, - pub captures: Vec, - pub capture_mode: CaptureMode, -} - -pub struct Capture { - pub field_name: String, - pub ty: types::TField, - pub source_expr: String, -} - -pub enum CaptureMode { - Definite, - Indefinite(Vec), -} - -pub enum RefRenderStyle { - Bare, - Qualified, -} - -lazy_static! { - static ref ID_RE: regex::Regex = regex::Regex::new(r"^[a-zA-Z][a-zA-Z_0-9]*$").unwrap(); -} - -impl<'b> BundleContext<'b> { - pub fn new(config: &'b CompilerConfig) -> Self { - BundleContext { - config, - types: config.build_type_cache(), - literals: Map::new(), - } - } - - pub fn any_type(&self) -> &'static str { - "_Value" - } - - pub fn lookup_definition(&self, r: &Ref) -> Option<(&Definition, Purpose)> { - self.config - .bundle - .get(&r.module.0) - .and_then(|s| s.0.definitions.0.get(&r.name).map(|d| (d, s.1))) - } - - pub fn type_for_name(&self, r: &Ref) -> Option<&types::TDefinition> { - if r.module.0.is_empty() { - panic!( - "BundleContext::type_for_name with module-relative ref {:?}", - r - ); - } - let result = self.types.get(r); - if result.is_none() && !self.config.external_modules.contains_key(&r.module.0) { - panic!("Attempted to lookup unknown type {:?}", r) - } - result - } - - pub fn define_literal(&mut self, v: &IOValue) -> String { - let prefix = format!("LIT_{}", self.literals.len()); - let next_id = match v.value() { - Value::Boolean(b) => prefix + "_" + &b.to_string(), - Value::Symbol(s) => { - if ID_RE.is_match(&s) { - prefix + "_" + s - } else { - prefix - } - } - Value::String(s) => { - if ID_RE.is_match(&s) { - prefix + "_" + s - } else { - prefix - } - } - Value::SignedInteger(n) => prefix + "_" + &n.to_string(), - _ => prefix, - }; - let next_id = next_id.to_case(Case::UpperSnake); - format!( - "&<_L as Into<&'a {}>>::into(_ctxt).{}", - self.language_type(), - self.literals.entry(v.clone()).or_insert(next_id) - ) - } - - pub fn generate_module( - &mut self, - path: &Vec, - schema: &Schema, - mode: ModuleContextMode, - items: &mut Map>, - f: F, - ) { - let mut m = ModuleContext::new(self, &ModulePath(path.clone()), schema, mode); - f(&mut m); - items.entry(mode).or_default().extend(m.extract()); - } - - pub fn language_struct_name(&self) -> &'static str { - "Language" - } - - pub fn language_type_base(&self) -> String { - format!( - "{}::{}", - self.config.fully_qualified_module_prefix.clone(), - self.language_struct_name() - ) - } - - pub fn language_type(&self) -> String { - format!("{}<{}>", self.language_type_base(), self.any_type()) - } -} - -impl<'m, 'b> ModuleContext<'m, 'b> { - pub fn new( - bundle: &'m mut BundleContext<'b>, - module_path: &ModulePath, - schema: &'m Schema, - mode: ModuleContextMode, - ) -> Self { - ModuleContext { - bundle, - module_path: module_path.to_owned(), - schema, - typedefs: Vec::new(), - functiondefs: Vec::new(), - mode, - } - } - - pub fn any_type(&self) -> &'static str { - self.bundle.any_type() - } - - pub fn reset_mode(&mut self) { - self.mode = ModuleContextMode::TargetToplevel; - } - - pub fn define_literal(&mut self, v: &IOValue) -> String { - self.bundle.define_literal(v) - } - - pub fn define_type(&mut self, i: Item) { - self.typedefs.push(i) - } - - pub fn define_function Item>( - &mut self, - error_context: &str, - f: F, - ) { - let i = f(FunctionContext::new(self, error_context)); - self.functiondefs.push(i) - } - - pub fn render_ref(&self, r: &Ref, style: RefRenderStyle) -> Item { - let base = match self.bundle.config.external_modules.get(&r.module.0) { - None => { - if r.module.0.is_empty() { - item(names::render_constructor(&r.name)) - } else { - let mut items = Vec::new(); - items.push(item( - self.bundle.config.fully_qualified_module_prefix.to_owned(), - )); - for p in &r.module.0 { - items.push(item(names::render_modname(p))) - } - items.push(item(names::render_constructor(&r.name))); - item(name(items)) - } - } - Some(xm) => item(name![ - xm.rust_namespace.clone(), - names::render_constructor(&r.name) - ]), - }; - let q = self.ref_has_embedded(r); - match style { - RefRenderStyle::Bare => base, - RefRenderStyle::Qualified => { - if q { - item(seq![base, anglebrackets![self.any_type()]]) - } else { - base - } - } - } - } - - pub fn ref_has_embedded(&self, r: &Ref) -> bool { - let r = r.qualify(&self.module_path); - self.bundle - .type_for_name(&r) - .map(|ty| ty.has_embedded(self.bundle)) - .unwrap_or(false) - // ^ TODO: should the "false" be configurable? - } - - pub fn parse_unparse_generic_decls(&self, ty: &types::TDefinition) -> Item { - let mut lts = ty.language_types(self.bundle); - lts.insert(self.bundle.language_type()); - item(anglebrackets![ - "'a", - seq![ - "_L: Copy", - seq(lts - .into_iter() - .map(|t| item(seq![" + Into<&'a ", t, ">"])) - .collect()) - ], - seq![self.any_type(), ": preserves::value::NestedValue + 'a"] - ]) - } - - pub fn extract(&mut self) -> Vec { - let mut items = std::mem::take(&mut self.typedefs); - items.extend(std::mem::take(&mut self.functiondefs)); - items - } -} - -impl<'a, 'm, 'b> FunctionContext<'a, 'm, 'b> { - pub fn new(m: &'a mut ModuleContext<'m, 'b>, error_context: &str) -> Self { - FunctionContext { - error_context: error_context.to_owned(), - m, - temp_counter: 0, - captures: Vec::new(), - capture_mode: CaptureMode::Definite, - } - } - - pub fn capture(&mut self, field_name: String, ty: types::TField, source_expr: String) { - self.captures.push(Capture { - field_name, - ty, - source_expr: match self.capture_mode { - CaptureMode::Definite => source_expr, - CaptureMode::Indefinite(_) => format!( - "{}.ok_or_else(|| {:?})?", - source_expr, - self.conformance_err_code() - ), - }, - }) - } - - pub fn lookup_capture(&self, field_name: &str) -> &Capture { - for c in &self.captures { - if c.field_name == field_name { - return c; - } - } - panic!("No capture for field {:?} available", field_name) - } - - pub fn gentempname(&mut self) -> String { - let i = self.temp_counter; - self.temp_counter += 1; - 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_definite_mode R>(&mut self, f: F) -> R { - let saved_mode = std::mem::replace(&mut self.capture_mode, CaptureMode::Definite); - let result = f(self); - match std::mem::replace(&mut self.capture_mode, saved_mode) { - CaptureMode::Definite => (), - CaptureMode::Indefinite(_) => panic!("corrupt capture_mode"), - } - result - } - - 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(); - let result = f(self); - self.temp_counter = saved_temp_counter; - self.captures.truncate(saved_capture_count); - result - } - - pub fn err_code(&self) -> Item { - return item(seq!["Err", parens![self.conformance_err_code()]]); - } - - pub fn fully_qualified_error_context(&self) -> String { - self.m.module_path.0.join(".") + "." + &self.error_context - } - - pub fn conformance_err_code(&self) -> Item { - return item(seq![ - "_support::ParseError::conformance_error", - parens![escape_string(&self.fully_qualified_error_context())] - ]); - } -} diff --git a/implementations/rust/preserves-schema/src/compiler/cycles.rs b/implementations/rust/preserves-schema/src/compiler/cycles.rs deleted file mode 100644 index 612f757..0000000 --- a/implementations/rust/preserves-schema/src/compiler/cycles.rs +++ /dev/null @@ -1,46 +0,0 @@ -use preserves::value::Set; - -use crate::gen::schema::ModulePath; -use crate::gen::schema::Ref; - -pub struct WalkState { - pub context: T, - pub module_path: ModulePath, - seen: Set, -} - -impl WalkState { - pub fn new(context: T, module_path: ModulePath) -> Self { - WalkState { - context, - module_path, - seen: Set::new(), - } - } - - pub fn cycle_check< - E, - F: Fn(&T, &Ref) -> Option, - R, - Ks: FnOnce(&mut Self, Option) -> R, - Kf: FnOnce() -> R, - >( - &mut self, - r: &Ref, - step: F, - ks: Ks, - kf: Kf, - ) -> R { - let r = r.qualify(&self.module_path); - if self.seen.contains(&r) { - kf() - } else { - self.seen.insert(r.clone()); - let maybe_e = step(&self.context, &r); - let saved = std::mem::replace(&mut self.module_path, r.module); - let result = ks(self, maybe_e); - self.module_path = saved; - result - } - } -} diff --git a/implementations/rust/preserves-schema/src/compiler/mod.rs b/implementations/rust/preserves-schema/src/compiler/mod.rs deleted file mode 100644 index 9f6ed2e..0000000 --- a/implementations/rust/preserves-schema/src/compiler/mod.rs +++ /dev/null @@ -1,636 +0,0 @@ -//! Implementation of the Schema-to-Rust compiler; this is the core of the -//! [preserves-schema-rs][] program. -//! -//! See the [documentation for preserves-schema-rs][preserves-schema-rs] for examples of how to -//! use the compiler programmatically from a `build.rs` script, but very briefly, use -//! [preserves-schemac](https://preserves.dev/doc/preserves-schemac.html) to generate a -//! metaschema instance `*.prb` file, and then put something like this in `build.rs`: -//! -//! ```rust,ignore -//! use preserves_schema::compiler::*; -//! -//! const PATH_TO_PRB_FILE: &'static str = "your-metaschema-instance-file.prb"; -//! -//! fn main() -> Result<(), std::io::Error> { -//! let buildroot = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); -//! -//! let mut gen_dir = buildroot.clone(); -//! gen_dir.push("src/schemas"); -//! let mut c = CompilerConfig::new("crate::schemas".to_owned()); -//! -//! let inputs = expand_inputs(&vec![PATH_TO_PRB_FILE.to_owned()])?; -//! c.load_schemas_and_bundles(&inputs, &vec![])?; -//! compile(&c, &mut CodeCollector::files(gen_dir)) -//! } -//! ``` -//! -//! plus something like this in your `lib.rs` or main program: -//! -//! ```rust,ignore -//! pub mod schemas { -//! include!(concat!(env!("OUT_DIR"), "/src/schemas/mod.rs")); -//! } -//! ``` -//! -//! [preserves-schema-rs]: https://preserves.dev/doc/preserves-schema-rs.html - -pub mod context; -pub mod cycles; -pub mod names; -pub mod parsers; -pub mod readers; -pub mod types; -pub mod unparsers; - -use crate::compiler::context::*; -use crate::compiler::types::Purpose; -use crate::gen::schema; -use crate::gen::schema::*; -use crate::gen::Language; -use crate::syntax::block::constructors::*; -use crate::syntax::block::{Formatter, Item}; -use crate::*; - -use glob::glob; -use preserves::value::BinarySource; -use preserves::value::BytesBinarySource; -use preserves::value::Map; -use preserves::value::Reader; -use preserves::value::Set; - -use std::fs::DirBuilder; -use std::fs::File; -use std::io; -use std::io::Read; -use std::io::Write; -use std::path::PathBuf; - -/// Names a Schema module within a (collection of) Schema bundle(s). -pub type ModulePath = Vec; - -/// Implement this trait to extend the compiler with custom code generation support. The main -/// code generators are also implemented as plugins. -/// -/// For an example of its use outside the core compiler, see [`build.rs` for the `syndicate-rs` project](https://git.syndicate-lang.org/syndicate-lang/syndicate-rs/src/commit/60e6c6badfcbcbccc902994f4f32db6048f60d1f/syndicate/build.rs). -pub trait Plugin: std::fmt::Debug { - /// Use `_module_ctxt` to emit code at a per-module level. - fn generate_module(&self, _module_ctxt: &mut ModuleContext) {} - - /// Use `module_ctxt` to emit code at a per-Schema-[Definition] level. - fn generate_definition( - &self, - module_ctxt: &mut ModuleContext, - definition_name: &str, - definition: &Definition, - ); -} - -pub struct LanguageTypes { - pub fallback: Option Set>>, - pub definitions: Map Set>>, -} - -impl std::fmt::Debug for LanguageTypes { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - f.debug_struct("LanguageTypes") - .field("fallback", &self.fallback.as_ref().map(|f| f("_"))) - .field( - "definitions", - &self - .definitions - .iter() - .map(|(k, f)| (k.clone(), f("_"))) - .collect::>>(), - ) - .finish() - } -} - -#[derive(Debug)] -pub struct ExternalModule { - pub path: ModulePath, - pub rust_namespace: String, - pub rust_language_types: LanguageTypes, -} - -impl ExternalModule { - pub fn new(path: ModulePath, rust_namespace: &str) -> Self { - ExternalModule { - path, - rust_namespace: rust_namespace.to_owned(), - rust_language_types: LanguageTypes { - fallback: None, - definitions: Map::new(), - }, - } - } - - pub fn set_fallback_language_types Set>( - mut self, - f: F, - ) -> Self { - self.rust_language_types.fallback = Some(Box::new(f)); - self - } - - pub fn set_definition_language_types Set>( - mut self, - d: &str, - f: F, - ) -> Self { - if self - .rust_language_types - .definitions - .insert(d.to_owned(), Box::new(f)) - .is_some() - { - panic!( - "Duplicate language types definition installed: {:?} {:?}", - &self.path, d - ); - } - self - } -} - -/// Used to collect output from the compiler. -pub enum CodeModuleCollector<'a> { - /// Default file-based code emitter. - Files { - /// Where output Rust code files will be placed. - output_dir: PathBuf, - }, - Custom { - /// Used to collect the various produced source files. - /// Useful for when compiling in e.g. proc_macro context. - collect_output: &'a mut dyn FnMut(Option<&ModulePath>, &str) -> io::Result<()>, - }, -} - -/// Used to configure and collect output from the compiler. -pub struct CodeCollector<'a> { - pub emit_mod_declarations: bool, - pub collect_module: CodeModuleCollector<'a>, -} - -/// Main entry point to the compiler. -#[derive(Debug)] -pub struct CompilerConfig { - /// All known Schema modules, indexed by [ModulePath] and annotated with a [Purpose]. - pub bundle: Map, - /// Fully-qualified Rust module prefix to use for each generated module. - pub fully_qualified_module_prefix: String, - /// Rust module path to the [preserves_schema::support][crate::support] module. - pub support_crate: String, - /// External modules for cross-referencing. - pub external_modules: Map, - /// Plugins active in this compiler instance. - pub plugins: Vec>, - /// If true, a directive is emitted in each module instructing - /// [rustfmt](https://github.com/rust-lang/rustfmt) to ignore it. - pub rustfmt_skip: bool, -} - -/// Loads a [Schema] or [Bundle] from path `i` into `bundle` for the given `purpose`. -/// -/// If `i` holds a [Schema], then the file stem of `i` is used as the module name when placing -/// the schema in `bundle`. -pub fn load_schema_or_bundle_with_purpose( - bundle: &mut Map, - i: &PathBuf, - purpose: Purpose, -) -> io::Result<()> { - let mut inserted = Map::::new(); - load_schema_or_bundle(&mut inserted, i)?; - for (k, v) in inserted.into_iter() { - bundle.insert(k, (v, purpose)); - } - Ok(()) -} - -/// Loads a [Schema] or [Bundle] from raw binary encoded value `input` into `bundle` for the -/// given `purpose`. -/// -/// If `input` corresponds to a [Schema], then `prefix` is used as its module name; otherwise, -/// it's a [Bundle], and `prefix` is ignored. -pub fn load_schema_or_bundle_bin_with_purpose( - bundle: &mut Map, - prefix: &str, - input: &[u8], - purpose: Purpose, -) -> io::Result<()> { - let mut inserted = Map::::new(); - load_schema_or_bundle_bin(&mut inserted, prefix, input)?; - for (k, v) in inserted.into_iter() { - bundle.insert(k, (v, purpose)); - } - Ok(()) -} - -fn bundle_prefix(i: &PathBuf) -> io::Result<&str> { - i.file_stem() - .ok_or_else(|| { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Bad schema file stem: {:?}", i), - ) - })? - .to_str() - .ok_or_else(|| { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Invalid UTF-8 in schema file name: {:?}", i), - ) - }) -} - -/// Loads a [Schema] or [Bundle] from path `i` into `bundle`. -/// -/// If `i` holds a [Schema], then the file stem of `i` is used as the module name when placing -/// the schema in `bundle`. -/// -/// Returns true if it was a schema, false if it was a bundle. -pub fn load_schema_or_bundle(bundle: &mut Map, i: &PathBuf) -> io::Result { - let mut f = File::open(&i)?; - let mut bs = vec![]; - f.read_to_end(&mut bs)?; - load_schema_or_bundle_bin(bundle, bundle_prefix(i)?, &bs[..]) -} - -/// Loads a [Schema] or [Bundle] from raw binary encoded value `input` into `bundle`. -/// -/// If `input` corresponds to a [Schema], then `prefix` is used as its module name; otherwise, -/// it's a [Bundle], and `prefix` is ignored. -/// -/// Returns true if it was a schema, false if it was a bundle. -pub fn load_schema_or_bundle_bin( - bundle: &mut Map, - prefix: &str, - input: &[u8], -) -> io::Result { - let mut src = BytesBinarySource::new(input); - let mut reader = src.packed_iovalues(); - let blob = reader.demand_next(false)?; - let language = Language::default(); - - if let Ok(s) = language.parse(&blob) { - bundle.insert(vec![prefix.to_owned()], s); - Ok(true) - } else if let Ok(Bundle { modules }) = language.parse(&blob) { - for (ModulePath(k), v) in modules.0 { - bundle.insert(k, v); - } - Ok(false) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - format!("Invalid schema binary blob {:?}", prefix), - )) - } -} - -impl CompilerConfig { - /// Construct a [CompilerConfig] configured to use `fully_qualified_module_prefix` as the - /// Rust module prefix for generated code. - pub fn new(fully_qualified_module_prefix: String) -> Self { - CompilerConfig { - bundle: Map::new(), - fully_qualified_module_prefix, - support_crate: "preserves_schema".to_owned(), - external_modules: Map::new(), - plugins: vec![ - Box::new(types::TypePlugin), - Box::new(readers::ReaderPlugin), - Box::new(parsers::ParserPlugin), - Box::new(unparsers::UnparserPlugin), - ], - rustfmt_skip: false, - } - } - - pub fn add_external_module(&mut self, m: ExternalModule) { - let path = m.path.clone(); - if self.external_modules.insert(path.clone(), m).is_some() { - panic!("Duplicate external module installed: {:?}", path) - } - } - - pub fn load_schemas_and_bundles( - &mut self, - inputs: &Vec, - xrefs: &Vec, - ) -> io::Result<()> { - for i in inputs { - load_schema_or_bundle_with_purpose(&mut self.bundle, i, Purpose::Codegen)?; - } - for i in xrefs { - load_schema_or_bundle_with_purpose(&mut self.bundle, i, Purpose::Xref)?; - } - Ok(()) - } - - pub fn load_xref_bin(&mut self, prefix: &str, bundle_or_schema: &[u8]) -> io::Result<()> { - load_schema_or_bundle_bin_with_purpose( - &mut self.bundle, - prefix, - bundle_or_schema, - Purpose::Xref, - ) - } - - fn build_type_cache(&self) -> Map { - self.bundle - .iter() - .flat_map(|(modpath, s)| { - let modpath = ModulePath(modpath.clone()); - s.0.definitions.0.iter().map(move |(name, def)| { - let ty = types::definition_type(&modpath, s.1, name, def); - (ty.self_ref.clone(), ty) - }) - }) - .collect() - } - - fn generate_definition( - &self, - b: &mut BundleContext, - k: &ModulePath, - v: &Schema, - n: &str, - d: &Definition, - mode: ModuleContextMode, - generated: &mut Map>, - ) { - b.generate_module(k, v, mode, generated, |m| { - for plugin in self.plugins.iter() { - plugin.generate_definition(m, n, d); - } - }); - } -} - -/// Expands a vector of [mod@glob]s to a vector of actual paths. -pub fn expand_inputs(globs: &Vec) -> io::Result> { - let mut result = Vec::new(); - for g in globs.iter() { - for p in - glob(g).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("{}", e)))? - { - result.push(p.map_err(glob::GlobError::into_error)?) - } - } - Ok(result) -} - -impl<'a> CodeCollector<'a> { - /// Construct a [CodeCollector] that collects output Rust modules directly into the file - /// system tree rooted at `output_dir`. - pub fn files(output_dir: PathBuf) -> Self { - CodeCollector { - emit_mod_declarations: true, - collect_module: CodeModuleCollector::Files { output_dir }, - } - } - - #[doc(hidden)] - pub fn collect_output(&mut self, module: Option<&ModulePath>, contents: &str) -> io::Result<()> { - match &mut self.collect_module { - CodeModuleCollector::Files { output_dir } => { - let mut output_path = output_dir.clone(); - if let Some(k) = module { - output_path.extend(k); - let module_name = output_path - .file_stem() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - let module_name = names::render_modname(&module_name); - output_path.set_file_name(format!("{}.rs", module_name)); - } else { - output_path.push("mod.rs"); - } - DirBuilder::new().recursive(true).create(output_path.parent().unwrap())?; - - if output_path.exists() { - if let Ok(mut f) = File::open(&output_path) { - let mut existing_contents = String::new(); - f.read_to_string(&mut existing_contents)?; - if existing_contents == contents { - return Ok(()); - } - } - } - - let mut f = File::create(output_path)?; - f.write_all(contents.as_bytes()) - } - CodeModuleCollector::Custom { collect_output } => { - collect_output(module, contents) - } - } - } -} - -impl Ref { - pub fn qualify(&self, default_module_path: &schema::ModulePath) -> Ref { - if self.module.0.is_empty() { - Ref { - module: default_module_path.clone(), - name: self.name.clone(), - } - } else { - self.clone() - } - } -} - -impl Schema { - pub fn has_embedded_type(&self) -> bool { - self.embedded_type != EmbeddedTypeName::False - } -} - -/// Main entry point: runs the compilation process. -pub fn compile<'a>(config: &CompilerConfig, emitter: &mut CodeCollector<'a>) -> io::Result<()> { - let mut b = BundleContext::new(config); - - for (k, (v, module_purpose)) in config.bundle.iter() { - if *module_purpose != Purpose::Codegen { - continue; - } - - //--------------------------------------------------------------------------- - - let mut generated = Map::new(); - - b.generate_module(k, v, ModuleContextMode::TargetModule, &mut generated, |m| { - for plugin in config.plugins.iter() { - plugin.generate_module(m); - } - }); - - for (n, d) in &v.definitions.0 { - use ModuleContextMode::*; - config.generate_definition(&mut b, k, v, n, d, TargetToplevel, &mut generated); - config.generate_definition(&mut b, k, v, n, d, TargetGeneric, &mut generated); - } - - //--------------------------------------------------------------------------- - - let mut lines: Vec = Vec::new(); - - lines.push(Formatter::to_string(vertical( - false, - seq!["#![allow(unused_parens)]", "#![allow(unused_imports)]"], - ))); - if config.rustfmt_skip { - lines.push("#![cfg_attr(rustfmt, rustfmt_skip)]".to_owned()); - } - lines.push(Formatter::to_string(vertical( - false, - seq![ - "", - "use std::convert::TryFrom;", - format!("use {}::support as _support;", &config.support_crate), - "use _support::Deserialize;", - "use _support::Parse;", - "use _support::Unparse;", - "use _support::preserves;", - "use preserves::value::Domain;", - "use preserves::value::NestedValue;", - "" - ], - ))); - - let mut emit_items = |items: Vec| { - if !items.is_empty() { - lines.push(Formatter::to_string(vertical(true, seq(items)))); - lines.push("".to_owned()); - } - }; - emit_items(generated.remove(&ModuleContextMode::TargetModule).unwrap()); - emit_items( - generated - .remove(&ModuleContextMode::TargetToplevel) - .unwrap(), - ); - emit_items(generated.remove(&ModuleContextMode::TargetGeneric).unwrap()); - - { - let contents = lines.join("\n"); - emitter.collect_output(Some(k), &contents)?; - } - } - - { - let mut lines = Vec::new(); - - if config.rustfmt_skip { - lines.push("#![cfg_attr(rustfmt, rustfmt_skip)]".to_owned()); - lines.push("".to_owned()); - } - - if emitter.emit_mod_declarations { - for (modpath, (_, module_purpose)) in config.bundle.iter() { - if *module_purpose != Purpose::Codegen { - continue; - } - lines.push(format!( - "pub mod {};", - names::render_modname(modpath.last().unwrap()) - )); - } - lines.push("".to_owned()); - } - - lines.push(format!( - "use {}::support as _support;", - &config.support_crate - )); - lines.push("use _support::preserves;".to_owned()); - lines.push("".to_owned()); - - lines.push("#[allow(non_snake_case)]".to_owned()); - lines.push(Formatter::to_string(item(seq![ - "pub struct ", - b.language_struct_name(), - anglebrackets!["N: preserves::value::NestedValue"], - " ", - vertical( - false, - braces( - b.literals - .iter() - .map(|(value, name)| item(format!("pub {}: N /* {:?} */", name, value))) - .collect() - ) - ) - ]))); - lines.push("".to_owned()); - lines.push(Formatter::to_string(item(seq![ - "impl", - anglebrackets!["N: preserves::value::NestedValue"], - " Default for ", - b.language_struct_name(), - " ", - codeblock![seq![ - "fn default() -> Self ", - codeblock![seq![ - b.language_struct_name(), - " ", - vertical( - false, - braces( - b.literals - .iter() - .map(|(value, name)| { - let bs = preserves::value::PackedWriter::encode_iovalue(&value) - .unwrap(); - item(format!( - "{}: /* {:?} */ _support::decode_lit(&{:?}).unwrap()", - name, value, bs - )) - }) - .collect() - ) - ) - ]] - ]] - ]))); - lines.push("".to_owned()); - { - let mut b = Bundle { - modules: Modules(Map::new()), - }; - for (modpath, (schema, purpose)) in config.bundle.iter() { - if *purpose == Purpose::Codegen { - b.modules - .0 - .insert(ModulePath(modpath.clone()), schema.clone()); - } - } - let b_value = Language::default().unparse(&b); - let b_bin = preserves::value::PackedWriter::encode_iovalue(&b_value).unwrap(); - let mut hex_encoded_bundle = String::new(); - let mut count = 0; - for b in b_bin { - if count % 16 == 0 { - hex_encoded_bundle.push_str("\\\n "); - } - count += 1; - hex_encoded_bundle.push_str(&format!("\\x{:02x}", b)); - } - lines.push(Formatter::to_string(item(seq![ - "pub fn _bundle() -> &'static [u8] ", - codeblock![seq!["b\"", hex_encoded_bundle, "\""]] - ]))); - } - lines.push("".to_owned()); - - let contents = lines.join("\n"); - emitter.collect_output(None, &contents)?; - } - - Ok(()) -} diff --git a/implementations/rust/preserves-schema/src/compiler/names.rs b/implementations/rust/preserves-schema/src/compiler/names.rs deleted file mode 100644 index 174f05f..0000000 --- a/implementations/rust/preserves-schema/src/compiler/names.rs +++ /dev/null @@ -1,13 +0,0 @@ -use convert_case::{Case, Casing}; - -pub fn render_constructor(n: &str) -> String { - n.to_case(Case::UpperCamel) -} - -pub fn render_fieldname(n: &str) -> String { - n.to_case(Case::Snake) -} - -pub fn render_modname(n: &str) -> String { - n.to_case(Case::Snake) -} diff --git a/implementations/rust/preserves-schema/src/compiler/parsers.rs b/implementations/rust/preserves-schema/src/compiler/parsers.rs deleted file mode 100644 index 2dfcb98..0000000 --- a/implementations/rust/preserves-schema/src/compiler/parsers.rs +++ /dev/null @@ -1,467 +0,0 @@ -use crate::gen::schema::*; -use crate::syntax::block::constructors::*; -use crate::syntax::block::Item; -use crate::*; - -use super::context::FunctionContext; -use super::context::ModuleContext; -use super::context::ModuleContextMode; -use super::context::RefRenderStyle; -use super::names; -use super::types::*; - -#[derive(Debug)] -pub struct ParserPlugin; - -impl compiler::Plugin for ParserPlugin { - fn generate_definition( - &self, - module_ctxt: &mut ModuleContext, - definition_name: &str, - definition: &Definition, - ) { - if let ModuleContextMode::TargetGeneric = module_ctxt.mode { - gen_definition_parser(module_ctxt, definition_name, definition) - } - } -} - -pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { - let ty = definition_type(&m.module_path, Purpose::Codegen, n, d); - - 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); - for NamedAlternative { - variant_label: name, - pattern: pat, - } in ps - { - let fname = seq![ - "parse_", - 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); - let dest = dest.as_ref().map(String::as_str); - construct(&ctxt, ctorname, false, &pattern_type(pat), dest, &mut body); - - item(seq![ - "fn ", - fname.clone(), - ctxt.m.parse_unparse_generic_decls(&ty), - "(_ctxt: _L, value: &", - ctxt.m.any_type(), - ") -> ", - "std::result::Result<", - names::render_constructor(n), - ty.generic_arg(ctxt.m), - ", _support::ParseError> ", - codeblock(body) - ]) - }); - body.push(item(seq![ - "if let Ok(r) = ", - fname, - "(_ctxt, value) { return Ok(r); }" - ])); - } - 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_parser(&mut ctxt, e, "value", None, &mut body); - } - construct( - &ctxt, - item(names::render_constructor(n)), - true, - &record_type(&ps), - None, - &mut body, - ); - } - Definition::Pattern(p) => { - let dest = pattern_parser(&mut ctxt, p, "value", None, &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", - ctxt.m.parse_unparse_generic_decls(&ty), - " _support::Parse", - anglebrackets!["_L", ctxt.m.any_type()], - " for ", - names::render_constructor(n), - ty.generic_arg(ctxt.m), - " ", - codeblock![seq![ - "fn parse(_ctxt: _L, value: &", - ctxt.m.any_type(), - ")", - " -> std::result::Result ", - codeblock(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(_) | TField::Any | TField::Embedded => format!("{}.clone()", expr), - } -} - -fn simple_pattern_parser( - ctxt: &mut FunctionContext, - p: &SimplePattern, - src: &str, - sequence_base: Option, - body: &mut Vec, -) -> String { - let dest = ctxt.gentempname(); - match p { - SimplePattern::Any => { - ctxt.define_atom(body, &dest, item(src.to_owned())); - dest - } - SimplePattern::Atom { atom_kind: k } => { - let converter = match &**k { - AtomKind::Boolean => "to_boolean", - AtomKind::Double => "to_double", - AtomKind::SignedInteger => "to_signedinteger", - AtomKind::String => "to_string", - AtomKind::ByteString => "to_bytestring", - AtomKind::Symbol => "to_symbol", - }; - ctxt.define_atom( - body, - &dest, - item(seq![src.to_owned(), ".value().", converter, "()?"]), - ); - dest - } - SimplePattern::Embedded { .. } => { - 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 ", - ctxt.err_code(), - "; }" - ])); - ctxt.define_atom(body, &dest, item("()")); - dest - } - SimplePattern::Seqof { pattern } => { - let (src, n) = sequenceify(ctxt, src, sequence_base, body); - let tmp = ctxt.gentempname(); - let mut inner = Vec::new(); - 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), - ");" - ])); - 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(), ".."]], - " ", - codeblock(inner) - ])); - dest - } - SimplePattern::Setof { pattern } => { - let tmp = ctxt.gentempname(); - let mut inner = Vec::new(); - 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), - ");" - ])); - 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()?", - " ", - codeblock(inner) - ])); - dest - } - SimplePattern::Dictof { key, value } => { - let tmp_key = ctxt.gentempname(); - let tmp_value = ctxt.gentempname(); - let mut inner = Vec::new(); - let key_dest = simple_pattern_parser(ctxt, key, &tmp_key, None, &mut inner); - let value_dest = simple_pattern_parser(ctxt, value, &tmp_value, None, &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![ - "for (", - tmp_key.to_owned(), - ", ", - tmp_value.to_owned(), - ")", - " in ", - src.to_owned(), - ".value().to_dictionary()?", - " ", - codeblock(inner) - ])); - dest - } - SimplePattern::Ref(r) => { - let tf = name![ctxt.m.render_ref(&**r, RefRenderStyle::Bare), "parse"]; - ctxt.define_atom( - body, - &dest, - item(seq![tf, parens!["_ctxt", src.to_owned()], "?"]), - ); - dest - } - } -} - -fn sequenceify( - ctxt: &mut FunctionContext, - src: &str, - sequence_base: Option, - body: &mut Vec, -) -> (String, usize) { - match sequence_base { - Some(n) => (src.to_owned(), n), - None => { - let tmp = ctxt.gentempname(); - ctxt.define_atom( - body, - &tmp, - item(seq![src.to_owned(), ".value().to_sequence()?"]), - ); - (tmp, 0) - } - } -} - -fn fixed_sequence_parser( - ctxt: &mut FunctionContext, - base: usize, - ps: &[NamedPattern], - src: &str, - body: &mut Vec, -) { - let mut i = base; - let required_count = ps.len(); - if required_count > 0 { - body.push(item(seq![ - "if ", - src.to_owned(), - ".len()", - if base > 0 { - seq![" - ", base.to_string()] - } else { - seq![] - }, - " < ", - required_count.to_string(), - " { return ", - ctxt.err_code(), - "; }" - ])); - } - for p in ps { - named_pattern_parser(ctxt, p, &format!("(&{}[{}])", src, i), None, body); - i += 1; - } -} - -fn named_pattern_parser( - ctxt: &mut FunctionContext, - p: &NamedPattern, - src: &str, - sequence_base: Option, - body: &mut Vec, -) { - match p { - NamedPattern::Anonymous(p) => { - pattern_parser(ctxt, p, src, sequence_base, body); - } - NamedPattern::Named(b) => { - let Binding { name, pattern } = &**b; - let dest = simple_pattern_parser(ctxt, pattern, src, sequence_base, body); - let capture_ty = field_type(pattern); - ctxt.capture(names::render_fieldname(name), capture_ty, dest); - } - } -} - -fn pattern_parser( - ctxt: &mut FunctionContext, - p: &Pattern, - src: &str, - sequence_base: Option, - body: &mut Vec, -) -> Option { - match p { - Pattern::SimplePattern(s) => Some(simple_pattern_parser(ctxt, s, src, sequence_base, body)), - Pattern::CompoundPattern(c) => { - match &**c { - CompoundPattern::Rec { label, fields } => { - let rtmp = ctxt.gentempname(); - 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, - ); - } - CompoundPattern::Tuple { patterns } => { - let (src, n) = sequenceify(ctxt, src, sequence_base, body); - fixed_sequence_parser(ctxt, n, patterns, &src, body); - } - CompoundPattern::TuplePrefix { fixed, variable } => { - let (src, n) = sequenceify(ctxt, src, sequence_base, body); - fixed_sequence_parser(ctxt, n, fixed, &src, body); - named_pattern_parser( - ctxt, - &promote(variable), - &src, - Some(n + fixed.len()), - body, - ); - } - CompoundPattern::Dict { entries } => { - let dtmp = ctxt.gentempname(); - 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(); - let init_expr = item(seq![ - dtmp.to_owned(), - ".get", - parens![ctxt.m.define_literal(key_lit)], - ".ok_or_else(|| ", - ctxt.conformance_err_code(), - ")?" - ]); - ctxt.define_atom(body, &vtmp, init_expr); - named_pattern_parser(ctxt, &promote(value_pat), &vtmp, None, body); - } - } - } - None - } - } -} diff --git a/implementations/rust/preserves-schema/src/compiler/readers.rs b/implementations/rust/preserves-schema/src/compiler/readers.rs deleted file mode 100644 index 9035f17..0000000 --- a/implementations/rust/preserves-schema/src/compiler/readers.rs +++ /dev/null @@ -1,652 +0,0 @@ -use crate::gen::schema::*; -use crate::syntax::block::constructors::*; -use crate::syntax::block::escape_bytes; -use crate::syntax::block::escape_string; -use crate::syntax::block::Item; -use crate::*; - -use preserves::value::AtomClass; -use preserves::value::CompoundClass; -use preserves::value::IOValue; -use preserves::value::NestedValue; -use preserves::value::ValueClass; - -use super::context::FunctionContext; -use super::context::ModuleContext; -use super::context::ModuleContextMode; -use super::context::RefRenderStyle; -use super::names; -use super::types::*; - -#[derive(Debug)] -pub struct ReaderPlugin; - -impl compiler::Plugin for ReaderPlugin { - fn generate_definition( - &self, - module_ctxt: &mut ModuleContext, - definition_name: &str, - definition: &Definition, - ) { - if let ModuleContextMode::TargetGeneric = module_ctxt.mode { - gen_definition_reader(module_ctxt, definition_name, definition) - } - } -} - -#[derive(Clone)] -struct BoundaryTracker { - tracker_name: String, - item_expr: &'static str, -} - -impl BoundaryTracker { - fn unwrap( - ctxt: &mut FunctionContext, - body: &mut Vec, - open_expr: &'static str, - e: Option<&BoundaryTracker>, - ) -> Self { - match e { - None => Self::new(ctxt, body, open_expr, "_support::B::Item::SequenceValue"), - Some(b) => b.clone(), - } - } - - fn new( - ctxt: &mut FunctionContext, - body: &mut Vec, - open_expr: &'static str, - item_expr: &'static str, - ) -> Self { - let tracker_name = ctxt.gentempname(); - body.push(item(open_expr)); - body.push(item(seq![ - "let mut ", - tracker_name.clone(), - " = _support::B::Type::default();" - ])); - BoundaryTracker { - tracker_name, - item_expr, - } - } - - fn emit_boundary(&self, body: &mut Vec) { - body.push(item(seq![ - self.tracker_name.clone(), - ".shift(Some(", - self.item_expr, - "));" - ])); - body.push(item(seq!["r.boundary(&", self.tracker_name.clone(), ")?;"])); - } - - fn emit_loop(&self, body: &mut Vec, inner: Vec) { - body.push(item(seq![ - "while !r.close_compound", - parens![ - seq!["&mut ", self.tracker_name.clone()], - seq!["&", self.item_expr] - ], - "? ", - codeblock(inner) - ])) - } -} - -pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) { - let ty = definition_type(&m.module_path, Purpose::Codegen, n, d); - - 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![ - "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, None, &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", - seq![ctxt.m.any_type(), ": preserves::value::NestedValue"], - seq!["R: _support::Reader<'de, ", ctxt.m.any_type(), ">"] - ], - "(r: &mut R) -> ", - "std::result::Result<", - names::render_constructor(n), - ty.generic_arg(ctxt.m), - ", _support::ParseError> ", - codeblock(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]; - let mut need_restore = false; - ps.extend(pattern_n); - ctxt.define_atom(&mut body, "_mark", item("r.mark()?")); - for e in &ps { - if need_restore { - body.push(item("r.restore(&_mark)?;")); - } else { - need_restore = true; - } - named_pattern_reader(&mut ctxt, e, None, &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, None, &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![seq![ctxt.m.any_type(), ": preserves::value::NestedValue"]], - " _support::Deserialize", - anglebrackets![ctxt.m.any_type()], - " for ", - names::render_constructor(n), - ty.generic_arg(ctxt.m), - " ", - codeblock![seq![ - "fn deserialize", - anglebrackets![ - "'de", - seq!["R: _support::Reader<'de, ", ctxt.m.any_type(), ">"] - ], - "(r: &mut R) -> ", - "std::result::Result ", - codeblock(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(_) | TField::Any | TField::Embedded => 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<(IOValue, LiteralContinuation)>; -type LiteralSeqCases = Vec<(Vec, 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 => ", - codeblock(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(true)? ", codeblock(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::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())), - }, - " => ", - codeblock(inner)])); - } - subcases.push(item(seq!["_ => return ", ctxt.err_code(), "?,"])); - item(seq!["preserves::value::Token::Atom(v) => match v.value() ", codeblock(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) => ", - codeblock(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) => ", - codeblock(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(true)? ", codeblock(cases)])); -} - -fn simple_pattern_reader( - ctxt: &mut FunctionContext, - p: &SimplePattern, - boundary_tracker: Option<&BoundaryTracker>, - body: &mut Vec, -) -> String { - let dest = ctxt.gentempname(); - match p { - SimplePattern::Any => { - ctxt.define_atom(body, &dest, item("r.demand_next(true)?")); - dest - } - SimplePattern::Atom { atom_kind: k } => { - let reader = match &**k { - AtomKind::Boolean => "r.next_boolean()?", - 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 { .. } => { - ctxt.define_atom( - body, - &dest, - item("r.demand_next(true)?.value().to_embedded()?.clone()"), - ); - 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 } => { - let compound_dest = ctxt.gentempname(); - ctxt.with_definite_mode(|ctxt| { - let boundary_tracker = - BoundaryTracker::unwrap(ctxt, body, "r.open_sequence()?;", boundary_tracker); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); - inner.push(item(seq![ - compound_dest.to_owned(), - ".push(", - store_wrap(true, &field_type(pattern), &item_dest), - ");" - ])); - ctxt.declare_compound(body, &compound_dest, item("std::vec::Vec::new()")); - boundary_tracker.emit_loop(body, inner); - }); - ctxt.define_atom(body, &dest, item(compound_dest)); - dest - } - SimplePattern::Setof { pattern } => { - let compound_dest = ctxt.gentempname(); - ctxt.with_definite_mode(|ctxt| { - let boundary_tracker = BoundaryTracker::new( - ctxt, - body, - "r.open_set()?;", - "_support::B::Item::SetValue", - ); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); - inner.push(item(seq![ - compound_dest.to_owned(), - ".insert(", - store_wrap(true, &field_type(pattern), &item_dest), - ");" - ])); - ctxt.declare_compound(body, &compound_dest, item("preserves::value::Set::new()")); - boundary_tracker.emit_loop(body, inner); - }); - ctxt.define_atom(body, &dest, item(compound_dest)); - dest - } - SimplePattern::Dictof { key, value } => { - let compound_dest = ctxt.gentempname(); - ctxt.with_definite_mode(|ctxt| { - let mut boundary_tracker = BoundaryTracker::new( - ctxt, - body, - "r.open_dictionary()?;", - "_support::B::Item::DictionaryKey", - ); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let key_dest = simple_pattern_reader(ctxt, key, None, &mut inner); - boundary_tracker.item_expr = "_support::B::Item::DictionaryValue"; - boundary_tracker.emit_boundary(&mut inner); - let value_dest = simple_pattern_reader(ctxt, value, None, &mut inner); - inner.push(item(seq![ - compound_dest.to_owned(), - ".insert(", - store_wrap(true, &field_type(key), &key_dest), - ", ", - store_wrap(true, &field_type(value), &value_dest), - ");" - ])); - ctxt.declare_compound(body, &compound_dest, item("preserves::value::Map::new()")); - boundary_tracker.item_expr = "_support::B::Item::DictionaryKey"; - boundary_tracker.emit_loop(body, inner); - }); - ctxt.define_atom(body, &dest, item(compound_dest)); - dest - } - SimplePattern::Ref(r) => { - let tf = name![ctxt.m.render_ref(&**r, RefRenderStyle::Bare), "deserialize"]; - ctxt.define_atom(body, &dest, item(seq![tf, "(r)?"])); - dest - } - } -} - -fn named_pattern_reader( - ctxt: &mut FunctionContext, - p: &NamedPattern, - boundary_tracker: Option<&BoundaryTracker>, - body: &mut Vec, -) { - match p { - NamedPattern::Anonymous(p) => { - pattern_reader(ctxt, p, boundary_tracker, body); - } - NamedPattern::Named(b) => { - let Binding { name, pattern } = &**b; - let dest = simple_pattern_reader(ctxt, pattern, boundary_tracker, body); - let capture_ty = field_type(pattern); - ctxt.capture(names::render_fieldname(name), capture_ty, dest); - } - } -} - -fn pattern_reader( - ctxt: &mut FunctionContext, - p: &Pattern, - boundary_tracker: Option<&BoundaryTracker>, - body: &mut Vec, -) -> Option { - match p { - Pattern::SimplePattern(s) => Some(simple_pattern_reader(ctxt, s, boundary_tracker, body)), - Pattern::CompoundPattern(c) => { - match &**c { - CompoundPattern::Rec { label, fields } => { - let mut boundary_tracker = BoundaryTracker::new( - ctxt, - body, - "r.open_record(None)?;", - "_support::B::Item::RecordLabel", - ); - boundary_tracker.emit_boundary(body); - boundary_tracker.item_expr = "_support::B::Item::RecordField"; - named_pattern_reader(ctxt, &**label, None, body); - named_pattern_reader(ctxt, &**fields, Some(&boundary_tracker), body); - } - CompoundPattern::Tuple { patterns } => { - let boundary_tracker = BoundaryTracker::unwrap( - ctxt, - body, - "r.open_sequence()?;", - boundary_tracker, - ); - for p in patterns { - boundary_tracker.emit_boundary(body); - named_pattern_reader(ctxt, p, None, body); - } - body.push(item(seq![ - "r.ensure_complete", - parens![ - boundary_tracker.tracker_name.clone(), - seq!["&", boundary_tracker.item_expr] - ], - "?;" - ])); - } - CompoundPattern::TuplePrefix { fixed, variable } => { - let boundary_tracker = BoundaryTracker::unwrap( - ctxt, - body, - "r.open_sequence()?;", - boundary_tracker, - ); - for p in fixed { - boundary_tracker.emit_boundary(body); - named_pattern_reader(ctxt, p, None, body); - } - named_pattern_reader(ctxt, &promote(variable), Some(&boundary_tracker), body); - } - CompoundPattern::Dict { entries } => { - let boundary_tracker = BoundaryTracker::new( - ctxt, - body, - "r.open_dictionary()?;", - "_support::B::Item::DictionaryKey", - ); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let mut val_boundary_tracker = boundary_tracker.clone(); - val_boundary_tracker.item_expr = "_support::B::Item::DictionaryValue"; - 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 val_boundary_tracker = val_boundary_tracker.clone(); - let f: LiteralContinuation = Box::new( - move |ctxt: &mut FunctionContext, innerinner: &mut Vec| { - val_boundary_tracker.emit_boundary(innerinner); - named_pattern_reader(ctxt, &promote(&value_pat), None, innerinner); - innerinner.push(item("continue;")); - }); - (key_lit.clone(), f) - }).collect()); - })); - boundary_tracker.emit_loop(body, inner); - } - } - None - } - } -} diff --git a/implementations/rust/preserves-schema/src/compiler/types.rs b/implementations/rust/preserves-schema/src/compiler/types.rs deleted file mode 100644 index d047ebf..0000000 --- a/implementations/rust/preserves-schema/src/compiler/types.rs +++ /dev/null @@ -1,461 +0,0 @@ -use crate::gen::schema::*; -use crate::syntax::block::constructors::*; -use crate::syntax::block::{Emittable, Item}; -use crate::*; - -use preserves::value::Set; - -use super::context::BundleContext; -use super::context::ModuleContext; -use super::context::ModuleContextMode; -use super::context::RefRenderStyle; -use super::names; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] -pub enum Purpose { - Codegen, - Xref, -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub struct TDefinition { - pub purpose: Purpose, - pub self_ref: Ref, - pub body: TDefinitionBody, -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub enum TDefinitionBody { - Union(Vec<(String, TSimple)>), - Simple(TSimple), -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub enum TSimple { - Field(TField), - Record(TRecord), -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub enum TField { - Unit, - Any, - Embedded, - Array(Box), - Set(Box), - Map(Box, Box), - Ref(Ref), - Base(String), -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub struct TRecord(pub Vec<(String, TField)>); - -#[derive(Debug)] -pub struct TypePlugin; - -impl compiler::Plugin for TypePlugin { - fn generate_module(&self, m: &mut ModuleContext) { - if let EmbeddedTypeName::Ref(r) = &m.schema.embedded_type { - m.define_type(item(vertical( - false, - seq![ - seq![ - "pub type _Dom = ", - m.render_ref(&*r, RefRenderStyle::Bare), - ";" - ], - seq!["pub type _Ptr = std::sync::Arc<_Dom>;"], - seq!["pub type _Any = preserves::value::ArcValue<_Ptr>;"] - ], - ))); - } - } - - fn generate_definition(&self, m: &mut ModuleContext, n: &str, d: &Definition) { - if let ModuleContextMode::TargetGeneric = m.mode { - let ty = definition_type(&m.module_path, Purpose::Codegen, n, d); - m.define_type(item(ty.render(m, n))); - m.define_type(item(seq![ - "impl", - ty.generic_decl(m), - " preserves::value::Domain for ", - names::render_constructor(n), - ty.generic_arg(m), - " {}" - ])); - } - } -} - -pub fn definition_type( - module: &ModulePath, - purpose: Purpose, - n: &str, - d: &Definition, -) -> TDefinition { - TDefinition { - purpose, - self_ref: Ref { - module: module.clone(), - name: n.to_owned(), - }, - body: match d { - Definition::Or { - pattern_0, - pattern_1, - pattern_n, - } => TDefinitionBody::Union(or_definition_type(pattern_0, pattern_1, pattern_n)), - Definition::And { - pattern_0, - pattern_1, - pattern_n, - } => TDefinitionBody::Simple(and_definition_type(pattern_0, pattern_1, pattern_n)), - Definition::Pattern(p) => TDefinitionBody::Simple(pattern_type(p)), - }, - } -} - -pub fn or_definition_type( - p0: &NamedAlternative, - p1: &NamedAlternative, - pn: &Vec, -) -> Vec<(String, TSimple)> { - let mut entries = Vec::new(); - entries.push((p0.variant_label.to_owned(), pattern_type(&p0.pattern))); - entries.push((p1.variant_label.to_owned(), pattern_type(&p1.pattern))); - for e in pn { - entries.push((e.variant_label.to_owned(), pattern_type(&e.pattern))); - } - entries -} - -pub fn and_definition_type( - p0: &NamedPattern, - p1: &NamedPattern, - pn: &Vec, -) -> TSimple { - let mut arms = vec![p0, p1]; - arms.extend(pn); - record_type(&arms) -} - -pub fn pattern_type(p: &Pattern) -> TSimple { - match p { - Pattern::SimplePattern(p) => TSimple::Field(field_type(p)), - Pattern::CompoundPattern(_) => { - record_type(&vec![&NamedPattern::Anonymous(Box::new(p.clone()))]) - } - } -} - -pub fn record_type(ps: &Vec<&NamedPattern>) -> TSimple { - let fs = gather_fields(ps, Vec::new()); - if fs.is_empty() { - TSimple::Field(TField::Unit) - } else { - TSimple::Record(TRecord(fs)) - } -} - -pub fn gather_fields( - ps: &Vec<&NamedPattern>, - mut fs: Vec<(String, TField)>, -) -> Vec<(String, TField)> { - for p in ps.iter() { - fs = gather_field(p, fs); - } - fs -} - -pub fn gather_field(p: &NamedPattern, mut fs: Vec<(String, TField)>) -> Vec<(String, TField)> { - match p { - NamedPattern::Named(b) => { - let Binding { name, pattern } = &**b; - fs.push((name.to_owned(), field_type(pattern))); - fs - } - NamedPattern::Anonymous(p) => match &**p { - Pattern::SimplePattern(_) => fs, - Pattern::CompoundPattern(c) => match &**c { - CompoundPattern::Rec { label, fields } => { - gather_field(&*fields, gather_field(&*label, fs)) - } - CompoundPattern::Tuple { patterns } => { - gather_fields(&patterns.iter().collect(), fs) - } - CompoundPattern::TuplePrefix { fixed, variable } => gather_field( - &promote(&**variable), - gather_fields(&fixed.iter().collect(), fs), - ), - CompoundPattern::Dict { entries } => { - for (_k, p) in &entries.0 { - fs = gather_field(&promote(&p), fs); - } - fs - } - }, - }, - } -} - -pub fn promote(p: &NamedSimplePattern) -> NamedPattern { - match p { - NamedSimplePattern::Anonymous(p) => { - NamedPattern::Anonymous(Box::new(Pattern::SimplePattern(p.clone()))) - } - NamedSimplePattern::Named(n) => NamedPattern::Named(n.clone()), - } -} - -pub fn field_type(p: &SimplePattern) -> TField { - match p { - SimplePattern::Any => TField::Any, - SimplePattern::Atom { atom_kind: k } => match **k { - AtomKind::Boolean => TField::Base("bool".to_owned()), - AtomKind::Double => TField::Base("preserves::value::Double".to_owned()), - AtomKind::SignedInteger => { - TField::Base("preserves::value::signed_integer::SignedInteger".to_owned()) - } - AtomKind::String => TField::Base("std::string::String".to_owned()), - AtomKind::ByteString => TField::Base("std::vec::Vec".to_owned()), - AtomKind::Symbol => TField::Base("std::string::String".to_owned()), - }, - SimplePattern::Embedded { .. } => TField::Embedded, - SimplePattern::Lit { .. } => TField::Unit, - SimplePattern::Seqof { pattern: t } => TField::Array(Box::new(field_type(t))), - SimplePattern::Setof { pattern: t } => TField::Set(Box::new(field_type(t))), - SimplePattern::Dictof { key: k, value: v } => { - TField::Map(Box::new(field_type(k)), Box::new(field_type(v))) - } - SimplePattern::Ref(r) => TField::Ref((**r).clone()), - } -} - -type WalkState<'a, 'b> = super::cycles::WalkState<&'a BundleContext<'b>>; - -impl TField { - fn render(&self, ctxt: &ModuleContext, box_needed: bool) -> impl Emittable { - match self { - TField::Unit => seq!["()"], - TField::Any => seq![ctxt.any_type()], - TField::Embedded => seq![ctxt.any_type(), "::Embedded"], - TField::Array(t) => seq!["std::vec::Vec<", t.render(ctxt, false), ">"], - TField::Set(t) => seq!["preserves::value::Set<", t.render(ctxt, false), ">"], - TField::Map(k, v) => seq![ - "preserves::value::Map", - anglebrackets![k.render(ctxt, false), v.render(ctxt, false)] - ], - TField::Ref(r) => { - if box_needed { - seq![ - "std::boxed::Box", - anglebrackets![ctxt.render_ref(r, RefRenderStyle::Qualified)] - ] - } else { - seq![ctxt.render_ref(r, RefRenderStyle::Qualified)] - } - } - TField::Base(n) => seq![n.to_owned()], - } - } - - fn language_types(&self, s: &mut WalkState, ts: &mut Set) { - match self { - TField::Unit | TField::Any | TField::Embedded | TField::Base(_) => (), - TField::Array(f) => f.language_types(s, ts), - TField::Set(f) => f.language_types(s, ts), - TField::Map(k, v) => { - k.language_types(s, ts); - v.language_types(s, ts); - } - TField::Ref(r) => s.cycle_check( - r, - |ctxt, r| ctxt.type_for_name(r), - |s, t| match t { - Some(ty) if ty.purpose == Purpose::Codegen => ty._language_types(s, ts), - Some(_) | None => { - let xmts = &s - .context - .config - .external_modules - .get(&r.module.0) - .unwrap() - .rust_language_types; - if let Some(f) = xmts.definitions.get(&r.name).or(xmts.fallback.as_ref()) { - ts.extend(f(s.context.any_type())); - } - } - }, - || (), - ), - } - } - - fn has_embedded(&self, s: &mut WalkState) -> bool { - match self { - TField::Unit | TField::Base(_) => false, - TField::Any | TField::Embedded => true, // at least potentially true - TField::Array(f) => f.has_embedded(s), - TField::Set(f) => f.has_embedded(s), - TField::Map(k, v) => k.has_embedded(s) || v.has_embedded(s), - TField::Ref(r) => - // v TODO: should the "false" be configurable? cf. ModuleContext::ref_has_embedded. - { - s.cycle_check( - r, - |ctxt, r| ctxt.type_for_name(r), - |s, t| t.map(|t| t._has_embedded(s)).unwrap_or(false), - || false, - ) - } - } - } -} - -impl TSimple { - pub fn render( - &self, - ctxt: &ModuleContext, - ptr: Item, - is_struct: bool, - n: &str, - ) -> impl Emittable { - let semi = if is_struct { seq![";"] } else { seq![] }; - let ppub = if is_struct { "pub " } else { "" }; - seq![ - names::render_constructor(n), - ptr.to_owned(), - match self { - TSimple::Record(TRecord(fs)) => seq![ - " ", - vertical( - false, - braces( - fs.iter() - .map(|(n, d)| item(seq![ - ppub, - names::render_fieldname(n), - ": ", - d.render(ctxt, !is_struct) - ])) - .collect() - ) - ) - ], - TSimple::Field(TField::Unit) => semi, - TSimple::Field(t) => seq![parens![seq![ppub, t.render(ctxt, !is_struct)]], semi], - } - ] - } - - fn language_types(&self, s: &mut WalkState, ts: &mut Set) { - match self { - TSimple::Field(f) => f.language_types(s, ts), - TSimple::Record(TRecord(fs)) => fs.iter().for_each(|(_k, v)| v.language_types(s, ts)), - } - } - - fn has_embedded(&self, s: &mut WalkState) -> bool { - match self { - TSimple::Field(f) => f.has_embedded(s), - TSimple::Record(TRecord(fs)) => fs.iter().any(|(_k, v)| v.has_embedded(s)), - } - } -} - -impl TDefinition { - pub fn generic_decl(&self, ctxt: &ModuleContext) -> Item { - if self.has_embedded(ctxt.bundle) { - item(anglebrackets![seq![ - ctxt.any_type(), - ": preserves::value::NestedValue" - ]]) - } else { - item("") - } - } - - pub fn generic_decl_with_defaults(&self, ctxt: &ModuleContext) -> Item { - if self.has_embedded(ctxt.bundle) { - item(anglebrackets![seq![ - ctxt.any_type(), - ": preserves::value::NestedValue = ", - match ctxt.schema.embedded_type { - EmbeddedTypeName::False => "preserves::value::IOValue", - EmbeddedTypeName::Ref(_) => "_Any", - } - ]]) - } else { - item("") - } - } - - pub fn generic_arg(&self, ctxt: &ModuleContext) -> Item { - if self.has_embedded(ctxt.bundle) { - item(anglebrackets![ctxt.any_type()]) - } else { - item("") - } - } - - pub fn render(&self, ctxt: &ModuleContext, n: &str) -> impl Emittable { - vertical( - false, - seq![ - "#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)]", - match &self.body { - TDefinitionBody::Union(items) => seq![ - "pub enum ", - names::render_constructor(n), - self.generic_decl_with_defaults(ctxt), - " ", - vertical( - false, - braces( - items - .iter() - .map(|(n, d)| item(d.render(ctxt, item(""), false, n))) - .collect() - ) - ) - ], - TDefinitionBody::Simple(s) => seq![ - "pub struct ", - s.render(ctxt, self.generic_decl_with_defaults(ctxt), true, n) - ], - } - ], - ) - } - - fn walk_state<'a, 'b>(&self, ctxt: &'a BundleContext<'b>) -> WalkState<'a, 'b> { - WalkState::new(ctxt, self.self_ref.module.clone()) - } - - pub fn language_types(&self, ctxt: &BundleContext) -> Set { - let mut ts = Set::new(); - self._language_types(&mut self.walk_state(ctxt), &mut ts); - ts - } - - fn _language_types(&self, s: &mut WalkState, ts: &mut Set) { - match &self.body { - TDefinitionBody::Union(entries) => { - entries.iter().for_each(|(_k, v)| v.language_types(s, ts)) - } - TDefinitionBody::Simple(t) => t.language_types(s, ts), - } - } - - pub fn has_embedded(&self, ctxt: &BundleContext) -> bool { - self._has_embedded(&mut self.walk_state(ctxt)) - } - - fn _has_embedded(&self, s: &mut WalkState) -> bool { - match &self.body { - TDefinitionBody::Union(entries) => entries.iter().any(|(_k, v)| v.has_embedded(s)), - TDefinitionBody::Simple(t) => t.has_embedded(s), - } - } -} diff --git a/implementations/rust/preserves-schema/src/compiler/unparsers.rs b/implementations/rust/preserves-schema/src/compiler/unparsers.rs deleted file mode 100644 index 2f1cf7b..0000000 --- a/implementations/rust/preserves-schema/src/compiler/unparsers.rs +++ /dev/null @@ -1,440 +0,0 @@ -use crate::gen::schema::*; -use crate::syntax::block::constructors::*; -use crate::syntax::block::{escape_string, Emittable, Item}; -use crate::*; - -use std::cell::Cell; -use std::rc::Rc; - -use super::context::{FunctionContext, ModuleContext, ModuleContextMode}; -use super::names; -use super::types::*; - -#[derive(Debug)] -pub struct UnparserPlugin; - -impl compiler::Plugin for UnparserPlugin { - fn generate_definition( - &self, - module_ctxt: &mut ModuleContext, - definition_name: &str, - definition: &Definition, - ) { - if let ModuleContextMode::TargetGeneric = module_ctxt.mode { - gen_definition_unparser(module_ctxt, definition_name, definition) - } - } -} - -type ValueSource = Option; - -#[derive(Clone)] -struct FieldsSink { - finish: Item, - vec_expr: Item, - body: Vec, -} - -#[derive(Clone)] -enum ValueSink { - Normal, - Fields(Rc>>), -} - -impl std::fmt::Debug for ValueSink { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - ValueSink::Normal => write!(f, "ValueSink::Normal"), - ValueSink::Fields(_) => write!(f, "ValueSink::Normal"), - } - } -} - -#[derive(Debug)] -struct ValueContext { - src: ValueSource, - sink: ValueSink, - is_struct: bool, -} - -fn normal_none(is_struct: bool) -> ValueContext { - ValueContext { - src: None, - sink: ValueSink::Normal, - is_struct, - } -} - -fn normal_src(src: String, is_struct: bool) -> ValueContext { - ValueContext { - src: Some(src), - sink: ValueSink::Normal, - is_struct, - } -} - -pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) { - let ty = definition_type(&m.module_path, Purpose::Codegen, n, d); - - 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); - body.push(item(seq![ - "match self ", - codeblock( - ps.iter() - .map( - |NamedAlternative { - variant_label: name, - pattern: pat, - }| ctxt.branch(|ctxt| { - let ctorname = item(name![ - names::render_constructor(n), - names::render_constructor(name) - ]); - let (patpat, vc) = - destruct(ctxt, ctorname, false, &pattern_type(pat)); - item(seq![ - patpat, - " => ", - pattern_unparser(ctxt, pat, &vc), - "," - ]) - }) - ) - .collect() - ) - ])); - } - Definition::And { - pattern_0, - pattern_1, - pattern_n, - } => { - 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), - ); - body.push(item(seq!["let ", patpat, " = self;"])); - body.push(item(seq![ - "preserves::value::merge(vec!", - brackets( - ps.iter() - .map(|p| named_pattern_unparser(&mut ctxt, p, &vc)) - .collect() - ), - ").expect", - parens![escape_string( - &("merge of ".to_owned() + &ctxt.fully_qualified_error_context()) - )] - ])); - } - Definition::Pattern(p) => { - let (patpat, vc) = destruct( - &mut ctxt, - item(names::render_constructor(n)), - true, - &pattern_type(p), - ); - body.push(item(seq!["let ", patpat, " = self;"])); - body.push(pattern_unparser(&mut ctxt, p, &vc)); - } - } - - item(seq![ - "impl", - ctxt.m.parse_unparse_generic_decls(&ty), - " _support::Unparse", - anglebrackets!["_L", ctxt.m.any_type()], - " for ", - names::render_constructor(n), - ty.generic_arg(ctxt.m), - " ", - codeblock![seq![ - "fn unparse(&self, _ctxt: _L) -> ", - ctxt.m.any_type(), - " ", - codeblock(body) - ]] - ]) - }); -} - -fn destruct( - ctxt: &mut FunctionContext, - ctorname: Item, - is_struct: bool, - ty: &TSimple, -) -> (impl Emittable, ValueContext) { - match ty { - TSimple::Field(TField::Unit) => (seq![ctorname], normal_none(is_struct)), - TSimple::Field(_) => { - let src = ctxt.gentempname(); - ( - seq![ctorname, parens![src.to_owned()]], - normal_src(src, is_struct), - ) - } - TSimple::Record(TRecord(fs)) => { - for (fname, fty) in fs { - let fsrc = ctxt.gentempname(); - ctxt.capture(names::render_fieldname(fname), fty.clone(), fsrc); - } - ( - seq![ - ctorname, - " ", - braces( - ctxt.captures - .iter() - .map(|c| item(seq![c.field_name.clone(), ": ", c.source_expr.clone()])) - .collect() - ) - ], - normal_none(is_struct), - ) - } - } -} - -fn simple_pattern_unparser( - ctxt: &mut FunctionContext, - p: &SimplePattern, - vc: &ValueContext, -) -> Item { - let src = &vc.src; - match p { - SimplePattern::Any => item(seq![src.as_ref().unwrap().to_owned(), ".clone()"]), - SimplePattern::Atom { atom_kind: k } => match &**k { - AtomKind::Symbol => item(seq![ - "preserves::value::Value::symbol(", - src.as_ref().unwrap().to_owned(), - ").wrap()" - ]), - AtomKind::ByteString => item(seq![ - "preserves::value::Value::ByteString(", - src.as_ref().unwrap().to_owned(), - ".clone()).wrap()" - ]), - _ => item(seq![ - "preserves::value::Value::from(", - src.as_ref().unwrap().to_owned(), - ").wrap()" - ]), - }, - SimplePattern::Embedded { .. } => item(seq![ - "preserves::value::Value::Embedded(", - src.as_ref().unwrap().to_owned(), - ".clone()).wrap()" - ]), - SimplePattern::Lit { value } => { - item(seq![parens![ctxt.m.define_literal(value)], ".clone()"]) - } - SimplePattern::Seqof { pattern } => { - let mut fields_sink = sequenceify(ctxt, vc); - let tmp = ctxt.gentempname(); - fields_sink.body.push(item(seq![ - "for ", - tmp.to_owned(), - " in ", - src.as_ref().unwrap().to_owned(), - " ", - codeblock![seq![ - fields_sink.vec_expr.clone(), - ".push(", - simple_pattern_unparser(ctxt, pattern, &normal_src(tmp, true)), - ");" - ]] - ])); - finish(fields_sink) - } - SimplePattern::Setof { pattern } => { - let tmp = ctxt.gentempname(); - item(seq![ - "preserves::value::Value::Set(", - src.as_ref().unwrap().to_owned(), - ".iter().map(|", - tmp.to_owned(), - "| ", - simple_pattern_unparser(ctxt, pattern, &normal_src(tmp, true)), - ").collect()).wrap()" - ]) - } - SimplePattern::Dictof { key, value } => { - let tmp_key = ctxt.gentempname(); - let tmp_value = ctxt.gentempname(); - item(seq![ - "preserves::value::Value::Dictionary(", - src.as_ref().unwrap().to_owned(), - ".iter().map(|(", - tmp_key.to_owned(), - ", ", - tmp_value.to_owned(), - ")| ", - parens![ - simple_pattern_unparser(ctxt, key, &normal_src(tmp_key, true)), - simple_pattern_unparser(ctxt, value, &normal_src(tmp_value, true)) - ], - ").collect()).wrap()" - ]) - } - SimplePattern::Ref(_r) => item(seq![ - src.as_ref().unwrap().to_owned(), - if vc.is_struct { "" } else { ".as_ref()" }, - ".unparse(_ctxt)" - ]), - } -} - -fn named_pattern_unparser(ctxt: &mut FunctionContext, p: &NamedPattern, vc: &ValueContext) -> Item { - match p { - NamedPattern::Anonymous(p) => pattern_unparser(ctxt, p, vc), - NamedPattern::Named(b) => { - let Binding { name, pattern } = &**b; - let src = ctxt - .lookup_capture(&names::render_fieldname(name)) - .source_expr - .to_owned(); - simple_pattern_unparser( - ctxt, - pattern, - &ValueContext { - src: Some(src), - sink: vc.sink.clone(), - is_struct: vc.is_struct, - }, - ) - } - } -} - -fn pattern_unparser(ctxt: &mut FunctionContext, p: &Pattern, vc: &ValueContext) -> Item { - match p { - Pattern::SimplePattern(s) => simple_pattern_unparser(ctxt, s, vc), - Pattern::CompoundPattern(c) => match &**c { - CompoundPattern::Rec { label, fields } => { - let rtmp = ctxt.gentempname(); - let mut body = Vec::new(); - 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 { - finish: item(seq![rtmp.clone(), ".finish().wrap()"]), - vec_expr: item(seq![rtmp.clone(), ".fields_vec_mut()"]), - body, - })))), - is_struct: vc.is_struct, - }, - ) - } - CompoundPattern::Tuple { patterns } => { - let mut fields_sink = sequenceify(ctxt, vc); - fixed_sequence_parser(ctxt, patterns, &mut fields_sink, vc.is_struct); - finish(fields_sink) - } - CompoundPattern::TuplePrefix { fixed, variable } => { - let mut fields_sink = sequenceify(ctxt, vc); - fixed_sequence_parser(ctxt, fixed, &mut fields_sink, vc.is_struct); - named_pattern_unparser( - ctxt, - &promote(variable), - &ValueContext { - src: vc.src.clone(), - sink: ValueSink::Fields(Rc::new(Cell::new(Some(fields_sink)))), - is_struct: true, - }, - ) - } - CompoundPattern::Dict { entries } => { - let dtmp = ctxt.gentempname(); - let mut body = Vec::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()"], - named_pattern_unparser( - ctxt, - &promote(value_pat), - &normal_none(vc.is_struct) - ) - ], - ";" - ])); - } - body.push(item(seq![ - "preserves::value::Value::Dictionary(", - dtmp, - ").wrap()" - ])); - item(codeblock(body)) - } - }, - } -} - -fn sequenceify<'a>(ctxt: &mut FunctionContext, vc: &'a ValueContext) -> FieldsSink { - match vc { - ValueContext { - sink: ValueSink::Fields(fields_sink), - .. - } => (**fields_sink).take().unwrap(), - _ => { - let rtmp = ctxt.gentempname(); - let mut body = Vec::new(); - 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: item(rtmp), - body, - } - } - } -} - -fn finish(mut fields_sink: FieldsSink) -> Item { - fields_sink.body.push(fields_sink.finish); - item(codeblock(fields_sink.body)) -} - -fn fixed_sequence_parser( - ctxt: &mut FunctionContext, - patterns: &Vec, - fields_sink: &mut FieldsSink, - is_struct: bool, -) { - for p in patterns { - fields_sink.body.push(item(seq![ - fields_sink.vec_expr.clone(), - ".push", - parens![named_pattern_unparser(ctxt, p, &normal_none(is_struct))], - ";" - ])); - } -} diff --git a/implementations/rust/preserves-schema/src/gen/mod.rs b/implementations/rust/preserves-schema/src/gen/mod.rs deleted file mode 100644 index aa1414f..0000000 --- a/implementations/rust/preserves-schema/src/gen/mod.rs +++ /dev/null @@ -1,261 +0,0 @@ -#![cfg_attr(rustfmt, rustfmt_skip)] - -pub mod schema; - -use crate::support as _support; -use _support::preserves; - -#[allow(non_snake_case)] -pub struct Language { - pub LIT_14_FALSE: N /* #f */, - pub LIT_27_1: N /* 1 */, - pub LIT_0_BOOLEAN: N /* Boolean */, - pub LIT_4_BYTE_STRING: N /* ByteString */, - pub LIT_1_DOUBLE: N /* Double */, - pub LIT_2_SIGNED_INTEGER: N /* SignedInteger */, - pub LIT_3_STRING: N /* String */, - pub LIT_5_SYMBOL: N /* Symbol */, - pub LIT_13_AND: N /* and */, - pub LIT_20_ANY: N /* any */, - pub LIT_21_ATOM: N /* atom */, - pub LIT_7_BUNDLE: N /* bundle */, - pub LIT_17_DEFINITIONS: N /* definitions */, - pub LIT_11_DICT: N /* dict */, - pub LIT_26_DICTOF: N /* dictof */, - pub LIT_22_EMBEDDED: N /* embedded */, - pub LIT_18_EMBEDDED_TYPE: N /* embeddedType */, - pub LIT_23_LIT: N /* lit */, - pub LIT_6_NAMED: N /* named */, - pub LIT_12_OR: N /* or */, - pub LIT_8_REC: N /* rec */, - pub LIT_15_REF: N /* ref */, - pub LIT_16_SCHEMA: N /* schema */, - pub LIT_24_SEQOF: N /* seqof */, - pub LIT_25_SETOF: N /* setof */, - pub LIT_9_TUPLE: N /* tuple */, - pub LIT_10_TUPLE_PREFIX: N /* tuplePrefix */, - pub LIT_19_VERSION: N /* version */ -} - -impl Default for Language { - fn default() -> Self { - Language { - LIT_14_FALSE: /* #f */ _support::decode_lit(&[128]).unwrap(), - LIT_27_1: /* 1 */ _support::decode_lit(&[176, 1, 1]).unwrap(), - LIT_0_BOOLEAN: /* Boolean */ _support::decode_lit(&[179, 7, 66, 111, 111, 108, 101, 97, 110]).unwrap(), - LIT_4_BYTE_STRING: /* ByteString */ _support::decode_lit(&[179, 10, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103]).unwrap(), - LIT_1_DOUBLE: /* Double */ _support::decode_lit(&[179, 6, 68, 111, 117, 98, 108, 101]).unwrap(), - LIT_2_SIGNED_INTEGER: /* SignedInteger */ _support::decode_lit(&[179, 13, 83, 105, 103, 110, 101, 100, 73, 110, 116, 101, 103, 101, 114]).unwrap(), - LIT_3_STRING: /* String */ _support::decode_lit(&[179, 6, 83, 116, 114, 105, 110, 103]).unwrap(), - LIT_5_SYMBOL: /* Symbol */ _support::decode_lit(&[179, 6, 83, 121, 109, 98, 111, 108]).unwrap(), - LIT_13_AND: /* and */ _support::decode_lit(&[179, 3, 97, 110, 100]).unwrap(), - LIT_20_ANY: /* any */ _support::decode_lit(&[179, 3, 97, 110, 121]).unwrap(), - LIT_21_ATOM: /* atom */ _support::decode_lit(&[179, 4, 97, 116, 111, 109]).unwrap(), - LIT_7_BUNDLE: /* bundle */ _support::decode_lit(&[179, 6, 98, 117, 110, 100, 108, 101]).unwrap(), - LIT_17_DEFINITIONS: /* definitions */ _support::decode_lit(&[179, 11, 100, 101, 102, 105, 110, 105, 116, 105, 111, 110, 115]).unwrap(), - LIT_11_DICT: /* dict */ _support::decode_lit(&[179, 4, 100, 105, 99, 116]).unwrap(), - LIT_26_DICTOF: /* dictof */ _support::decode_lit(&[179, 6, 100, 105, 99, 116, 111, 102]).unwrap(), - LIT_22_EMBEDDED: /* embedded */ _support::decode_lit(&[179, 8, 101, 109, 98, 101, 100, 100, 101, 100]).unwrap(), - LIT_18_EMBEDDED_TYPE: /* embeddedType */ _support::decode_lit(&[179, 12, 101, 109, 98, 101, 100, 100, 101, 100, 84, 121, 112, 101]).unwrap(), - LIT_23_LIT: /* lit */ _support::decode_lit(&[179, 3, 108, 105, 116]).unwrap(), - LIT_6_NAMED: /* named */ _support::decode_lit(&[179, 5, 110, 97, 109, 101, 100]).unwrap(), - LIT_12_OR: /* or */ _support::decode_lit(&[179, 2, 111, 114]).unwrap(), - LIT_8_REC: /* rec */ _support::decode_lit(&[179, 3, 114, 101, 99]).unwrap(), - LIT_15_REF: /* ref */ _support::decode_lit(&[179, 3, 114, 101, 102]).unwrap(), - LIT_16_SCHEMA: /* schema */ _support::decode_lit(&[179, 6, 115, 99, 104, 101, 109, 97]).unwrap(), - LIT_24_SEQOF: /* seqof */ _support::decode_lit(&[179, 5, 115, 101, 113, 111, 102]).unwrap(), - LIT_25_SETOF: /* setof */ _support::decode_lit(&[179, 5, 115, 101, 116, 111, 102]).unwrap(), - LIT_9_TUPLE: /* tuple */ _support::decode_lit(&[179, 5, 116, 117, 112, 108, 101]).unwrap(), - LIT_10_TUPLE_PREFIX: /* tuplePrefix */ _support::decode_lit(&[179, 11, 116, 117, 112, 108, 101, 80, 114, 101, 102, 105, 120]).unwrap(), - LIT_19_VERSION: /* version */ _support::decode_lit(&[179, 7, 118, 101, 114, 115, 105, 111, 110]).unwrap() - } - } -} - -pub fn _bundle() -> &'static [u8] { - b"\ - \xb4\xb3\x06\x62\x75\x6e\x64\x6c\x65\xb7\xb5\xb3\x06\x73\x63\x68\ - \x65\x6d\x61\x84\xb4\xb3\x06\x73\x63\x68\x65\x6d\x61\xb7\xb3\x07\ - \x76\x65\x72\x73\x69\x6f\x6e\xb0\x01\x01\xb3\x0b\x64\x65\x66\x69\ - \x6e\x69\x74\x69\x6f\x6e\x73\xb7\xb3\x03\x52\x65\x66\xb4\xb3\x03\ - \x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\x03\x72\x65\x66\x84\xb4\ - \xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\ - \xb3\x06\x6d\x6f\x64\x75\x6c\x65\xb4\xb3\x03\x72\x65\x66\xb5\x84\ - \xb3\x0a\x4d\x6f\x64\x75\x6c\x65\x50\x61\x74\x68\x84\x84\xb4\xb3\ - \x05\x6e\x61\x6d\x65\x64\xb3\x04\x6e\x61\x6d\x65\xb4\xb3\x04\x61\ - \x74\x6f\x6d\xb3\x06\x53\x79\x6d\x62\x6f\x6c\x84\x84\x84\x84\x84\ - \xb3\x06\x42\x75\x6e\x64\x6c\x65\xb4\xb3\x03\x72\x65\x63\xb4\xb3\ - \x03\x6c\x69\x74\xb3\x06\x62\x75\x6e\x64\x6c\x65\x84\xb4\xb3\x05\ - \x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x07\ - \x6d\x6f\x64\x75\x6c\x65\x73\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\ - \x07\x4d\x6f\x64\x75\x6c\x65\x73\x84\x84\x84\x84\x84\xb3\x06\x53\ - \x63\x68\x65\x6d\x61\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\ - \x74\xb3\x06\x73\x63\x68\x65\x6d\x61\x84\xb4\xb3\x05\x74\x75\x70\ - \x6c\x65\xb5\xb4\xb3\x04\x64\x69\x63\x74\xb7\xb3\x07\x76\x65\x72\ - \x73\x69\x6f\x6e\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x07\x76\x65\ - \x72\x73\x69\x6f\x6e\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x07\x56\ - \x65\x72\x73\x69\x6f\x6e\x84\x84\xb3\x0b\x64\x65\x66\x69\x6e\x69\ - \x74\x69\x6f\x6e\x73\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x0b\x64\ - \x65\x66\x69\x6e\x69\x74\x69\x6f\x6e\x73\xb4\xb3\x03\x72\x65\x66\ - \xb5\x84\xb3\x0b\x44\x65\x66\x69\x6e\x69\x74\x69\x6f\x6e\x73\x84\ - \x84\xb3\x0c\x65\x6d\x62\x65\x64\x64\x65\x64\x54\x79\x70\x65\xb4\ - \xb3\x05\x6e\x61\x6d\x65\x64\xb3\x0c\x65\x6d\x62\x65\x64\x64\x65\ - \x64\x54\x79\x70\x65\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x10\x45\ - \x6d\x62\x65\x64\x64\x65\x64\x54\x79\x70\x65\x4e\x61\x6d\x65\x84\ - \x84\x84\x84\x84\x84\x84\xb3\x07\x42\x69\x6e\x64\x69\x6e\x67\xb4\ - \xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\x05\x6e\x61\x6d\ - \x65\x64\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\ - \x61\x6d\x65\x64\xb3\x04\x6e\x61\x6d\x65\xb4\xb3\x04\x61\x74\x6f\ - \x6d\xb3\x06\x53\x79\x6d\x62\x6f\x6c\x84\x84\xb4\xb3\x05\x6e\x61\ - \x6d\x65\x64\xb3\x07\x70\x61\x74\x74\x65\x72\x6e\xb4\xb3\x03\x72\ - \x65\x66\xb5\x84\xb3\x0d\x53\x69\x6d\x70\x6c\x65\x50\x61\x74\x74\ - \x65\x72\x6e\x84\x84\x84\x84\x84\xb3\x07\x4d\x6f\x64\x75\x6c\x65\ - \x73\xb4\xb3\x06\x64\x69\x63\x74\x6f\x66\xb4\xb3\x03\x72\x65\x66\ - \xb5\x84\xb3\x0a\x4d\x6f\x64\x75\x6c\x65\x50\x61\x74\x68\x84\xb4\ - \xb3\x03\x72\x65\x66\xb5\x84\xb3\x06\x53\x63\x68\x65\x6d\x61\x84\ - \x84\xb3\x07\x50\x61\x74\x74\x65\x72\x6e\xb4\xb3\x02\x6f\x72\xb5\ - \xb5\xb1\x0d\x53\x69\x6d\x70\x6c\x65\x50\x61\x74\x74\x65\x72\x6e\ - \xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0d\x53\x69\x6d\x70\x6c\x65\ - \x50\x61\x74\x74\x65\x72\x6e\x84\x84\xb5\xb1\x0f\x43\x6f\x6d\x70\ - \x6f\x75\x6e\x64\x50\x61\x74\x74\x65\x72\x6e\xb4\xb3\x03\x72\x65\ - \x66\xb5\x84\xb3\x0f\x43\x6f\x6d\x70\x6f\x75\x6e\x64\x50\x61\x74\ - \x74\x65\x72\x6e\x84\x84\x84\x84\xb3\x07\x56\x65\x72\x73\x69\x6f\ - \x6e\xb4\xb3\x03\x6c\x69\x74\xb0\x01\x01\x84\xb3\x08\x41\x74\x6f\ - \x6d\x4b\x69\x6e\x64\xb4\xb3\x02\x6f\x72\xb5\xb5\xb1\x07\x42\x6f\ - \x6f\x6c\x65\x61\x6e\xb4\xb3\x03\x6c\x69\x74\xb3\x07\x42\x6f\x6f\ - \x6c\x65\x61\x6e\x84\x84\xb5\xb1\x06\x44\x6f\x75\x62\x6c\x65\xb4\ - \xb3\x03\x6c\x69\x74\xb3\x06\x44\x6f\x75\x62\x6c\x65\x84\x84\xb5\ - \xb1\x0d\x53\x69\x67\x6e\x65\x64\x49\x6e\x74\x65\x67\x65\x72\xb4\ - \xb3\x03\x6c\x69\x74\xb3\x0d\x53\x69\x67\x6e\x65\x64\x49\x6e\x74\ - \x65\x67\x65\x72\x84\x84\xb5\xb1\x06\x53\x74\x72\x69\x6e\x67\xb4\ - \xb3\x03\x6c\x69\x74\xb3\x06\x53\x74\x72\x69\x6e\x67\x84\x84\xb5\ - \xb1\x0a\x42\x79\x74\x65\x53\x74\x72\x69\x6e\x67\xb4\xb3\x03\x6c\ - \x69\x74\xb3\x0a\x42\x79\x74\x65\x53\x74\x72\x69\x6e\x67\x84\x84\ - \xb5\xb1\x06\x53\x79\x6d\x62\x6f\x6c\xb4\xb3\x03\x6c\x69\x74\xb3\ - \x06\x53\x79\x6d\x62\x6f\x6c\x84\x84\x84\x84\xb3\x0a\x44\x65\x66\ - \x69\x6e\x69\x74\x69\x6f\x6e\xb4\xb3\x02\x6f\x72\xb5\xb5\xb1\x02\ - \x6f\x72\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\x02\ - \x6f\x72\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x0b\x74\ - \x75\x70\x6c\x65\x50\x72\x65\x66\x69\x78\xb5\xb4\xb3\x05\x6e\x61\ - \x6d\x65\x64\xb3\x08\x70\x61\x74\x74\x65\x72\x6e\x30\xb4\xb3\x03\ - \x72\x65\x66\xb5\x84\xb3\x10\x4e\x61\x6d\x65\x64\x41\x6c\x74\x65\ - \x72\x6e\x61\x74\x69\x76\x65\x84\x84\xb4\xb3\x05\x6e\x61\x6d\x65\ - \x64\xb3\x08\x70\x61\x74\x74\x65\x72\x6e\x31\xb4\xb3\x03\x72\x65\ - \x66\xb5\x84\xb3\x10\x4e\x61\x6d\x65\x64\x41\x6c\x74\x65\x72\x6e\ - \x61\x74\x69\x76\x65\x84\x84\x84\xb4\xb3\x05\x6e\x61\x6d\x65\x64\ - \xb3\x08\x70\x61\x74\x74\x65\x72\x6e\x4e\xb4\xb3\x05\x73\x65\x71\ - \x6f\x66\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x10\x4e\x61\x6d\x65\ - \x64\x41\x6c\x74\x65\x72\x6e\x61\x74\x69\x76\x65\x84\x84\x84\x84\ - \x84\x84\x84\x84\xb5\xb1\x03\x61\x6e\x64\xb4\xb3\x03\x72\x65\x63\ - \xb4\xb3\x03\x6c\x69\x74\xb3\x03\x61\x6e\x64\x84\xb4\xb3\x05\x74\ - \x75\x70\x6c\x65\xb5\xb4\xb3\x0b\x74\x75\x70\x6c\x65\x50\x72\x65\ - \x66\x69\x78\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x08\x70\x61\ - \x74\x74\x65\x72\x6e\x30\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0c\ - \x4e\x61\x6d\x65\x64\x50\x61\x74\x74\x65\x72\x6e\x84\x84\xb4\xb3\ - \x05\x6e\x61\x6d\x65\x64\xb3\x08\x70\x61\x74\x74\x65\x72\x6e\x31\ - \xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0c\x4e\x61\x6d\x65\x64\x50\ - \x61\x74\x74\x65\x72\x6e\x84\x84\x84\xb4\xb3\x05\x6e\x61\x6d\x65\ - \x64\xb3\x08\x70\x61\x74\x74\x65\x72\x6e\x4e\xb4\xb3\x05\x73\x65\ - \x71\x6f\x66\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0c\x4e\x61\x6d\ - \x65\x64\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\x84\x84\x84\ - \x84\xb5\xb1\x07\x50\x61\x74\x74\x65\x72\x6e\xb4\xb3\x03\x72\x65\ - \x66\xb5\x84\xb3\x07\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\ - \xb3\x0a\x4d\x6f\x64\x75\x6c\x65\x50\x61\x74\x68\xb4\xb3\x05\x73\ - \x65\x71\x6f\x66\xb4\xb3\x04\x61\x74\x6f\x6d\xb3\x06\x53\x79\x6d\ - \x62\x6f\x6c\x84\x84\xb3\x0b\x44\x65\x66\x69\x6e\x69\x74\x69\x6f\ - \x6e\x73\xb4\xb3\x06\x64\x69\x63\x74\x6f\x66\xb4\xb3\x04\x61\x74\ - \x6f\x6d\xb3\x06\x53\x79\x6d\x62\x6f\x6c\x84\xb4\xb3\x03\x72\x65\ - \x66\xb5\x84\xb3\x0a\x44\x65\x66\x69\x6e\x69\x74\x69\x6f\x6e\x84\ - \x84\xb3\x0c\x4e\x61\x6d\x65\x64\x50\x61\x74\x74\x65\x72\x6e\xb4\ - \xb3\x02\x6f\x72\xb5\xb5\xb1\x05\x6e\x61\x6d\x65\x64\xb4\xb3\x03\ - \x72\x65\x66\xb5\x84\xb3\x07\x42\x69\x6e\x64\x69\x6e\x67\x84\x84\ - \xb5\xb1\x09\x61\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\xb4\xb3\x03\x72\ - \x65\x66\xb5\x84\xb3\x07\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\ - \x84\xb3\x0d\x53\x69\x6d\x70\x6c\x65\x50\x61\x74\x74\x65\x72\x6e\ - \xb4\xb3\x02\x6f\x72\xb5\xb5\xb1\x03\x61\x6e\x79\xb4\xb3\x03\x6c\ - \x69\x74\xb3\x03\x61\x6e\x79\x84\x84\xb5\xb1\x04\x61\x74\x6f\x6d\ - \xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\x04\x61\x74\ - \x6f\x6d\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\ - \x61\x6d\x65\x64\xb3\x08\x61\x74\x6f\x6d\x4b\x69\x6e\x64\xb4\xb3\ - \x03\x72\x65\x66\xb5\x84\xb3\x08\x41\x74\x6f\x6d\x4b\x69\x6e\x64\ - \x84\x84\x84\x84\x84\x84\xb5\xb1\x08\x65\x6d\x62\x65\x64\x64\x65\ - \x64\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\x08\x65\ - \x6d\x62\x65\x64\x64\x65\x64\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\ - \xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x09\x69\x6e\x74\x65\x72\ - \x66\x61\x63\x65\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0d\x53\x69\ - \x6d\x70\x6c\x65\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\x84\ - \x84\xb5\xb1\x03\x6c\x69\x74\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\ - \x6c\x69\x74\xb3\x03\x6c\x69\x74\x84\xb4\xb3\x05\x74\x75\x70\x6c\ - \x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x05\x76\x61\x6c\x75\ - \x65\xb3\x03\x61\x6e\x79\x84\x84\x84\x84\x84\xb5\xb1\x05\x73\x65\ - \x71\x6f\x66\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\ - \x05\x73\x65\x71\x6f\x66\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\ - \xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x07\x70\x61\x74\x74\x65\x72\ - \x6e\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0d\x53\x69\x6d\x70\x6c\ - \x65\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\x84\x84\xb5\xb1\ - \x05\x73\x65\x74\x6f\x66\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\ - \x69\x74\xb3\x05\x73\x65\x74\x6f\x66\x84\xb4\xb3\x05\x74\x75\x70\ - \x6c\x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x07\x70\x61\x74\ - \x74\x65\x72\x6e\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0d\x53\x69\ - \x6d\x70\x6c\x65\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\x84\ - \x84\xb5\xb1\x06\x64\x69\x63\x74\x6f\x66\xb4\xb3\x03\x72\x65\x63\ - \xb4\xb3\x03\x6c\x69\x74\xb3\x06\x64\x69\x63\x74\x6f\x66\x84\xb4\ - \xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\ - \xb3\x03\x6b\x65\x79\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0d\x53\ - \x69\x6d\x70\x6c\x65\x50\x61\x74\x74\x65\x72\x6e\x84\x84\xb4\xb3\ - \x05\x6e\x61\x6d\x65\x64\xb3\x05\x76\x61\x6c\x75\x65\xb4\xb3\x03\ - \x72\x65\x66\xb5\x84\xb3\x0d\x53\x69\x6d\x70\x6c\x65\x50\x61\x74\ - \x74\x65\x72\x6e\x84\x84\x84\x84\x84\x84\xb5\xb1\x03\x52\x65\x66\ - \xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x03\x52\x65\x66\x84\x84\x84\ - \x84\xb3\x0f\x43\x6f\x6d\x70\x6f\x75\x6e\x64\x50\x61\x74\x74\x65\ - \x72\x6e\xb4\xb3\x02\x6f\x72\xb5\xb5\xb1\x03\x72\x65\x63\xb4\xb3\ - \x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\xb3\x03\x72\x65\x63\x84\ - \xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\ - \x64\xb3\x05\x6c\x61\x62\x65\x6c\xb4\xb3\x03\x72\x65\x66\xb5\x84\ - \xb3\x0c\x4e\x61\x6d\x65\x64\x50\x61\x74\x74\x65\x72\x6e\x84\x84\ - \xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x06\x66\x69\x65\x6c\x64\x73\ - \xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0c\x4e\x61\x6d\x65\x64\x50\ - \x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\x84\x84\xb5\xb1\x05\x74\ - \x75\x70\x6c\x65\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\ - \xb3\x05\x74\x75\x70\x6c\x65\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\ - \xb5\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x08\x70\x61\x74\x74\x65\ - \x72\x6e\x73\xb4\xb3\x05\x73\x65\x71\x6f\x66\xb4\xb3\x03\x72\x65\ - \x66\xb5\x84\xb3\x0c\x4e\x61\x6d\x65\x64\x50\x61\x74\x74\x65\x72\ - \x6e\x84\x84\x84\x84\x84\x84\x84\xb5\xb1\x0b\x74\x75\x70\x6c\x65\ - \x50\x72\x65\x66\x69\x78\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\ - \x69\x74\xb3\x0b\x74\x75\x70\x6c\x65\x50\x72\x65\x66\x69\x78\x84\ - \xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\xb3\x05\x6e\x61\x6d\x65\ - \x64\xb3\x05\x66\x69\x78\x65\x64\xb4\xb3\x05\x73\x65\x71\x6f\x66\ - \xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x0c\x4e\x61\x6d\x65\x64\x50\ - \x61\x74\x74\x65\x72\x6e\x84\x84\x84\xb4\xb3\x05\x6e\x61\x6d\x65\ - \x64\xb3\x08\x76\x61\x72\x69\x61\x62\x6c\x65\xb4\xb3\x03\x72\x65\ - \x66\xb5\x84\xb3\x12\x4e\x61\x6d\x65\x64\x53\x69\x6d\x70\x6c\x65\ - \x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\x84\x84\xb5\xb1\x04\ - \x64\x69\x63\x74\xb4\xb3\x03\x72\x65\x63\xb4\xb3\x03\x6c\x69\x74\ - \xb3\x04\x64\x69\x63\x74\x84\xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\ - \xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x07\x65\x6e\x74\x72\x69\x65\ - \x73\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x11\x44\x69\x63\x74\x69\ - \x6f\x6e\x61\x72\x79\x45\x6e\x74\x72\x69\x65\x73\x84\x84\x84\x84\ - \x84\x84\x84\x84\xb3\x10\x45\x6d\x62\x65\x64\x64\x65\x64\x54\x79\ - \x70\x65\x4e\x61\x6d\x65\xb4\xb3\x02\x6f\x72\xb5\xb5\xb1\x05\x66\ - \x61\x6c\x73\x65\xb4\xb3\x03\x6c\x69\x74\x80\x84\x84\xb5\xb1\x03\ - \x52\x65\x66\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\x03\x52\x65\x66\ - \x84\x84\x84\x84\xb3\x10\x4e\x61\x6d\x65\x64\x41\x6c\x74\x65\x72\ - \x6e\x61\x74\x69\x76\x65\xb4\xb3\x05\x74\x75\x70\x6c\x65\xb5\xb4\ - \xb3\x05\x6e\x61\x6d\x65\x64\xb3\x0c\x76\x61\x72\x69\x61\x6e\x74\ - \x4c\x61\x62\x65\x6c\xb4\xb3\x04\x61\x74\x6f\x6d\xb3\x06\x53\x74\ - \x72\x69\x6e\x67\x84\x84\xb4\xb3\x05\x6e\x61\x6d\x65\x64\xb3\x07\ - \x70\x61\x74\x74\x65\x72\x6e\xb4\xb3\x03\x72\x65\x66\xb5\x84\xb3\ - \x07\x50\x61\x74\x74\x65\x72\x6e\x84\x84\x84\x84\xb3\x11\x44\x69\ - \x63\x74\x69\x6f\x6e\x61\x72\x79\x45\x6e\x74\x72\x69\x65\x73\xb4\ - \xb3\x06\x64\x69\x63\x74\x6f\x66\xb3\x03\x61\x6e\x79\xb4\xb3\x03\ - \x72\x65\x66\xb5\x84\xb3\x12\x4e\x61\x6d\x65\x64\x53\x69\x6d\x70\ - \x6c\x65\x50\x61\x74\x74\x65\x72\x6e\x84\x84\xb3\x12\x4e\x61\x6d\ - \x65\x64\x53\x69\x6d\x70\x6c\x65\x50\x61\x74\x74\x65\x72\x6e\xb4\ - \xb3\x02\x6f\x72\xb5\xb5\xb1\x05\x6e\x61\x6d\x65\x64\xb4\xb3\x03\ - \x72\x65\x66\xb5\x84\xb3\x07\x42\x69\x6e\x64\x69\x6e\x67\x84\x84\ - \xb5\xb1\x09\x61\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\xb4\xb3\x03\x72\ - \x65\x66\xb5\x84\xb3\x0d\x53\x69\x6d\x70\x6c\x65\x50\x61\x74\x74\ - \x65\x72\x6e\x84\x84\x84\x84\x84\xb3\x0c\x65\x6d\x62\x65\x64\x64\ - \x65\x64\x54\x79\x70\x65\x80\x84\x84\x84\x84" -} diff --git a/implementations/rust/preserves-schema/src/gen/schema.rs b/implementations/rust/preserves-schema/src/gen/schema.rs deleted file mode 100644 index 0276f82..0000000 --- a/implementations/rust/preserves-schema/src/gen/schema.rs +++ /dev/null @@ -1,1941 +0,0 @@ -#![allow(unused_parens)] -#![allow(unused_imports)] -#![cfg_attr(rustfmt, rustfmt_skip)] - -use std::convert::TryFrom; -use crate::support as _support; -use _support::Deserialize; -use _support::Parse; -use _support::Unparse; -use _support::preserves; -use preserves::value::Domain; -use preserves::value::NestedValue; - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum AtomKind { - Boolean, - Double, - SignedInteger, - String, - ByteString, - Symbol -} - -impl preserves::value::Domain for AtomKind {} - -fn read_atom_kind_boolean<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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 read_atom_kind_double<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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 read_atom_kind_signed_integer<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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 read_atom_kind_string<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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 read_atom_kind_byte_string<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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 read_atom_kind_symbol<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for AtomKind { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_atom_kind_boolean(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_atom_kind_double(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_atom_kind_signed_integer(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_atom_kind_string(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_atom_kind_byte_string(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match 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")) - } -} - -fn parse_atom_kind_boolean< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_0_BOOLEAN { return Err(_support::ParseError::conformance_error("schema.AtomKind::Boolean")); } - let _tmp0 = (); - Ok(AtomKind::Boolean) -} - -fn parse_atom_kind_double< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_1_DOUBLE { return Err(_support::ParseError::conformance_error("schema.AtomKind::Double")); } - let _tmp0 = (); - Ok(AtomKind::Double) -} - -fn parse_atom_kind_signed_integer< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_2_SIGNED_INTEGER { return Err(_support::ParseError::conformance_error("schema.AtomKind::SignedInteger")); } - let _tmp0 = (); - Ok(AtomKind::SignedInteger) -} - -fn parse_atom_kind_string< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_3_STRING { return Err(_support::ParseError::conformance_error("schema.AtomKind::String")); } - let _tmp0 = (); - Ok(AtomKind::String) -} - -fn parse_atom_kind_byte_string< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_4_BYTE_STRING { return Err(_support::ParseError::conformance_error("schema.AtomKind::ByteString")); } - let _tmp0 = (); - Ok(AtomKind::ByteString) -} - -fn parse_atom_kind_symbol< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_5_SYMBOL { return Err(_support::ParseError::conformance_error("schema.AtomKind::Symbol")); } - let _tmp0 = (); - Ok(AtomKind::Symbol) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for AtomKind { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_atom_kind_boolean(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_atom_kind_double(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_atom_kind_signed_integer(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_atom_kind_string(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_atom_kind_byte_string(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_atom_kind_symbol(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.AtomKind")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for AtomKind { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - AtomKind::Boolean => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_0_BOOLEAN).clone(), - AtomKind::Double => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_1_DOUBLE).clone(), - AtomKind::SignedInteger => ( - &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_2_SIGNED_INTEGER - ).clone(), - AtomKind::String => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_3_STRING).clone(), - AtomKind::ByteString => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_4_BYTE_STRING).clone(), - AtomKind::Symbol => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_5_SYMBOL).clone(), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Binding<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - pub name: std::string::String, - pub pattern: SimplePattern<_Value> -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Binding<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Binding<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = r.next_symbol()?.into_owned(); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp3 = SimplePattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(Binding {name: _tmp2, pattern: _tmp3}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Binding<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_6_NAMED { return Err(_support::ParseError::conformance_error("schema.Binding")); } - let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.Binding")); } - let _tmp2 = (&_tmp0.fields()[0]).value().to_symbol()?; - let _tmp3 = SimplePattern::parse(_ctxt, (&_tmp0.fields()[1]))?; - Ok(Binding {name: _tmp2.clone(), pattern: _tmp3}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Binding<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let Binding {name: _tmp0, pattern: _tmp1} = self; - { - let mut _tmp2 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_6_NAMED).clone()]); - _tmp2.fields_vec_mut().push(preserves::value::Value::symbol(_tmp0).wrap()); - _tmp2.fields_vec_mut().push(_tmp1.unparse(_ctxt)); - _tmp2.finish().wrap() - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Bundle<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - pub modules: Modules<_Value> -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Bundle<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Bundle<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = Modules::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(Bundle {modules: _tmp2}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Bundle<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_7_BUNDLE { return Err(_support::ParseError::conformance_error("schema.Bundle")); } - let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.Bundle")); } - let _tmp2 = Modules::parse(_ctxt, (&_tmp0.fields()[0]))?; - Ok(Bundle {modules: _tmp2}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Bundle<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let Bundle {modules: _tmp0} = self; - { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_7_BUNDLE).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.unparse(_ctxt)); - _tmp1.finish().wrap() - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum CompoundPattern<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - Rec { - label: std::boxed::Box>, - fields: std::boxed::Box> - }, - Tuple { - patterns: std::vec::Vec> - }, - TuplePrefix { - fixed: std::vec::Vec>, - variable: std::boxed::Box> - }, - Dict { - entries: std::boxed::Box> - } -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for CompoundPattern<_Value> {} - -fn read_compound_pattern_rec<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = NamedPattern::deserialize(r)?; - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp3 = NamedPattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(CompoundPattern::Rec {label: std::boxed::Box::new(_tmp2), fields: std::boxed::Box::new(_tmp3)}) -} - -fn read_compound_pattern_tuple<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - r.open_sequence()?; - let mut _tmp4 = _support::B::Type::default(); - let mut _tmp3 = std::vec::Vec::new(); - while !r.close_compound(&mut _tmp4, &_support::B::Item::SequenceValue)? { - _tmp4.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp4)?; - let _tmp5 = NamedPattern::deserialize(r)?; - _tmp3.push(_tmp5); - } - let _tmp2 = _tmp3; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(CompoundPattern::Tuple {patterns: _tmp2}) -} - -fn read_compound_pattern_tuple_prefix<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - r.open_sequence()?; - let mut _tmp4 = _support::B::Type::default(); - let mut _tmp3 = std::vec::Vec::new(); - while !r.close_compound(&mut _tmp4, &_support::B::Item::SequenceValue)? { - _tmp4.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp4)?; - let _tmp5 = NamedPattern::deserialize(r)?; - _tmp3.push(_tmp5); - } - let _tmp2 = _tmp3; - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp6 = NamedSimplePattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(CompoundPattern::TuplePrefix {fixed: _tmp2, variable: std::boxed::Box::new(_tmp6)}) -} - -fn read_compound_pattern_dict<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = DictionaryEntries::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(CompoundPattern::Dict {entries: std::boxed::Box::new(_tmp2)}) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for CompoundPattern<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_compound_pattern_rec(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_compound_pattern_tuple(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_compound_pattern_tuple_prefix(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match 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 parse_compound_pattern_rec< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_8_REC { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::rec")); } - let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::rec")); } - let _tmp2 = NamedPattern::parse(_ctxt, (&_tmp0.fields()[0]))?; - let _tmp3 = NamedPattern::parse(_ctxt, (&_tmp0.fields()[1]))?; - Ok(CompoundPattern::Rec {label: std::boxed::Box::new(_tmp2), fields: std::boxed::Box::new(_tmp3)}) -} - -fn parse_compound_pattern_tuple< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_9_TUPLE { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuple")); } - let _tmp1 = (); - 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::parse(_ctxt, _tmp4)?; - _tmp2.push(_tmp5); - } - Ok(CompoundPattern::Tuple {patterns: _tmp2}) -} - -fn parse_compound_pattern_tuple_prefix< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_10_TUPLE_PREFIX { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::tuplePrefix")); } - let _tmp1 = (); - 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::parse(_ctxt, _tmp4)?; - _tmp2.push(_tmp5); - } - let _tmp6 = NamedSimplePattern::parse(_ctxt, (&_tmp0.fields()[1]))?; - Ok(CompoundPattern::TuplePrefix {fixed: _tmp2, variable: std::boxed::Box::new(_tmp6)}) -} - -fn parse_compound_pattern_dict< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_11_DICT { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::dict")); } - let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.CompoundPattern::dict")); } - let _tmp2 = DictionaryEntries::parse(_ctxt, (&_tmp0.fields()[0]))?; - Ok(CompoundPattern::Dict {entries: std::boxed::Box::new(_tmp2)}) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for CompoundPattern<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_compound_pattern_rec(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_compound_pattern_tuple(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_compound_pattern_tuple_prefix(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_compound_pattern_dict(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.CompoundPattern")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for CompoundPattern<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - CompoundPattern::Rec {label: _tmp0, fields: _tmp1} => { - let mut _tmp2 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_8_REC).clone()]); - _tmp2.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp2.fields_vec_mut().push(_tmp1.as_ref().unparse(_ctxt)); - _tmp2.finish().wrap() - }, - CompoundPattern::Tuple {patterns: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_9_TUPLE).clone()]); - _tmp1.fields_vec_mut().push( - { - let mut _tmp2 = std::vec::Vec::new(); - for _tmp3 in _tmp0 { - _tmp2.push(_tmp3.unparse(_ctxt)); - } - preserves::value::Value::Sequence(_tmp2).wrap() - } - ); - _tmp1.finish().wrap() - }, - CompoundPattern::TuplePrefix {fixed: _tmp0, variable: _tmp1} => { - let mut _tmp2 = preserves::value::Record(vec![( - &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_10_TUPLE_PREFIX - ).clone()]); - _tmp2.fields_vec_mut().push( - { - let mut _tmp3 = std::vec::Vec::new(); - for _tmp4 in _tmp0 { - _tmp3.push(_tmp4.unparse(_ctxt)); - } - preserves::value::Value::Sequence(_tmp3).wrap() - } - ); - _tmp2.fields_vec_mut().push(_tmp1.as_ref().unparse(_ctxt)); - _tmp2.finish().wrap() - }, - CompoundPattern::Dict {entries: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_11_DICT).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp1.finish().wrap() - }, - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum Definition<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - Or { - pattern_0: std::boxed::Box>, - pattern_1: std::boxed::Box>, - pattern_n: std::vec::Vec> - }, - And { - pattern_0: std::boxed::Box>, - pattern_1: std::boxed::Box>, - pattern_n: std::vec::Vec> - }, - Pattern(std::boxed::Box>) -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Definition<_Value> {} - -fn read_definition_or<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - r.open_sequence()?; - let mut _tmp2 = _support::B::Type::default(); - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp3 = NamedAlternative::deserialize(r)?; - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp4 = NamedAlternative::deserialize(r)?; - let mut _tmp6 = std::vec::Vec::new(); - while !r.close_compound(&mut _tmp2, &_support::B::Item::SequenceValue)? { - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp7 = NamedAlternative::deserialize(r)?; - _tmp6.push(_tmp7); - } - let _tmp5 = _tmp6; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(Definition::Or { - pattern_0: std::boxed::Box::new(_tmp3), - pattern_1: std::boxed::Box::new(_tmp4), - pattern_n: _tmp5 - }) -} - -fn read_definition_and<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - r.open_sequence()?; - let mut _tmp2 = _support::B::Type::default(); - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp3 = NamedPattern::deserialize(r)?; - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp4 = NamedPattern::deserialize(r)?; - let mut _tmp6 = std::vec::Vec::new(); - while !r.close_compound(&mut _tmp2, &_support::B::Item::SequenceValue)? { - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp7 = NamedPattern::deserialize(r)?; - _tmp6.push(_tmp7); - } - let _tmp5 = _tmp6; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(Definition::And { - pattern_0: std::boxed::Box::new(_tmp3), - pattern_1: std::boxed::Box::new(_tmp4), - pattern_n: _tmp5 - }) -} - -fn read_definition_pattern<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = Pattern::deserialize(r)?; - Ok(Definition::Pattern(std::boxed::Box::new(_tmp0))) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Definition<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_definition_or(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_definition_and(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_definition_pattern(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - Err(_support::ParseError::conformance_error("schema.Definition")) - } -} - -fn parse_definition_or< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_12_OR { return Err(_support::ParseError::conformance_error("schema.Definition::or")); } - let _tmp1 = (); - 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::conformance_error("schema.Definition::or")); } - let _tmp3 = NamedAlternative::parse(_ctxt, (&_tmp2[0]))?; - let _tmp4 = NamedAlternative::parse(_ctxt, (&_tmp2[1]))?; - let mut _tmp5 = std::vec::Vec::new(); - for _tmp6 in &_tmp2[2..] { - let _tmp7 = NamedAlternative::parse(_ctxt, _tmp6)?; - _tmp5.push(_tmp7); - } - Ok(Definition::Or { - pattern_0: std::boxed::Box::new(_tmp3), - pattern_1: std::boxed::Box::new(_tmp4), - pattern_n: _tmp5 - }) -} - -fn parse_definition_and< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_13_AND { return Err(_support::ParseError::conformance_error("schema.Definition::and")); } - let _tmp1 = (); - 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::conformance_error("schema.Definition::and")); } - let _tmp3 = NamedPattern::parse(_ctxt, (&_tmp2[0]))?; - let _tmp4 = NamedPattern::parse(_ctxt, (&_tmp2[1]))?; - let mut _tmp5 = std::vec::Vec::new(); - for _tmp6 in &_tmp2[2..] { - let _tmp7 = NamedPattern::parse(_ctxt, _tmp6)?; - _tmp5.push(_tmp7); - } - Ok(Definition::And { - pattern_0: std::boxed::Box::new(_tmp3), - pattern_1: std::boxed::Box::new(_tmp4), - pattern_n: _tmp5 - }) -} - -fn parse_definition_pattern< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = Pattern::parse(_ctxt, value)?; - Ok(Definition::Pattern(std::boxed::Box::new(_tmp0))) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Definition<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_definition_or(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_definition_and(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_definition_pattern(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.Definition")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Definition<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - Definition::Or {pattern_0: _tmp0, pattern_1: _tmp1, pattern_n: _tmp2} => { - let mut _tmp3 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_12_OR).clone()]); - _tmp3.fields_vec_mut().push( - { - let mut _tmp4 = std::vec::Vec::new(); - _tmp4.push(_tmp0.as_ref().unparse(_ctxt)); - _tmp4.push(_tmp1.as_ref().unparse(_ctxt)); - for _tmp5 in _tmp2 { - _tmp4.push(_tmp5.unparse(_ctxt)); - } - preserves::value::Value::Sequence(_tmp4).wrap() - } - ); - _tmp3.finish().wrap() - }, - Definition::And {pattern_0: _tmp0, pattern_1: _tmp1, pattern_n: _tmp2} => { - let mut _tmp3 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_13_AND).clone()]); - _tmp3.fields_vec_mut().push( - { - let mut _tmp4 = std::vec::Vec::new(); - _tmp4.push(_tmp0.as_ref().unparse(_ctxt)); - _tmp4.push(_tmp1.as_ref().unparse(_ctxt)); - for _tmp5 in _tmp2 { - _tmp4.push(_tmp5.unparse(_ctxt)); - } - preserves::value::Value::Sequence(_tmp4).wrap() - } - ); - _tmp3.finish().wrap() - }, - Definition::Pattern(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Definitions<_Value: preserves::value::NestedValue = preserves::value::IOValue>(pub preserves::value::Map>); - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Definitions<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Definitions<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_dictionary()?; - let mut _tmp2 = _support::B::Type::default(); - let mut _tmp1 = preserves::value::Map::new(); - while !r.close_compound(&mut _tmp2, &_support::B::Item::DictionaryKey)? { - _tmp2.shift(Some(_support::B::Item::DictionaryKey)); - r.boundary(&_tmp2)?; - let _tmp3 = r.next_symbol()?.into_owned(); - _tmp2.shift(Some(_support::B::Item::DictionaryValue)); - r.boundary(&_tmp2)?; - let _tmp4 = Definition::deserialize(r)?; - _tmp1.insert(_tmp3, _tmp4); - } - let _tmp0 = _tmp1; - Ok(Definitions(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Definitions<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let mut _tmp0 = preserves::value::Map::new(); - for (_tmp1, _tmp2) in value.value().to_dictionary()? { - let _tmp3 = _tmp1.value().to_symbol()?; - let _tmp4 = Definition::parse(_ctxt, _tmp2)?; - _tmp0.insert(_tmp3.clone(), _tmp4); - } - Ok(Definitions(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Definitions<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let Definitions(_tmp0) = self; - preserves::value::Value::Dictionary(_tmp0.iter().map(|(_tmp1, _tmp2)| (preserves::value::Value::symbol(_tmp1).wrap(), _tmp2.unparse(_ctxt))).collect()).wrap() - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct DictionaryEntries<_Value: preserves::value::NestedValue = preserves::value::IOValue>(pub preserves::value::Map<_Value, NamedSimplePattern<_Value>>); - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for DictionaryEntries<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for DictionaryEntries<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_dictionary()?; - let mut _tmp2 = _support::B::Type::default(); - let mut _tmp1 = preserves::value::Map::new(); - while !r.close_compound(&mut _tmp2, &_support::B::Item::DictionaryKey)? { - _tmp2.shift(Some(_support::B::Item::DictionaryKey)); - r.boundary(&_tmp2)?; - let _tmp3 = r.demand_next(true)?; - _tmp2.shift(Some(_support::B::Item::DictionaryValue)); - r.boundary(&_tmp2)?; - let _tmp4 = NamedSimplePattern::deserialize(r)?; - _tmp1.insert(_tmp3, _tmp4); - } - let _tmp0 = _tmp1; - Ok(DictionaryEntries(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for DictionaryEntries<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let mut _tmp0 = preserves::value::Map::new(); - for (_tmp1, _tmp2) in value.value().to_dictionary()? { - let _tmp3 = _tmp1; - let _tmp4 = NamedSimplePattern::parse(_ctxt, _tmp2)?; - _tmp0.insert(_tmp3.clone(), _tmp4); - } - Ok(DictionaryEntries(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for DictionaryEntries<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let DictionaryEntries(_tmp0) = self; - preserves::value::Value::Dictionary(_tmp0.iter().map(|(_tmp1, _tmp2)| (_tmp1.clone(), _tmp2.unparse(_ctxt))).collect()).wrap() - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum EmbeddedTypeName { - False, - Ref(std::boxed::Box) -} - -impl preserves::value::Domain for EmbeddedTypeName {} - -fn read_embedded_type_name_false<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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) -} - -fn read_embedded_type_name_ref<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _tmp0 = Ref::deserialize(r)?; - Ok(EmbeddedTypeName::Ref(std::boxed::Box::new(_tmp0))) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for EmbeddedTypeName { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_embedded_type_name_false(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_embedded_type_name_ref(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName")) - } -} - -fn parse_embedded_type_name_false< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_14_FALSE { return Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName::false")); } - let _tmp0 = (); - Ok(EmbeddedTypeName::False) -} - -fn parse_embedded_type_name_ref< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp0 = Ref::parse(_ctxt, value)?; - Ok(EmbeddedTypeName::Ref(std::boxed::Box::new(_tmp0))) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for EmbeddedTypeName { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_embedded_type_name_false(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_embedded_type_name_ref(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.EmbeddedTypeName")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for EmbeddedTypeName { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - EmbeddedTypeName::False => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_14_FALSE).clone(), - EmbeddedTypeName::Ref(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct ModulePath(pub std::vec::Vec); - -impl preserves::value::Domain for ModulePath {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for ModulePath { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_sequence()?; - let mut _tmp2 = _support::B::Type::default(); - let mut _tmp1 = std::vec::Vec::new(); - while !r.close_compound(&mut _tmp2, &_support::B::Item::SequenceValue)? { - _tmp2.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp2)?; - let _tmp3 = r.next_symbol()?.into_owned(); - _tmp1.push(_tmp3); - } - let _tmp0 = _tmp1; - Ok(ModulePath(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for ModulePath { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp1 = value.value().to_sequence()?; - let mut _tmp0 = std::vec::Vec::new(); - for _tmp2 in &_tmp1[0..] { - let _tmp3 = _tmp2.value().to_symbol()?; - _tmp0.push(_tmp3.clone()); - } - Ok(ModulePath(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for ModulePath { - fn unparse(&self, _ctxt: _L) -> _Value { - let ModulePath(_tmp0) = self; - { - 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() - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Modules<_Value: preserves::value::NestedValue = preserves::value::IOValue>(pub preserves::value::Map>); - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Modules<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Modules<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_dictionary()?; - let mut _tmp2 = _support::B::Type::default(); - let mut _tmp1 = preserves::value::Map::new(); - while !r.close_compound(&mut _tmp2, &_support::B::Item::DictionaryKey)? { - _tmp2.shift(Some(_support::B::Item::DictionaryKey)); - r.boundary(&_tmp2)?; - let _tmp3 = ModulePath::deserialize(r)?; - _tmp2.shift(Some(_support::B::Item::DictionaryValue)); - r.boundary(&_tmp2)?; - let _tmp4 = Schema::deserialize(r)?; - _tmp1.insert(_tmp3, _tmp4); - } - let _tmp0 = _tmp1; - Ok(Modules(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Modules<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let mut _tmp0 = preserves::value::Map::new(); - for (_tmp1, _tmp2) in value.value().to_dictionary()? { - let _tmp3 = ModulePath::parse(_ctxt, _tmp1)?; - let _tmp4 = Schema::parse(_ctxt, _tmp2)?; - _tmp0.insert(_tmp3, _tmp4); - } - Ok(Modules(_tmp0)) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Modules<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let Modules(_tmp0) = self; - preserves::value::Value::Dictionary(_tmp0.iter().map(|(_tmp1, _tmp2)| (_tmp1.unparse(_ctxt), _tmp2.unparse(_ctxt))).collect()).wrap() - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct NamedAlternative<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - pub variant_label: std::string::String, - pub pattern: Pattern<_Value> -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for NamedAlternative<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for NamedAlternative<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_sequence()?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp0)?; - let _tmp1 = r.next_str()?.into_owned(); - _tmp0.shift(Some(_support::B::Item::SequenceValue)); - r.boundary(&_tmp0)?; - let _tmp2 = Pattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::SequenceValue)?; - Ok(NamedAlternative {variant_label: _tmp1, pattern: _tmp2}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for NamedAlternative<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp0 = value.value().to_sequence()?; - if _tmp0.len() < 2 { return Err(_support::ParseError::conformance_error("schema.NamedAlternative")); } - let _tmp1 = (&_tmp0[0]).value().to_string()?; - let _tmp2 = Pattern::parse(_ctxt, (&_tmp0[1]))?; - Ok(NamedAlternative {variant_label: _tmp1.clone(), pattern: _tmp2}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for NamedAlternative<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let NamedAlternative {variant_label: _tmp0, pattern: _tmp1} = self; - { - let mut _tmp2 = std::vec::Vec::new(); - _tmp2.push(preserves::value::Value::from(_tmp0).wrap()); - _tmp2.push(_tmp1.unparse(_ctxt)); - preserves::value::Value::Sequence(_tmp2).wrap() - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum NamedPattern<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - Named(std::boxed::Box>), - Anonymous(std::boxed::Box>) -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for NamedPattern<_Value> {} - -fn read_named_pattern_named<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = Binding::deserialize(r)?; - Ok(NamedPattern::Named(std::boxed::Box::new(_tmp0))) -} - -fn read_named_pattern_anonymous<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = Pattern::deserialize(r)?; - Ok(NamedPattern::Anonymous(std::boxed::Box::new(_tmp0))) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for NamedPattern<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_named_pattern_named(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match 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 parse_named_pattern_named< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = Binding::parse(_ctxt, value)?; - Ok(NamedPattern::Named(std::boxed::Box::new(_tmp0))) -} - -fn parse_named_pattern_anonymous< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = Pattern::parse(_ctxt, value)?; - Ok(NamedPattern::Anonymous(std::boxed::Box::new(_tmp0))) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for NamedPattern<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_named_pattern_named(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_named_pattern_anonymous(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.NamedPattern")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for NamedPattern<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - NamedPattern::Named(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - NamedPattern::Anonymous(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum NamedSimplePattern<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - Named(std::boxed::Box>), - Anonymous(std::boxed::Box>) -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for NamedSimplePattern<_Value> {} - -fn read_named_simple_pattern_named<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = Binding::deserialize(r)?; - Ok(NamedSimplePattern::Named(std::boxed::Box::new(_tmp0))) -} - -fn read_named_simple_pattern_anonymous<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = SimplePattern::deserialize(r)?; - Ok(NamedSimplePattern::Anonymous(std::boxed::Box::new(_tmp0))) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for NamedSimplePattern<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_named_simple_pattern_named(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match 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 parse_named_simple_pattern_named< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = Binding::parse(_ctxt, value)?; - Ok(NamedSimplePattern::Named(std::boxed::Box::new(_tmp0))) -} - -fn parse_named_simple_pattern_anonymous< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = SimplePattern::parse(_ctxt, value)?; - Ok(NamedSimplePattern::Anonymous(std::boxed::Box::new(_tmp0))) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for NamedSimplePattern<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_named_simple_pattern_named(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_named_simple_pattern_anonymous(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.NamedSimplePattern")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for NamedSimplePattern<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - NamedSimplePattern::Named(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - NamedSimplePattern::Anonymous(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum Pattern<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - SimplePattern(std::boxed::Box>), - CompoundPattern(std::boxed::Box>) -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Pattern<_Value> {} - -fn read_pattern_simple_pattern<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = SimplePattern::deserialize(r)?; - Ok(Pattern::SimplePattern(std::boxed::Box::new(_tmp0))) -} - -fn read_pattern_compound_pattern<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = CompoundPattern::deserialize(r)?; - Ok(Pattern::CompoundPattern(std::boxed::Box::new(_tmp0))) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Pattern<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_pattern_simple_pattern(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match 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")) - } -} - -fn parse_pattern_simple_pattern< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = SimplePattern::parse(_ctxt, value)?; - Ok(Pattern::SimplePattern(std::boxed::Box::new(_tmp0))) -} - -fn parse_pattern_compound_pattern< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = CompoundPattern::parse(_ctxt, value)?; - Ok(Pattern::CompoundPattern(std::boxed::Box::new(_tmp0))) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Pattern<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_pattern_simple_pattern(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_pattern_compound_pattern(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.Pattern")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Pattern<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - Pattern::SimplePattern(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - Pattern::CompoundPattern(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Ref { - pub module: ModulePath, - pub name: std::string::String -} - -impl preserves::value::Domain for Ref {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Ref { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = ModulePath::deserialize(r)?; - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp3 = r.next_symbol()?.into_owned(); - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(Ref {module: _tmp2, name: _tmp3}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Ref { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_15_REF { return Err(_support::ParseError::conformance_error("schema.Ref")); } - let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.Ref")); } - let _tmp2 = ModulePath::parse(_ctxt, (&_tmp0.fields()[0]))?; - let _tmp3 = (&_tmp0.fields()[1]).value().to_symbol()?; - Ok(Ref {module: _tmp2, name: _tmp3.clone()}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Ref { - fn unparse(&self, _ctxt: _L) -> _Value { - let Ref {module: _tmp0, name: _tmp1} = self; - { - let mut _tmp2 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_15_REF).clone()]); - _tmp2.fields_vec_mut().push(_tmp0.unparse(_ctxt)); - _tmp2.fields_vec_mut().push(preserves::value::Value::symbol(_tmp1).wrap()); - _tmp2.finish().wrap() - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Schema<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - pub definitions: Definitions<_Value>, - pub embedded_type: EmbeddedTypeName, - pub version: Version -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for Schema<_Value> {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Schema<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - r.open_dictionary()?; - let mut _tmp2 = _support::B::Type::default(); - let mut _tmp3 = None; - let mut _tmp4 = None; - let mut _tmp5 = None; - while !r.close_compound(&mut _tmp2, &_support::B::Item::DictionaryKey)? { - _tmp2.shift(Some(_support::B::Item::DictionaryKey)); - r.boundary(&_tmp2)?; - match r.next_token(true)? { - preserves::value::Token::Atom(v) => match v.value() { - preserves::value::Value::Symbol(w) if w == "definitions" => { - _tmp2.shift(Some(_support::B::Item::DictionaryValue)); - r.boundary(&_tmp2)?; - _tmp3 = Some(Definitions::deserialize(r)?); - continue; - } - preserves::value::Value::Symbol(w) if w == "embeddedType" => { - _tmp2.shift(Some(_support::B::Item::DictionaryValue)); - r.boundary(&_tmp2)?; - _tmp4 = Some(EmbeddedTypeName::deserialize(r)?); - continue; - } - preserves::value::Value::Symbol(w) if w == "version" => { - _tmp2.shift(Some(_support::B::Item::DictionaryValue)); - r.boundary(&_tmp2)?; - _tmp5 = Some(Version::deserialize(r)?); - continue; - } - _ => return Err(_support::ParseError::conformance_error("schema.Schema"))?, - } - _ => return Err(_support::ParseError::conformance_error("schema.Schema"))?, - } - } - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(Schema { - definitions: _tmp3.ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?, - embedded_type: _tmp4.ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?, - version: _tmp5.ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))? - }) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Schema<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_16_SCHEMA { return Err(_support::ParseError::conformance_error("schema.Schema")); } - let _tmp1 = (); - 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( - &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_17_DEFINITIONS - ).ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?; - let _tmp4 = Definitions::parse(_ctxt, _tmp3)?; - let _tmp5 = _tmp2.get( - &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_18_EMBEDDED_TYPE - ).ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?; - let _tmp6 = EmbeddedTypeName::parse(_ctxt, _tmp5)?; - let _tmp7 = _tmp2.get(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_19_VERSION).ok_or_else(|| _support::ParseError::conformance_error("schema.Schema"))?; - let _tmp8 = Version::parse(_ctxt, _tmp7)?; - Ok(Schema {definitions: _tmp4, embedded_type: _tmp6, version: _tmp8}) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Schema<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - let Schema {definitions: _tmp0, embedded_type: _tmp1, version: _tmp2} = self; - { - let mut _tmp3 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_16_SCHEMA).clone()]); - _tmp3.fields_vec_mut().push( - { - let mut _tmp4 = preserves::value::Map::new(); - _tmp4.insert( - ( - &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_17_DEFINITIONS - ).clone(), - _tmp0.unparse(_ctxt) - ); - _tmp4.insert( - ( - &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_18_EMBEDDED_TYPE - ).clone(), - _tmp1.unparse(_ctxt) - ); - _tmp4.insert( - (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_19_VERSION).clone(), - _tmp2.unparse(_ctxt) - ); - preserves::value::Value::Dictionary(_tmp4).wrap() - } - ); - _tmp3.finish().wrap() - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub enum SimplePattern<_Value: preserves::value::NestedValue = preserves::value::IOValue> { - Any, - Atom { - atom_kind: std::boxed::Box - }, - Embedded { - interface: std::boxed::Box> - }, - Lit { - value: _Value - }, - Seqof { - pattern: std::boxed::Box> - }, - Setof { - pattern: std::boxed::Box> - }, - Dictof { - key: std::boxed::Box>, - value: std::boxed::Box> - }, - Ref(std::boxed::Box) -} - -impl<_Value: preserves::value::NestedValue> preserves::value::Domain for SimplePattern<_Value> {} - -fn read_simple_pattern_any<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - match r.next_token(true)? { - 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 read_simple_pattern_atom<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = AtomKind::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(SimplePattern::Atom {atom_kind: std::boxed::Box::new(_tmp2)}) -} - -fn read_simple_pattern_embedded<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = SimplePattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(SimplePattern::Embedded {interface: std::boxed::Box::new(_tmp2)}) -} - -fn read_simple_pattern_lit<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = r.demand_next(true)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(SimplePattern::Lit {value: _tmp2}) -} - -fn read_simple_pattern_seqof<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = SimplePattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(SimplePattern::Seqof {pattern: std::boxed::Box::new(_tmp2)}) -} - -fn read_simple_pattern_setof<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = SimplePattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(SimplePattern::Setof {pattern: std::boxed::Box::new(_tmp2)}) -} - -fn read_simple_pattern_dictof<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - r.open_record(None)?; - let mut _tmp0 = _support::B::Type::default(); - _tmp0.shift(Some(_support::B::Item::RecordLabel)); - r.boundary(&_tmp0)?; - match r.next_token(true)? { - 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 _tmp1 = (); - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp2 = SimplePattern::deserialize(r)?; - _tmp0.shift(Some(_support::B::Item::RecordField)); - r.boundary(&_tmp0)?; - let _tmp3 = SimplePattern::deserialize(r)?; - r.ensure_complete(_tmp0, &_support::B::Item::RecordField)?; - Ok(SimplePattern::Dictof {key: std::boxed::Box::new(_tmp2), value: std::boxed::Box::new(_tmp3)}) -} - -fn read_simple_pattern_ref<'de, _Value: preserves::value::NestedValue, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result, _support::ParseError> { - let _tmp0 = Ref::deserialize(r)?; - Ok(SimplePattern::Ref(std::boxed::Box::new(_tmp0))) -} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for SimplePattern<_Value> { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - let _mark = r.mark()?; - match read_simple_pattern_any(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_simple_pattern_atom(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_simple_pattern_embedded(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_simple_pattern_lit(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_simple_pattern_seqof(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_simple_pattern_setof(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match read_simple_pattern_dictof(r) { Err(e) if e.is_conformance_error() => r.restore(&_mark)?, result => return result } - match 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")) - } -} - -fn parse_simple_pattern_any< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_20_ANY { return Err(_support::ParseError::conformance_error("schema.SimplePattern::any")); } - let _tmp0 = (); - Ok(SimplePattern::Any) -} - -fn parse_simple_pattern_atom< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_21_ATOM { return Err(_support::ParseError::conformance_error("schema.SimplePattern::atom")); } - let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::atom")); } - let _tmp2 = AtomKind::parse(_ctxt, (&_tmp0.fields()[0]))?; - Ok(SimplePattern::Atom {atom_kind: std::boxed::Box::new(_tmp2)}) -} - -fn parse_simple_pattern_embedded< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_22_EMBEDDED { return Err(_support::ParseError::conformance_error("schema.SimplePattern::embedded")); } - let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::embedded")); } - let _tmp2 = SimplePattern::parse(_ctxt, (&_tmp0.fields()[0]))?; - Ok(SimplePattern::Embedded {interface: std::boxed::Box::new(_tmp2)}) -} - -fn parse_simple_pattern_lit< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_23_LIT { return Err(_support::ParseError::conformance_error("schema.SimplePattern::lit")); } - let _tmp1 = (); - 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 parse_simple_pattern_seqof< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_24_SEQOF { return Err(_support::ParseError::conformance_error("schema.SimplePattern::seqof")); } - let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::seqof")); } - let _tmp2 = SimplePattern::parse(_ctxt, (&_tmp0.fields()[0]))?; - Ok(SimplePattern::Seqof {pattern: std::boxed::Box::new(_tmp2)}) -} - -fn parse_simple_pattern_setof< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_25_SETOF { return Err(_support::ParseError::conformance_error("schema.SimplePattern::setof")); } - let _tmp1 = (); - if _tmp0.fields().len() < 1 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::setof")); } - let _tmp2 = SimplePattern::parse(_ctxt, (&_tmp0.fields()[0]))?; - Ok(SimplePattern::Setof {pattern: std::boxed::Box::new(_tmp2)}) -} - -fn parse_simple_pattern_dictof< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = value.value().to_record(None)?; - if _tmp0.label() != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_26_DICTOF { return Err(_support::ParseError::conformance_error("schema.SimplePattern::dictof")); } - let _tmp1 = (); - if _tmp0.fields().len() < 2 { return Err(_support::ParseError::conformance_error("schema.SimplePattern::dictof")); } - let _tmp2 = SimplePattern::parse(_ctxt, (&_tmp0.fields()[0]))?; - let _tmp3 = SimplePattern::parse(_ctxt, (&_tmp0.fields()[1]))?; - Ok(SimplePattern::Dictof {key: std::boxed::Box::new(_tmp2), value: std::boxed::Box::new(_tmp3)}) -} - -fn parse_simple_pattern_ref< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a ->(_ctxt: _L, value: &_Value) -> std::result::Result, _support::ParseError> { - let _tmp0 = Ref::parse(_ctxt, value)?; - Ok(SimplePattern::Ref(std::boxed::Box::new(_tmp0))) -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for SimplePattern<_Value> { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if let Ok(r) = parse_simple_pattern_any(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_atom(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_embedded(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_lit(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_seqof(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_setof(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_dictof(_ctxt, value) { return Ok(r); } - if let Ok(r) = parse_simple_pattern_ref(_ctxt, value) { return Ok(r); } - Err(_support::ParseError::conformance_error("schema.SimplePattern")) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for SimplePattern<_Value> { - fn unparse(&self, _ctxt: _L) -> _Value { - match self { - SimplePattern::Any => (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_20_ANY).clone(), - SimplePattern::Atom {atom_kind: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_21_ATOM).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp1.finish().wrap() - }, - SimplePattern::Embedded {interface: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_22_EMBEDDED).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp1.finish().wrap() - }, - SimplePattern::Lit {value: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_23_LIT).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.clone()); - _tmp1.finish().wrap() - }, - SimplePattern::Seqof {pattern: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_24_SEQOF).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp1.finish().wrap() - }, - SimplePattern::Setof {pattern: _tmp0} => { - let mut _tmp1 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_25_SETOF).clone()]); - _tmp1.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp1.finish().wrap() - }, - SimplePattern::Dictof {key: _tmp0, value: _tmp1} => { - let mut _tmp2 = preserves::value::Record(vec![(&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_26_DICTOF).clone()]); - _tmp2.fields_vec_mut().push(_tmp0.as_ref().unparse(_ctxt)); - _tmp2.fields_vec_mut().push(_tmp1.as_ref().unparse(_ctxt)); - _tmp2.finish().wrap() - }, - SimplePattern::Ref(_tmp0) => _tmp0.as_ref().unparse(_ctxt), - } - } -} - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)] -pub struct Version; - -impl preserves::value::Domain for Version {} - -impl<_Value: preserves::value::NestedValue> _support::Deserialize<_Value> for Version { - fn deserialize<'de, R: _support::Reader<'de, _Value>>(r: &mut R) -> std::result::Result { - match r.next_token(true)? { - 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) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Parse<_L, _Value> for Version { - fn parse(_ctxt: _L, value: &_Value) -> std::result::Result { - if value != &<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_27_1 { return Err(_support::ParseError::conformance_error("schema.Version")); } - let _tmp0 = (); - Ok(Version) - } -} - -impl< - 'a, - _L: Copy + Into<&'a crate::gen::Language<_Value>>, - _Value: preserves::value::NestedValue + 'a -> _support::Unparse<_L, _Value> for Version { - fn unparse(&self, _ctxt: _L) -> _Value { - let Version = self; - (&<_L as Into<&'a crate::gen::Language<_Value>>>::into(_ctxt).LIT_27_1).clone() - } -} diff --git a/implementations/rust/preserves-schema/src/lib.rs b/implementations/rust/preserves-schema/src/lib.rs deleted file mode 100644 index 289c037..0000000 --- a/implementations/rust/preserves-schema/src/lib.rs +++ /dev/null @@ -1,98 +0,0 @@ -#![doc = concat!( - include_str!("../README.md"), - "# What is Preserves Schema?\n\n", - include_str!("../doc/what-is-preserves-schema.md"), - include_str!("../doc/example.md"), -)] - -pub mod compiler; -/// Auto-generated Preserves Schema Metaschema types, parsers, and unparsers. -pub mod gen; -pub mod support; -pub mod syntax; - -pub use support::Codec; -pub use support::Deserialize; -pub use support::ParseError; - -#[cfg(test)] -mod tests { - #[test] - fn can_access_preserves_core() { - use preserves::value::*; - assert_eq!(format!("{:?}", UnwrappedIOValue::from(3 + 4)), "7"); - } - - #[test] - fn simple_rendering() { - use crate::syntax::block::*; - use crate::*; - - let code = semiblock![ - seq!["f", parens!["a", "b", "c"]], - seq!["f", parens!["a", "b", "c"]], - seq!["f", parens!["a", "b", "c"]], - seq!["f", parens!["a", "b", "c"]], - seq!["f", parens!["a", "b", "c"]], - seq!["f", parens!["a", "b", "c"]], - seq!["g", parens![]], - parens![] - ]; - println!("{}", Formatter::to_string(&code)); - } - - #[test] - fn metaschema_parsing() -> Result<(), std::io::Error> { - use crate::gen::schema::*; - use crate::support::Parse; - use crate::support::Unparse; - use preserves::value::{BinarySource, IOBinarySource, Reader}; - - let mut f = std::fs::File::open("../../../schema/schema.bin")?; - let mut src = IOBinarySource::new(&mut f); - let mut reader = src.packed_iovalues(); - let schema = reader.demand_next(false)?; - let language = crate::gen::Language::default(); - let parsed = Schema::parse(&language, &schema).expect("successful parse"); - assert_eq!(schema, parsed.unparse(&language)); - Ok(()) - } -} - -#[macro_export] -macro_rules! define_language { - ($fname:ident () : $lang:ident < $default_value:ty > { $($field:ident : $($type:ident)::+ ,)* }) => { - pub struct $lang { - $(pub $field: std::sync::Arc<$($type)::*>),* - } - - $(impl<'a, N: $crate::support::preserves::value::NestedValue> From<&'a $lang> for &'a $($type)::* { - fn from(v: &'a $lang) -> Self { - &v.$field - } - })* - - impl $crate::support::NestedValueCodec - for $lang {} - - mod $fname { - use super::*; - lazy_static::lazy_static! { - pub static ref GLOBAL_LANG: std::sync::Arc<$lang<$default_value>> = - std::sync::Arc::new($lang { - $($field: std::sync::Arc::new($($type)::*::default())),* - }); - } - } - - impl $lang<$default_value> { - pub fn arc() -> &'static std::sync::Arc<$lang<$default_value>> { - &*$fname::GLOBAL_LANG - } - } - - pub fn $fname() -> &'static $lang<$default_value> { - &*$fname::GLOBAL_LANG - } - }; -} diff --git a/implementations/rust/preserves-schema/src/support/interpret.rs b/implementations/rust/preserves-schema/src/support/interpret.rs deleted file mode 100644 index e8f4c93..0000000 --- a/implementations/rust/preserves-schema/src/support/interpret.rs +++ /dev/null @@ -1,297 +0,0 @@ -//! Interpreter for instances of Preserves Schema Metaschema, for schema-directed dynamic -//! parsing and unparsing of terms. - -use crate::gen::schema::*; - -use preserves::value::merge::merge2; -use preserves::value::Map; -use preserves::value::NestedValue; -use preserves::value::Value; - -/// Represents an environment mapping schema module names to [Schema] instances. -pub type Env = Map, Schema>; - -/// Context for a given interpretation of a [Schema]. -#[derive(Debug)] -pub struct Context<'a, V: NestedValue> { - pub env: &'a Env, - module: Vec, -} - -#[derive(Debug)] -enum DynField { - Simple(V), - Compound(Map), -} - -impl<'a, V: NestedValue> Context<'a, V> { - /// Construct a new [Context] with the given [Env]. - pub fn new(env: &'a Env) -> Self { - Context { - env, - module: Vec::new(), - } - } - - /// Parse `v` using the rule named `name` from the module at path `module` in `self.env`. - /// Yields `Some(...)` if the parse succeeds, and `None` otherwise. - pub fn dynamic_parse(&mut self, module: &Vec, name: &str, v: &V) -> Option { - let old_module = - (module.len() > 0).then(|| std::mem::replace(&mut self.module, module.clone())); - let schema = self.env.get(&self.module); - let definition = schema.and_then(|s| s.definitions.0.get(name)); - let result = definition.and_then(|d| d.dynamic_parse(self, v)); - if let Some(m) = old_module { - self.module = m; - } - result - } - - #[doc(hidden)] - pub fn dynamic_unparse(&mut self, _module: &Vec, _name: &str, _w: &V) -> Option { - panic!("Not yet implemented"); - } -} - -impl Definition { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option { - match self { - Definition::Or { - pattern_0, - pattern_1, - pattern_n, - } => pattern_0 - .dynamic_parse(ctxt, v) - .or_else(|| pattern_1.dynamic_parse(ctxt, v)) - .or_else(|| pattern_n.iter().find_map(|p| p.dynamic_parse(ctxt, v))), - Definition::And { - pattern_0, - pattern_1, - pattern_n, - } => pattern_0 - .dynamic_parse(ctxt, v) - .and_then(|w0| { - pattern_1.dynamic_parse(ctxt, v).and_then(|w1| { - pattern_n.iter().fold(merge(w0, w1), |w, p| { - w.and_then(|w| p.dynamic_parse(ctxt, v).and_then(|wn| merge(w, wn))) - }) - }) - }) - .map(|w| DynField::Compound(w).finish()), - Definition::Pattern(p) => p.dynamic_parse(ctxt, v).map(|w| w.finish()), - } - } -} - -impl NamedAlternative { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option { - self.pattern.dynamic_parse(ctxt, v).map(|w| { - let mut r = Value::simple_record(&self.variant_label, 1); - match w { - DynField::Simple(field) => r.fields_vec_mut().push(field), - DynField::Compound(fields) => { - if fields.len() > 0 { - r.fields_vec_mut().push(V::new(fields)) - } - } - } - r.finish().wrap() - }) - } -} - -impl NamedPattern { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option> { - match self { - NamedPattern::Named(b) => { - let binding = &**b; - binding - .pattern - .dynamic_parse(ctxt, v) - .map(|w| w.to_map(Some(&binding.name))) - } - NamedPattern::Anonymous(b) => b.dynamic_parse(ctxt, v).map(|w| w.to_map(None)), - } - } -} - -impl NamedSimplePattern { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option> { - match self { - NamedSimplePattern::Named(b) => { - let binding = &**b; - binding - .pattern - .dynamic_parse(ctxt, v) - .map(|w| DynField::Compound(w.to_map(Some(&binding.name)))) - } - NamedSimplePattern::Anonymous(b) => b.dynamic_parse(ctxt, v), - } - } -} - -impl SimplePattern { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option> { - match self { - SimplePattern::Any => Some(DynField::Simple(v.clone())), - SimplePattern::Atom { atom_kind } => match &**atom_kind { - AtomKind::Boolean => v.value().is_boolean().then(|| DynField::Simple(v.clone())), - AtomKind::Double => v.value().is_double().then(|| DynField::Simple(v.clone())), - AtomKind::SignedInteger => v - .value() - .is_signedinteger() - .then(|| DynField::Simple(v.clone())), - AtomKind::String => v.value().is_string().then(|| DynField::Simple(v.clone())), - AtomKind::ByteString => v - .value() - .is_bytestring() - .then(|| DynField::Simple(v.clone())), - AtomKind::Symbol => v.value().is_symbol().then(|| DynField::Simple(v.clone())), - }, - SimplePattern::Embedded { .. } => { - v.value().is_embedded().then(|| DynField::Simple(v.clone())) - } - SimplePattern::Lit { value } => (v == value).then(|| DynField::Compound(Map::new())), - SimplePattern::Seqof { pattern } => v - .value() - .as_sequence() - .and_then(|vs| { - vs.iter() - .map(|v| (**pattern).dynamic_parse(ctxt, v).map(|w| w.finish())) - .collect::>>() - }) - .map(|ws| DynField::Simple(V::new(ws))), - SimplePattern::Setof { pattern } => v - .value() - .as_set() - .and_then(|vs| { - vs.iter() - .map(|v| (**pattern).dynamic_parse(ctxt, v).map(|w| w.finish())) - .collect::>>() - }) - .map(|ws| DynField::Simple(V::new(ws))), - SimplePattern::Dictof { key, value } => v - .value() - .as_dictionary() - .and_then(|d| { - d.iter() - .map(|(k, v)| { - (**key).dynamic_parse(ctxt, k).and_then(|kw| { - (**value) - .dynamic_parse(ctxt, v) - .map(|vw| (kw.finish(), vw.finish())) - }) - }) - .collect::>>() - }) - .map(|d| DynField::Simple(V::new(d))), - SimplePattern::Ref(r) => ctxt - .dynamic_parse(&r.module.0, &r.name, v) - .map(DynField::Simple), - } - } -} - -impl CompoundPattern { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option> { - match self { - CompoundPattern::Rec { label, fields } => v.value().as_record(None).and_then(|r| { - (**label).dynamic_parse(ctxt, r.label()).and_then(|lw| { - (**fields) - .dynamic_parse(ctxt, &V::new(r.fields().to_vec())) - .and_then(|fsw| merge(lw, fsw)) - }) - }), - CompoundPattern::Tuple { patterns } => v.value().as_sequence().and_then(|vs| { - if vs.len() == patterns.len() { - patterns - .iter() - .zip(vs) - .fold(Some(Map::new()), |acc, (p, v)| { - acc.and_then(|acc| p.dynamic_parse(ctxt, v).and_then(|w| merge(acc, w))) - }) - } else { - None - } - }), - CompoundPattern::TuplePrefix { fixed, variable } => { - v.value().as_sequence().and_then(|vs| { - if vs.len() >= fixed.len() { - fixed - .iter() - .zip(vs) - .fold(Some(Map::new()), |acc, (p, v)| { - acc.and_then(|acc| { - p.dynamic_parse(ctxt, v).and_then(|w| merge(acc, w)) - }) - }) - .and_then(|fixed_ws| { - let remainder = V::new(vs[fixed.len()..].to_vec()); - (**variable).dynamic_parse(ctxt, &remainder).and_then( - |variable_ws| merge(fixed_ws, variable_ws.unwrap_compound()), - ) - }) - } else { - None - } - }) - } - CompoundPattern::Dict { entries } => v.value().as_dictionary().and_then(|d| { - (**entries).0.iter().fold(Some(Map::new()), |acc, (k, p)| { - acc.and_then(|acc| { - d.get(k).and_then(|v| { - p.dynamic_parse(ctxt, v) - .and_then(|w| merge(acc, w.unwrap_compound())) - }) - }) - }) - }), - } - } -} - -impl Pattern { - fn dynamic_parse(&self, ctxt: &mut Context, v: &V) -> Option> { - match self { - Pattern::SimplePattern(b) => (**b).dynamic_parse(ctxt, v), - Pattern::CompoundPattern(b) => (**b).dynamic_parse(ctxt, v).map(DynField::Compound), - } - } -} - -impl DynField { - fn finish(self) -> V { - match self { - DynField::Simple(v) => v, - DynField::Compound(v) => V::new(v), - } - } - - fn to_map(self, key: Option<&str>) -> Map { - match self { - DynField::Simple(v) => { - let mut d = Map::new(); - if let Some(k) = key { - d.insert(V::symbol(k), v); - } - d - } - DynField::Compound(d) => d, - } - } - - fn unwrap_compound(self) -> Map { - match self { - DynField::Simple(_) => panic!("Cannot unwrap DynField::Simple to compound fields"), - DynField::Compound(d) => d, - } - } -} - -fn merge(a: Map, b: Map) -> Option> { - merge2(V::new(a), V::new(b)).map(|d| { - d.value_owned() - .into_dictionary() - .expect("merge to yield Dictionary") - }) -} diff --git a/implementations/rust/preserves-schema/src/support/mod.rs b/implementations/rust/preserves-schema/src/support/mod.rs deleted file mode 100644 index fa457bc..0000000 --- a/implementations/rust/preserves-schema/src/support/mod.rs +++ /dev/null @@ -1,168 +0,0 @@ -//! The runtime support library for compiled Schemas. - -#[doc(hidden)] -/// Reexport lazy_static for generated code to use. -pub use lazy_static::lazy_static; - -pub use preserves; -pub use preserves::value::boundary as B; -pub use preserves::value::Reader; - -pub mod interpret; - -use preserves::value::ArcValue; -use preserves::value::Domain; -use preserves::value::IOValue; -use preserves::value::NestedValue; -use preserves::value::NoEmbeddedDomainCodec; -use preserves::value::Value; - -use std::convert::From; -use std::convert::Into; -use std::convert::TryFrom; -use std::io; -use std::sync::Arc; - -use thiserror::Error; - -/// Every [language][crate::define_language] implements [NestedValueCodec] as a marker trait. -pub trait NestedValueCodec {} // marker trait -impl NestedValueCodec for () {} - -/// Implementors of [Parse] can produce instances of themselves from a [Value], given a -/// supporting [language][crate::define_language]. All Schema-compiler-produced types implement -/// [Parse]. -pub trait Parse: Sized { - /// Decode the given `value` (using auxiliary structure from the `language` instance) to - /// produce an instance of [Self]. - fn parse(language: L, value: &Value) -> Result; -} - -impl<'a, T: NestedValueCodec, Value: NestedValue> Parse<&'a T, Value> for Value { - fn parse(_language: &'a T, value: &Value) -> Result { - Ok(value.clone()) - } -} - -/// Implementors of [Unparse] can convert themselves into a [Value], given a supporting -/// [language][crate::define_language]. All Schema-compiler-produced types implement [Unparse]. -pub trait Unparse { - /// Encode `self` into a [Value] (using auxiliary structure from the `language` instance). - fn unparse(&self, language: L) -> Value; -} - -impl<'a, T: NestedValueCodec, Value: NestedValue> Unparse<&'a T, Value> for Value { - fn unparse(&self, _language: &'a T) -> Value { - self.clone() - } -} - -/// Every [language][crate::define_language] implements [Codec], which supplies convenient -/// shorthand for invoking [Parse::parse] and [Unparse::unparse]. -pub trait Codec { - /// Delegates to [`T::parse`][Parse::parse], using `self` as language and the given `value` - /// as input. - fn parse<'a, T: Parse<&'a Self, N>>(&'a self, value: &N) -> Result; - /// Delegates to [`value.unparse`][Unparse::unparse], using `self` as language. - fn unparse<'a, T: Unparse<&'a Self, N>>(&'a self, value: &T) -> N; -} - -impl Codec for L { - fn parse<'a, T: Parse<&'a L, N>>(&'a self, value: &N) -> Result { - T::parse(self, value) - } - - fn unparse<'a, T: Unparse<&'a L, N>>(&'a self, value: &T) -> N { - value.unparse(self) - } -} - -/// Implementors of [Deserialize] can produce instances of themselves from a [Value]. All -/// Schema-compiler-produced types implement [Deserialize]. -/// -/// The difference between [Deserialize] and [Parse] is that implementors of [Deserialize] know -/// which [language][crate::define_language] to use. -pub trait Deserialize -where - Self: Sized, -{ - fn deserialize<'de, R: Reader<'de, N>>(r: &mut R) -> Result; -} - -/// Extracts a simple literal term from a byte array using -/// [PackedReader][preserves::value::packed::PackedReader]. No embedded values are permitted. -pub fn decode_lit(bs: &[u8]) -> io::Result { - preserves::value::packed::from_bytes(bs, NoEmbeddedDomainCodec) -} - -/// When `D` can parse itself from an [IOValue], this function parses all embedded [IOValue]s -/// into `D`s. -pub fn decode_embedded(v: &IOValue) -> Result>, ParseError> -where - for<'a> D: TryFrom<&'a IOValue, Error = ParseError>, -{ - v.copy_via(&mut |d| Ok(Value::Embedded(Arc::new(D::try_from(d)?)))) -} - -/// When `D` can unparse itself into an [IOValue], this function converts all embedded `D`s -/// into [IOValue]s. -pub fn encode_embedded(v: &ArcValue>) -> IOValue -where - for<'a> IOValue: From<&'a D>, -{ - v.copy_via::<_, _, std::convert::Infallible>(&mut |d| Ok(Value::Embedded(IOValue::from(d)))) - .unwrap() -} - -/// Error value yielded when parsing of an [IOValue] into a Schema-compiler-produced type. -#[derive(Error, Debug)] -pub enum ParseError { - /// Signalled when the input does not match the Preserves Schema associated with the type. - #[error("Input not conformant with Schema: {0}")] - ConformanceError(&'static str), - /// Signalled when the underlying Preserves library signals an error. - #[error(transparent)] - Preserves(preserves::error::Error), -} - -impl From for ParseError { - fn from(v: preserves::error::Error) -> Self { - match v { - preserves::error::Error::Expected(_, _) => { - ParseError::ConformanceError("preserves::error::Error::Expected") - } - _ => ParseError::Preserves(v), - } - } -} - -impl From for ParseError { - fn from(v: io::Error) -> Self { - 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, v), - ParseError::Preserves(e) => e.into(), - } - } -} - -impl ParseError { - /// Constructs a [ParseError::ConformanceError]. - pub fn conformance_error(context: &'static str) -> Self { - ParseError::ConformanceError(context) - } - - /// True iff `self` is a [ParseError::ConformanceError]. - 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 deleted file mode 100644 index 7bf1abc..0000000 --- a/implementations/rust/preserves-schema/src/syntax/block.rs +++ /dev/null @@ -1,538 +0,0 @@ -//! A library for emitting pretty-formatted structured source code. -//! -//! The main entry points are [Formatter::to_string] and [Formatter::write], plus the utilities -//! in the [macros] submodule. - -use std::fmt::Write; -use std::str; - -/// Default width for pretty-formatting, in columns. -pub const DEFAULT_WIDTH: usize = 80; - -/// All pretty-formattable items must implement this trait. -pub trait Emittable: std::fmt::Debug { - /// Serializes `self`, as pretty-printed code, on `f`. - fn write_on(&self, f: &mut Formatter); -} - -/// Tailoring of behaviour for [Vertical] groupings. -#[derive(Clone, PartialEq, Eq)] -pub enum VerticalMode { - Variable, - Normal, - ExtraNewline, -} - -/// Vertical formatting for [Emittable]s. -pub trait Vertical { - fn set_vertical_mode(&mut self, mode: VerticalMode); - fn write_vertically_on(&self, f: &mut Formatter); -} - -/// Polymorphic [Emittable], used consistently in the API. -pub type Item = std::rc::Rc; - -/// A possibly-vertical sequence of items with item-separating and -terminating text. -#[derive(Clone)] -pub struct Sequence { - pub items: Vec, - pub vertical_mode: VerticalMode, - pub separator: &'static str, - pub terminator: &'static str, -} - -/// A sequence of items, indented when formatted vertically, surrounded by opening and closing -/// text. -#[derive(Clone)] -pub struct Grouping { - pub sequence: Sequence, - pub open: &'static str, - pub close: &'static str, -} - -/// State needed for pretty-formatting of [Emittable]s. -pub struct Formatter { - /// Number of available columns. Used to decide between horizontal and vertical layouts. - pub width: usize, - indent_delta: String, - current_indent: String, - /// Mutable output buffer. Accumulates emitted text during writing. - pub buffer: String, -} - -impl Formatter { - /// Construct a Formatter using [DEFAULT_WIDTH] and a four-space indent. - pub fn new() -> Self { - Formatter { - width: DEFAULT_WIDTH, - indent_delta: " ".to_owned(), - current_indent: "\n".to_owned(), - buffer: String::new(), - } - } - - /// Construct a Formatter just like `self` but with an empty `buffer`. - pub fn copy_empty(&self) -> Formatter { - Formatter { - width: self.width, - indent_delta: self.indent_delta.clone(), - current_indent: self.current_indent.clone(), - buffer: String::new(), - } - } - - /// Yields the indent size. - pub fn indent_size(self) -> usize { - self.indent_delta.len() - } - - /// Updates the indent size. - pub fn set_indent_size(&mut self, n: usize) { - self.indent_delta = str::repeat(" ", n) - } - - /// Accumulates a text serialization of `e` in `buffer`. - pub fn write(&mut self, e: E) { - e.write_on(self) - } - - /// Emits a newline followed by indentation into `buffer`. - pub fn newline(&mut self) { - self.buffer.push_str(&self.current_indent) - } - - /// Creates a default Formatter, uses it to [write][Formatter::write] `e`, and yields the - /// contents of its `buffer`. - pub fn to_string(e: E) -> String { - let mut f = Formatter::new(); - f.write(e); - f.buffer - } - - /// Calls `f` in a context where the indentation has been increased by - /// [Formatter::indent_size] spaces. Restores the indentation level after `f` returns. - /// Yields the result of the call to `f`. - pub fn with_indent R>(&mut self, f: F) -> R { - let old_indent = self.current_indent.clone(); - self.current_indent += &self.indent_delta; - let r = f(self); - self.current_indent = old_indent; - r - } -} - -impl Default for Formatter { - fn default() -> Self { - Self::new() - } -} - -impl Default for VerticalMode { - fn default() -> Self { - Self::Variable - } -} - -//--------------------------------------------------------------------------- - -impl Emittable for &str { - fn write_on(&self, f: &mut Formatter) { - f.buffer.push_str(self) - } -} - -impl Emittable for String { - fn write_on(&self, f: &mut Formatter) { - f.write(self.as_str()) - } -} - -impl<'a, E: Emittable> Emittable for &'a Vec -where - &'a E: Emittable, -{ - fn write_on(&self, f: &mut Formatter) { - for e in self.iter() { - f.write(e) - } - } -} - -impl Emittable for Sequence { - fn write_on(&self, f: &mut Formatter) { - if self.vertical_mode != VerticalMode::Variable { - self.write_vertically_on(f) - } else { - let mut need_sep = false; - for e in self.items.iter() { - if need_sep { - self.separator.write_on(f) - } else { - need_sep = true - } - e.write_on(f) - } - if !self.items.is_empty() { - self.terminator.write_on(f) - } - } - } -} - -impl Vertical for Sequence { - fn set_vertical_mode(&mut self, vertical_mode: VerticalMode) { - self.vertical_mode = vertical_mode; - } - - fn write_vertically_on(&self, f: &mut Formatter) { - let mut i = self.items.len(); - let mut first = true; - for e in self.items.iter() { - if !first { - if self.vertical_mode == VerticalMode::ExtraNewline { - f.write("\n"); - } - f.newline(); - } - first = false; - e.write_on(f); - let delim = if i == 1 { - self.terminator - } else { - self.separator - }; - delim - .trim_end_matches(|c: char| c.is_whitespace() && c != '\n') - .write_on(f); - i = i - 1; - } - } -} - -impl Emittable for Grouping { - fn write_on(&self, f: &mut Formatter) { - if self.sequence.vertical_mode != VerticalMode::Variable { - self.write_vertically_on(f) - } else { - let mut g = f.copy_empty(); - self.open.write_on(&mut g); - g.write(&self.sequence); - self.close.write_on(&mut g); - let s = g.buffer; - if s.len() <= f.width { - f.write(&s) - } else { - self.write_vertically_on(f) - } - } - } -} - -impl Vertical for Grouping { - fn set_vertical_mode(&mut self, vertical_mode: VerticalMode) { - self.sequence.set_vertical_mode(vertical_mode); - } - - fn write_vertically_on(&self, f: &mut Formatter) { - self.open.write_on(f); - if !self.sequence.items.is_empty() { - f.with_indent(|f| { - f.newline(); - self.sequence.write_vertically_on(f) - }); - f.newline() - } - self.close.write_on(f); - } -} - -impl<'a, E: Emittable> Emittable for &'a E { - fn write_on(&self, f: &mut Formatter) { - (*self).write_on(f) - } -} - -impl Emittable for Item { - fn write_on(&self, f: &mut Formatter) { - (**self).write_on(f) - } -} - -impl std::fmt::Debug for Sequence { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - f.write_str(&Formatter::to_string(self)) - } -} - -impl std::fmt::Debug for Grouping { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - f.write_str(&Formatter::to_string(self)) - } -} - -//--------------------------------------------------------------------------- - -/// Escapes `s` by substituting `\\` for `\`, `\"` for `"`, and `\u{...}` for characters -/// outside the range 32..126, inclusive. -/// -/// This process is intended to generate literals compatible with `rustc`; see [the language -/// reference on "Character and string -/// literals"](https://doc.rust-lang.org/reference/tokens.html#character-and-string-literals). -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 -} - -/// Escapes `bs` into a Rust byte string literal, treating each byte as its ASCII equivalent -/// except producing `\\` for 0x5c, `\"` for 0x22, and `\x..` for bytes outside the range -/// 0x20..0x7e, inclusive. -/// -/// This process is intended to generate literals compatible with `rustc`; see [the language -/// reference on "Byte string -/// literals"](https://doc.rust-lang.org/reference/tokens.html#byte-string-literals). -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 -} - -//--------------------------------------------------------------------------- - -/// Utilities for constructing many useful kinds of [Sequence] and [Grouping]. -pub mod constructors { - use super::Emittable; - use super::Grouping; - use super::Item; - use super::Sequence; - use super::Vertical; - use super::VerticalMode; - - /// Produces a polymorphic, reference-counted [Item] from some generic [Emittable]. - pub fn item(i: E) -> Item { - std::rc::Rc::new(i) - } - - /// *a*`::`*b*`::`*...*`::`*z* - pub fn name(pieces: Vec) -> Sequence { - Sequence { - items: pieces, - vertical_mode: VerticalMode::default(), - separator: "::", - terminator: "", - } - } - - /// *ab...z* (directly adjacent, no separators or terminators) - pub fn seq(items: Vec) -> Sequence { - Sequence { - items: items, - vertical_mode: VerticalMode::default(), - separator: "", - terminator: "", - } - } - - /// *a*`, `*b*`, `*...*`, `*z* - pub fn commas(items: Vec) -> Sequence { - Sequence { - items: items, - vertical_mode: VerticalMode::default(), - separator: ", ", - terminator: "", - } - } - - /// `(`*a*`, `*b*`, `*...*`, `*z*`)` - pub fn parens(items: Vec) -> Grouping { - Grouping { - sequence: commas(items), - open: "(", - close: ")", - } - } - - /// `[`*a*`, `*b*`, `*...*`, `*z*`]` - pub fn brackets(items: Vec) -> Grouping { - Grouping { - sequence: commas(items), - open: "[", - close: "]", - } - } - - /// `<`*a*`, `*b*`, `*...*`, `*z*`>` - pub fn anglebrackets(items: Vec) -> Grouping { - Grouping { - sequence: commas(items), - open: "<", - close: ">", - } - } - - /// `{`*a*`, `*b*`, `*...*`, `*z*`}` - pub fn braces(items: Vec) -> Grouping { - Grouping { - sequence: commas(items), - open: "{", - close: "}", - } - } - - /// `{`*a*` `*b*` `*...*` `*z*`}` - pub fn block(items: Vec) -> Grouping { - Grouping { - sequence: Sequence { - items: items, - vertical_mode: VerticalMode::default(), - separator: " ", - terminator: "", - }, - open: "{", - close: "}", - } - } - - /// As [block], but always vertical - pub fn codeblock(items: Vec) -> Grouping { - vertical(false, block(items)) - } - - /// `{`*a*`; `*b*`; `*...*`; `*z*`}` - pub fn semiblock(items: Vec) -> Grouping { - Grouping { - sequence: Sequence { - items: items, - vertical_mode: VerticalMode::default(), - separator: "; ", - terminator: "", - }, - open: "{", - close: "}", - } - } - - /// Overrides `v` to be always vertical. - /// - /// If `spaced` is true, inserts an extra newline between items. - pub fn vertical(spaced: bool, mut v: V) -> V { - v.set_vertical_mode(if spaced { - VerticalMode::ExtraNewline - } else { - VerticalMode::Normal - }); - v - } - - /// Adds a layer of indentation to the given [Sequence]. - pub fn indented(sequence: Sequence) -> Grouping { - Grouping { - sequence, - open: "", - close: "", - } - } -} - -/// Ergonomic syntax for using the constructors in submodule [constructors]; see the -/// documentation for the macros, which appears on the [page for the crate -/// itself][crate#macros]. -pub mod macros { - /// `name!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ *a*`::`*b*`::`*...*`::`*z* - /// - /// See [super::constructors::name]. - #[macro_export] - macro_rules! name { - ($($item:expr),*) => {$crate::syntax::block::constructors::name(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `seq!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ *ab...z* - /// - /// See [super::constructors::seq]. - #[macro_export] - macro_rules! seq { - ($($item:expr),*) => {$crate::syntax::block::constructors::seq(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `commas!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ *a*`, `*b*`, `*...*`, `*z* - /// - /// See [super::constructors::commas]. - #[macro_export] - macro_rules! commas { - ($($item:expr),*) => {$crate::syntax::block::constructors::commas(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `parens!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ `(`*a*`, `*b*`, `*...*`, `*z*`)` - /// - /// See [super::constructors::parens]. - #[macro_export] - macro_rules! parens { - ($($item:expr),*) => {$crate::syntax::block::constructors::parens(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `brackets!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ `[`*a*`, `*b*`, `*...*`, `*z*`]` - /// - /// See [super::constructors::brackets]. - #[macro_export] - macro_rules! brackets { - ($($item:expr),*) => {$crate::syntax::block::constructors::brackets(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `anglebrackets!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ `<`*a*`, `*b*`, `*...*`, `*z*`>` - /// - /// See [super::constructors::anglebrackets]. - #[macro_export] - macro_rules! anglebrackets { - ($($item:expr),*) => {$crate::syntax::block::constructors::anglebrackets(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `braces!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ `{`*a*`, `*b*`, `*...*`, `*z*`}` - /// - /// See [super::constructors::braces]. - #[macro_export] - macro_rules! braces { - ($($item:expr),*) => {$crate::syntax::block::constructors::braces(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `block!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ `{`*a*` `*b*` `*...*` `*z*`}` - /// - /// See [super::constructors::block]. - #[macro_export] - macro_rules! block { - ($($item:expr),*) => {$crate::syntax::block::constructors::block(vec![$(std::rc::Rc::new($item)),*])} - } - - /// As [`block`]`!`, but always vertical. See - /// [constructors::codeblock][super::constructors::codeblock]. - #[macro_export] - macro_rules! codeblock { - ($($item:expr),*) => {$crate::syntax::block::constructors::codeblock(vec![$(std::rc::Rc::new($item)),*])} - } - - /// `semiblock!(`*a*`, `*b*`, `*...*`, `*z*`)` ⟶ `{`*a*`; `*b*`; `*...*`; `*z*`}` - /// - /// See [super::constructors::semiblock]. - #[macro_export] - macro_rules! semiblock { - ($($item:expr),*) => {$crate::syntax::block::constructors::semiblock(vec![$(std::rc::Rc::new($item)),*])} - } -} diff --git a/implementations/rust/preserves-schema/src/syntax/mod.rs b/implementations/rust/preserves-schema/src/syntax/mod.rs deleted file mode 100644 index 5aee0e8..0000000 --- a/implementations/rust/preserves-schema/src/syntax/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! A library for emitting pretty-formatted structured source code. - -pub mod block; diff --git a/implementations/rust/preserves-tools/Cargo.toml b/implementations/rust/preserves-tools/Cargo.toml deleted file mode 100644 index d268e96..0000000 --- a/implementations/rust/preserves-tools/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "preserves-tools" -version = "4.993.0" -authors = ["Tony Garnock-Jones "] -edition = "2018" -description = "Command-line utilities for working with Preserves documents." -homepage = "https://preserves.dev/" -repository = "https://gitlab.com/preserves/preserves" -license = "Apache-2.0" - -[dependencies] -preserves = { path = "../preserves", version = "4.993.0"} -preserves-path = { path = "../preserves-path", version = "5.993.0"} -preserves-schema = { path = "../preserves-schema", version = "5.993.0"} - -bytes = "1.0" -clap = { version = "3", features = ["derive"] } -clap_complete = "3" - -[package.metadata.workspaces] -independent = true diff --git a/implementations/rust/preserves-tools/src/bin/preserves-tool.rs b/implementations/rust/preserves-tools/src/bin/preserves-tool.rs deleted file mode 100644 index 7909c11..0000000 --- a/implementations/rust/preserves-tools/src/bin/preserves-tool.rs +++ /dev/null @@ -1,548 +0,0 @@ -use bytes::Buf; -use bytes::BufMut; -use bytes::BytesMut; - -use clap::{value_parser, ArgEnum, Command, IntoApp, Parser}; -use clap_complete::{generate, Generator, Shell}; - -use preserves::value::IOBinarySource; -use preserves::value::IOValue; -use preserves::value::IOValueDomainCodec; -use preserves::value::NestedValue; -use preserves::value::PackedReader; -use preserves::value::PackedWriter; -use preserves::value::Reader; -use preserves::value::Set; -use preserves::value::TextReader; -use preserves::value::TextWriter; -use preserves::value::Value; -use preserves::value::ViaCodec; -use preserves::value::Writer; - -use preserves::value::text::writer::CommaStyle; - -use std::io; -use std::io::Read; -use std::iter::FromIterator; - -// #[derive(ArgEnum, Clone, Debug)] -// enum Encoding { -// None, -// Base64, -// Hex, -// } - -#[derive(ArgEnum, Clone, Debug)] -enum InputFormat { - AutoDetect, - Text, - Binary, -} - -#[derive(ArgEnum, Clone, Debug)] -enum OutputFormat { - Text, - Binary, - Unquoted, -} - -#[derive(ArgEnum, Clone, Debug)] -enum CommasFormat { - None, - Separating, - Terminating, -} - -#[derive(ArgEnum, Clone, Copy, Debug)] -enum Boolish { - #[clap(alias = "no", alias = "n", alias = "off", alias = "0", alias = "false")] - Disabled, - #[clap(alias = "yes", alias = "y", alias = "on", alias = "1", alias = "true")] - Enabled, -} - -impl From for bool { - fn from(b: Boolish) -> Self { - matches!(b, Boolish::Enabled) - } -} - -impl From for CommaStyle { - fn from(commas: CommasFormat) -> Self { - match commas { - CommasFormat::None => CommaStyle::None, - CommasFormat::Separating => CommaStyle::Separating, - CommasFormat::Terminating => CommaStyle::Terminating, - } - } -} - -#[derive(ArgEnum, Clone, Debug)] -enum SelectOutput { - Sequence, - Set, -} - -#[derive(Clone, Debug, Parser)] -struct Convert { - // #[clap(long, arg_enum, default_value = "none")] - // input_encoding: Encoding, - - // #[clap(long, arg_enum, default_value = "none")] - // output_encoding: Encoding, - #[clap(long, short, arg_enum, default_value = "auto-detect")] - input_format: InputFormat, - - #[clap(long, short, arg_enum, default_value = "text")] - output_format: OutputFormat, - - #[clap(long)] - escape_spaces: bool, - - #[clap(long, short, arg_enum, default_value = "none")] - commas: CommasFormat, - - #[clap(long)] - limit: Option, - - #[clap(long, arg_enum, value_name = "on/off", default_value = "on")] - indent: Boolish, - - #[clap(long = "select", default_value = "*")] - select_expr: String, - - #[clap(long, arg_enum, default_value = "sequence")] - select_output: SelectOutput, - - #[clap(long)] - collect: bool, - - #[clap(long, arg_enum, value_name = "on/off", default_value = "on")] - read_annotations: Boolish, - - #[clap(long, arg_enum, value_name = "on/off", default_value = "on")] - write_annotations: Boolish, - - #[clap(long, value_name = "filename")] - bundle: Vec, - // #[clap(long)] - // schema: Option, -} - -#[derive(ArgEnum, Clone, Debug)] -enum StringInputTerminator { - EOF, - Newline, - Nul, -} - -#[derive(Clone, Debug, Parser)] -struct StringQuotation { - #[clap(long, arg_enum, default_value = "eof")] - input_terminator: StringInputTerminator, - - #[clap(long)] - include_terminator: bool, - - #[clap(long)] - escape_spaces: bool, -} - -#[derive(Clone, Debug, Parser)] -enum QuotationOutput { - String(StringQuotation), - ByteString, - Symbol(StringQuotation), -} - -#[derive(Clone, Debug, Parser)] -struct Quote { - #[clap(long, short, arg_enum, default_value = "text")] - output_format: OutputFormat, - - #[clap(subcommand)] - output: QuotationOutput, -} - -#[derive(Clone, Debug, Parser)] -enum Subcommand { - Completions { - #[clap(value_parser=value_parser!(Shell))] - shell: Shell, - }, - Convert(Convert), - Quote(Quote), -} - -#[derive(Clone, Debug, Parser)] -#[clap(name = "preserves-tool")] -#[clap(version)] -#[clap(args_conflicts_with_subcommands = true)] -/// Swiss-army knife tool for working with Preserves data. -/// See https://preserves.dev/. -/// If no subcommand is specified, the default subcommand will be `convert`. -struct CommandLine { - #[clap(subcommand)] - command: Option, - - #[clap(flatten, next_help_heading="OPTIONS FOR DEFAULT SUBCOMMAND convert")] - convert: Convert, -} - -fn print_completions(gen: G, cmd: &mut Command) { - generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout()); -} - -fn main() -> io::Result<()> { - let args = CommandLine::parse(); - Ok(match args.command { - Some(subcommand) => match subcommand { - Subcommand::Completions { shell } => { - let mut cmd = CommandLine::into_app(); - print_completions(shell, &mut cmd); - } - Subcommand::Convert(c) => convert(c)?, - Subcommand::Quote(q) => quote(q)?, - } - None => convert(args.convert)?, - }) -} - -struct RollingBuffer { - r: R, - discarded: usize, - pos: usize, - buf: BytesMut, -} - -impl RollingBuffer { - fn new(r: R) -> Self { - RollingBuffer { - r, - discarded: 0, - pos: 0, - buf: BytesMut::new(), - } - } - - fn read_more(&mut self) -> io::Result { - let mut buf = [0; 8192]; - let n = self.r.read(&mut buf)?; - self.buf.put(&buf[..n]); - Ok(n) - } - - fn peek_buf(&mut self) -> io::Result<&[u8]> { - if self.rhs() == self.pos { - let _ = self.read_more()?; - } - return Ok(&self.buf[self.pos - self.discarded..]); - } - - fn rhs(&self) -> usize { - self.buf.remaining() + self.discarded - } - - fn discard(&mut self, count: usize) { - self.buf.advance(count); - self.discarded += count; - } - - fn discard_to_pos(&mut self) { - self.discard(self.pos - self.discarded) - } - - fn read_upto(&mut self, delimiter: u8, inclusive: bool) -> io::Result>> { - let mut result = Vec::new(); - let mut buf = [0; 1]; - while self.read(&mut buf)? == 1 { - if buf[0] == delimiter { - if inclusive { - result.push(delimiter); - } - return Ok(Some(result)); - } - result.push(buf[0]); - } - Ok(if result.is_empty() { - None - } else { - Some(result) - }) - } -} - -impl io::Seek for RollingBuffer { - fn seek(&mut self, offset: io::SeekFrom) -> io::Result { - let new_position = match offset { - io::SeekFrom::Current(delta) => { - if delta >= 0 { - self.pos + delta as usize - } else { - self.pos - (-delta) as usize - } - } - io::SeekFrom::End(_) => Err(io::Error::new( - io::ErrorKind::Unsupported, - "Cannot seek wrt end on open-ended stream", - ))?, - io::SeekFrom::Start(new_position) => new_position as usize, - }; - if new_position > self.rhs() { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Attempt to seek beyond end of buffer", - ))?; - } - if new_position < self.discarded { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Attempt to seek before start of buffer", - ))?; - } - self.pos = new_position; - Ok(new_position as u64) - } - - fn stream_position(&mut self) -> io::Result { - Ok(self.pos as u64) - } -} - -impl io::Read for RollingBuffer { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let i = self.pos - self.discarded; - loop { - let n = std::cmp::min(self.buf.remaining() - i, buf.len()); - if n == 0 { - if self.read_more()? == 0 { - return Ok(0); - } - continue; - } - let _ = &buf[..n].copy_from_slice(&self.buf[i..i + n]); - self.pos += n; - return Ok(n); - } - } -} - -// TODO: extract this and RollingBuffer to some preserves utils module -pub struct ValueStream { - input_format: InputFormat, - read_annotations: bool, - source: IOBinarySource>, - count: usize, -} - -impl ValueStream { - fn new(input_format: InputFormat, read_annotations: bool, r: R) -> Self { - ValueStream { - input_format, - read_annotations, - source: IOBinarySource::new(RollingBuffer::new(r)), - count: 0, - } - } - - fn read(&mut self) -> io::Result> { - let is_text = { - let peek_buf = self.source.read.peek_buf()?; - if peek_buf.is_empty() { - return Ok(None); - } - peek_buf[0] < 128 - }; - - let maybe_value: Option = if is_text { - match self.input_format { - InputFormat::AutoDetect | InputFormat::Text => (), - InputFormat::Binary => { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "Expected binary input, saw text input", - )) - } - } - TextReader::new(&mut self.source, ViaCodec::new(IOValueDomainCodec)) - .next(self.read_annotations)? - } else { - match self.input_format { - InputFormat::AutoDetect | InputFormat::Binary => (), - InputFormat::Text => { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "Expected text input, saw binary input", - )) - } - } - PackedReader::new(&mut self.source, IOValueDomainCodec).next(self.read_annotations)? - }; - - match maybe_value { - None => return Ok(None), - Some(value) => { - self.source.read.discard_to_pos(); - self.count += 1; - Ok(Some(value)) - } - } - } -} - -impl std::iter::Iterator for ValueStream { - type Item = io::Result; - fn next(&mut self) -> Option { - self.read().transpose() - } -} - -fn print_unquoted(v: &IOValue) { - match v.value() { - Value::String(s) => println!("{}", &s), - Value::Symbol(s) => println!("{}", &s), - _ => (), - } -} - -fn convert(c: Convert) -> io::Result<()> { - let mut env = preserves_path::Env::new(); - for f in c.bundle.iter() { - env.load_bundle(f)?; - } - let select = preserves_path::Node::from_str(&env, &c.select_expr).map_err(|e| { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Invalid select expression: {}: {:?}", e, c.select_expr), - ) - })?; - let mut vs = ValueStream::new(c.input_format, c.read_annotations.into(), io::stdin()); - let write_ann: bool = c.write_annotations.into(); - let mut w: Box io::Result<()>> = match c.output_format { - OutputFormat::Text => { - let mut t = TextWriter::new(io::stdout()) - .set_escape_spaces(c.escape_spaces) - .set_comma_style(c.commas.into()); - if c.indent.into() { - t.indentation = 2; - } - Box::new(move |v| { - if write_ann { - t.write(&mut IOValueDomainCodec, v)?; - } else { - t.write(&mut IOValueDomainCodec, &v.strip_annotations::())?; - } - println!(); - Ok(()) - }) - } - OutputFormat::Binary => { - let mut p = PackedWriter::new(io::stdout()); - Box::new(move |v| { - if write_ann { - p.write(&mut IOValueDomainCodec, v)?; - } else { - p.write(&mut IOValueDomainCodec, &v.strip_annotations::())?; - } - Ok(()) - }) - } - OutputFormat::Unquoted => Box::new(|v| { - print_unquoted(v); - Ok(()) - }), - }; - while let Some(value) = vs.next() { - let value = value?; - let matches = select.exec(&mut env.to_context(), &value); - if c.collect { - match c.select_output { - SelectOutput::Sequence => w(&IOValue::new(matches))?, - SelectOutput::Set => w(&IOValue::new(Set::from_iter(matches)))?, - } - } else { - match c.select_output { - SelectOutput::Sequence => { - for v in matches { - w(&v)?; - } - } - SelectOutput::Set => { - for v in Set::from_iter(matches) { - w(&v)?; - } - } - } - } - if let Some(limit) = c.limit { - if vs.count >= limit { - break; - } - } - } - Ok(()) -} - -impl Quote { - fn escape_spaces(&self) -> bool { - match &self.output { - QuotationOutput::ByteString => false, - QuotationOutput::String(s) | QuotationOutput::Symbol(s) => s.escape_spaces, - } - } -} - -fn output_one(q: &Quote, v: &IOValue) -> io::Result<()> { - match q.output_format { - OutputFormat::Binary => PackedWriter::new(io::stdout()).write(&mut IOValueDomainCodec, v), - OutputFormat::Text => { - TextWriter::new(io::stdout()) - .set_escape_spaces(q.escape_spaces()) - .write(&mut IOValueDomainCodec, v)?; - println!(); - Ok(()) - } - OutputFormat::Unquoted => { - print_unquoted(v); - Ok(()) - } - } -} - -fn quote(q: Quote) -> io::Result<()> { - match &q.output { - QuotationOutput::ByteString => { - let mut buf = Vec::new(); - io::stdin().read_to_end(&mut buf)?; - output_one(&q, &IOValue::new(&buf[..])) - } - QuotationOutput::String(s) | QuotationOutput::Symbol(s) => match s.input_terminator { - StringInputTerminator::EOF => { - let mut buf = String::new(); - io::stdin().read_to_string(&mut buf)?; - quote_chunk(&q, buf) - } - StringInputTerminator::Newline => quote_terminated_strings(b'\n', &q, s), - StringInputTerminator::Nul => quote_terminated_strings(b'\0', &q, s), - }, - } -} - -fn quote_chunk(q: &Quote, buf: String) -> io::Result<()> { - match q.output { - QuotationOutput::Symbol(_) => output_one(q, &IOValue::symbol(&buf)), - _ => output_one(q, &IOValue::new(buf)), - } -} - -fn quote_terminated_strings(delimiter: u8, q: &Quote, s: &StringQuotation) -> io::Result<()> { - let mut r = RollingBuffer::new(io::stdin()); - while let Some(chunk) = r.read_upto(delimiter, s.include_terminator)? { - quote_chunk( - q, - String::from_utf8(chunk) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8"))?, - )? - } - Ok(()) -} diff --git a/implementations/rust/preserves/Cargo.toml b/implementations/rust/preserves/Cargo.toml deleted file mode 100644 index 52662a5..0000000 --- a/implementations/rust/preserves/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "preserves" -version = "4.993.0" -authors = ["Tony Garnock-Jones "] -edition = "2018" -description = "Implementation of the Preserves serialization format via serde." -homepage = "https://preserves.dev/" -repository = "https://gitlab.com/preserves/preserves" -license = "Apache-2.0" - -[badges] -gitlab = { repository = "preserves/preserves" } - -[dependencies] -base64 = "0.13" -dtoa = "0.4" -num = "0.4" -lazy_static = "1.4.0" -regex = "1.5" -serde = { version = "1.0", features = ["derive"] } -serde_bytes = "0.11" - -[dev-dependencies] -criterion = "0.3" - -[[bench]] -name = "codec" -harness = false - -[package.metadata.workspaces] -independent = true diff --git a/implementations/rust/preserves/Makefile b/implementations/rust/preserves/Makefile deleted file mode 100644 index 9c8a8f9..0000000 --- a/implementations/rust/preserves/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -TESTARGS=--lib --bins --examples --tests - -# cargo install cargo-watch -watch: - cargo watch -c -x 'test $(TESTARGS) -- --nocapture' - -test: - cargo test $(TESTARGS) -- --nocapture - -bench: benches/testdata.bin - cargo bench --benches - -.INTERMEDIATE: benches/testdata.bin -benches/testdata.bin: benches/testdata.bin.gz - gzip -dc $< > $@ - -clippy-watch: - cargo watch -c -x 'clippy $(TESTARGS)' - -inotifytest: - inotifytest sh -c 'reset; cargo build $(TESTARGS) && RUST_BACKTRACE=1 cargo test $(TESTARGS) -- --nocapture' - -debug-tests: - cargo test $(TESTARGS) --no-run - gdb --args $$(cargo test 3>&1 1>&2 2>&3 3>&- | grep Running | awk '{print $$2}') --test-threads=1 diff --git a/implementations/rust/preserves/README.md b/implementations/rust/preserves/README.md deleted file mode 100644 index e09a241..0000000 --- a/implementations/rust/preserves/README.md +++ /dev/null @@ -1,23 +0,0 @@ -```shell -cargo add preserves -``` - -This crate ([`preserves` on crates.io](https://crates.io/crates/preserves)) implements -[Preserves](https://preserves.dev/) for Rust. It provides the core -[semantics](https://preserves.dev/preserves.html#semantics) as well as both the [human-readable -text syntax][crate::value::text] (a superset of JSON) and [machine-oriented binary -format][crate::value::packed] (including -[canonicalization](https://preserves.dev/canonical-binary.html)) for Preserves. - -This crate is the foundation for others such as - - - [`preserves-schema`](https://docs.rs/preserves-schema/), which implements [Preserves - Schema](https://preserves.dev/preserves-schema.html); - - [`preserves-path`](https://docs.rs/preserves-path/), which implements [Preserves - Path](https://preserves.dev/preserves-path.html); and - - [`preserves-tools`](https://crates.io/crates/preserves-tools), which provides command-line - utilities for working with Preserves, in particular - [`preserves-tool`](https://preserves.dev/doc/preserves-tool.html), a kind of Preserves - Swiss-army knife. - -It also includes [Serde](https://serde.rs/) support (modules [de], [ser], [symbol], [set]). diff --git a/implementations/rust/preserves/benches/.gitignore b/implementations/rust/preserves/benches/.gitignore deleted file mode 100644 index 800aca2..0000000 --- a/implementations/rust/preserves/benches/.gitignore +++ /dev/null @@ -1 +0,0 @@ -testdata.bin diff --git a/implementations/rust/preserves/benches/codec.rs b/implementations/rust/preserves/benches/codec.rs deleted file mode 100644 index e1ac1dd..0000000 --- a/implementations/rust/preserves/benches/codec.rs +++ /dev/null @@ -1,170 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use preserves::de; -use preserves::ser; -use preserves::value; -use preserves::value::packed::annotated_iovalue_from_bytes; -use preserves::value::BinarySource; -use preserves::value::BytesBinarySource; -use preserves::value::IOBinarySource; -use preserves::value::IOValueDomainCodec; -use preserves::value::PackedWriter; -use preserves::value::Reader; -use preserves::value::Writer; -use std::fs::File; -use std::io; -use std::io::Read; -use std::io::Seek; - -#[path = "../tests/samples/mod.rs"] -mod samples; -use samples::TestCases; - -pub fn bench_decoder_bytes(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - let mut bs = vec![]; - fh.read_to_end(&mut bs).ok(); - c.bench_function("decode samples.bin via bytes", |b| { - b.iter_with_large_drop(|| annotated_iovalue_from_bytes(&bs[..]).unwrap()) - }); -} - -pub fn bench_decoder_file(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - c.bench_function("decode samples.bin via file", |b| { - b.iter_with_large_drop(|| { - fh.seek(io::SeekFrom::Start(0)).ok(); - IOBinarySource::new(&mut fh) - .packed_iovalues() - .demand_next(true) - .unwrap() - }) - }); -} - -pub fn bench_decoder_buffered_file(c: &mut Criterion) { - let mut fh = io::BufReader::new(File::open("../../../tests/samples.bin").unwrap()); - c.bench_function("decode samples.bin via buffered file", |b| { - b.iter_with_large_drop(|| { - fh.seek(io::SeekFrom::Start(0)).ok(); - IOBinarySource::new(&mut fh) - .packed_iovalues() - .demand_next(true) - .unwrap() - }) - }); -} - -pub fn bench_encoder(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - let v = IOBinarySource::new(&mut fh) - .packed_iovalues() - .demand_next(true) - .unwrap(); - c.bench_function("encode samples.bin", |b| { - b.iter_with_large_drop(|| PackedWriter::encode_iovalue(&v).unwrap()) - }); -} - -pub fn bench_de(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - let mut bs = vec![]; - fh.read_to_end(&mut bs).ok(); - c.bench_function("deserialize samples.bin", |b| { - b.iter_with_large_drop(|| de::from_bytes::(&bs[..]).unwrap()) - }); -} - -pub fn bench_ser(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - let v: TestCases = de::from_read(&mut fh).unwrap(); - c.bench_function("serialize samples.bin", |b| { - b.iter_with_large_drop(|| { - let mut bs = vec![]; - ser::to_writer(&mut PackedWriter::new(&mut bs), &v).unwrap(); - bs - }) - }); -} - -pub fn bench_decoder_de(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - let mut bs = vec![]; - fh.read_to_end(&mut bs).ok(); - c.bench_function("decode-then-deserialize samples.bin", |b| { - b.iter_with_large_drop(|| { - value::de::from_value::(&annotated_iovalue_from_bytes(&bs[..]).unwrap()) - .unwrap() - }) - }); -} - -pub fn bench_ser_encoder(c: &mut Criterion) { - let mut fh = File::open("../../../tests/samples.bin").unwrap(); - let v: TestCases = de::from_read(&mut fh).unwrap(); - c.bench_function("serialize-then-encode samples.bin", |b| { - b.iter_with_large_drop(|| PackedWriter::encode_iovalue(&value::ser::to_value(&v)).unwrap()) - }); -} - -pub fn large_testdata_decoder_with_ann(c: &mut Criterion) { - c.bench_function("decode testdata.bin with annotations", |b| { - let mut fh = File::open("benches/testdata.bin").unwrap(); - let mut bs = vec![]; - fh.read_to_end(&mut bs).ok(); - b.iter(|| { - let mut src = BytesBinarySource::new(&bs[..]); - let mut r = src.packed_iovalues(); - while let Some(_) = r.next(true).unwrap() {} - }) - }); -} - -pub fn large_testdata_decoder_without_ann(c: &mut Criterion) { - c.bench_function("decode testdata.bin without annotations", |b| { - let mut fh = File::open("benches/testdata.bin").unwrap(); - let mut bs = vec![]; - fh.read_to_end(&mut bs).ok(); - b.iter(|| { - let mut src = BytesBinarySource::new(&bs[..]); - let mut r = src.packed_iovalues(); - while let Some(_) = r.next(false).unwrap() {} - }) - }); -} - -pub fn large_testdata_encoder(c: &mut Criterion) { - c.bench_function("encode testdata.bin", |b| { - let mut fh = io::BufReader::new(File::open("benches/testdata.bin").unwrap()); - let mut vs = vec![]; - let mut src = IOBinarySource::new(&mut fh); - let mut r = src.packed_iovalues(); - while let Some(v) = r.next(true).unwrap() { - vs.push(v); - } - b.iter_with_large_drop(|| { - let mut bs = vec![]; - let mut w = PackedWriter::new(&mut bs); - let mut enc = IOValueDomainCodec; - for v in &vs { - w.write(&mut enc, v).unwrap(); - } - bs - }) - }); -} - -criterion_group!( - codec, - bench_decoder_bytes, - bench_decoder_file, - bench_decoder_buffered_file, - bench_encoder -); -criterion_group!(serde, bench_de, bench_ser); -criterion_group!(codec_then_serde, bench_decoder_de, bench_ser_encoder); -criterion_group! { - name = large_testdata; - config = Criterion::default().sample_size(10); - targets = large_testdata_decoder_with_ann, large_testdata_decoder_without_ann, large_testdata_encoder -} -criterion_main!(codec, serde, codec_then_serde, large_testdata); diff --git a/implementations/rust/preserves/benches/testdata.bin.gz b/implementations/rust/preserves/benches/testdata.bin.gz deleted file mode 100644 index 469262f273e693b8e5b2ce264e39e1ab0a2ca4ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72659 zcmeI*JuAck0LSsaC}+{#4Gb=_xjf_{CIeQbWK^#6FeqKgEn-qqB!d?~M&$+%rJPJ$ z3=B3!kr+rM%HW~fZ6@{k^?e1OH}I=k2!)33-V#A!dSoI!oJ=Ph21irD<4IHLOk>c| zTO7@nZ!Hh3#us}Iw;OjSs>k+MVz-|!_it@I-KX(PE}TeSPE}O)A0J#D^{=wfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72>dGWe3pqtgZw_eFCv@cv787HAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5;&zX|Nr&K2dq0A{`p-e*gi z*J|cPfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkL{ RUklts3bXa8uJFcm!4K!f*» = [0xB4] ++ «L» ++ «F_1» ++...++ «F_m» ++ [0x84] - «[X_1...X_m]» = [0xB5] ++ «X_1» ++...++ «X_m» ++ [0x84] - «#{E_1...E_m}» = [0xB6] ++ «E_1» ++...++ «E_m» ++ [0x84] - «{K_1:V_1...K_m:V_m}» = [0xB7] ++ «K_1» ++ «V_1» ++...++ «K_m» ++ «V_m» ++ [0x84] - - varint(n) = [n] if n < 128 - [(n & 127) | 128] ++ varint(n >> 7) if n ≥ 128 - - intbytes(n) = the empty sequence if n = 0, otherwise signedBigEndian(n) - - signedBigEndian(n) = [n & 255] if -128 ≤ n ≤ 127 - signedBigEndian(n >> 8) ++ [n & 255] otherwise -``` - -The function `binary64(D)` yields the big-endian 8-byte IEEE 754 binary representation of `D`. diff --git a/implementations/rust/preserves/doc/cheatsheet-text-plaintext.md b/implementations/rust/preserves/doc/cheatsheet-text-plaintext.md deleted file mode 100644 index af09470..0000000 --- a/implementations/rust/preserves/doc/cheatsheet-text-plaintext.md +++ /dev/null @@ -1,48 +0,0 @@ -```text -Document := Value ws -Value := ws (Record | Collection | Embedded | Annotated | Atom) -Collection := Sequence | Dictionary | Set - -Record := `<` Value+ ws `>` -Sequence := `[` (commas Value)* commas `]` -Set := `#{` (commas Value)* commas `}` -Dictionary := `{` (commas Value ws `:` Value)* commas `}` -commas := (ws `,`)* ws - -Embedded := `#!` Value -Annotated := Annotation Value -Annotation := `@` Value | `#` ((space | tab) linecomment) (cr | lf) - -Atom := Boolean | ByteString | String | QuotedSymbol | Symbol | Number -Boolean := `#t` | `#f` -ByteString := `#"` binchar* `"` - | `#x"` (ws hex hex)* ws `"` - | `#[` (ws base64char)* ws `]` -String := `"` («any unicode scalar except `\` or `"`» | escaped | `\"`)* `"` -QuotedSymbol := `|` («any unicode scalar except `\` or `|`» | escaped | `\|`)* `|` -Symbol := (`A`..`Z` | `a`..`z` | `0`..`9` | sympunct | symuchar)+ -Number := Double | SignedInteger -Double := flt | `#xd"` (ws hex hex)8 ws `"` -SignedInteger := int - -escaped := `\\` | `\/` | `\b` | `\f` | `\n` | `\r` | `\t` | `\u` hex hex hex hex -binescaped := `\\` | `\/` | `\b` | `\f` | `\n` | `\r` | `\t` | `\x` hex hex -binchar := «any scalar ≥32 and ≤126, except `\` or `"`» | binescaped | `\"` -base64char := `A`..`Z` | `a`..`z` | `0`..`9` | `+` | `/` | `-` | `_` | `=` -sympunct := `~` | `!` | `$` | `%` | `^` | `&` | `*` | `?` - | `_` | `=` | `+` | `-` | `/` | `.` -symuchar := «any scalar value ≥128 whose Unicode category is - Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Pc, - Pd, Po, Sc, Sm, Sk, So, or Co» - -flt := int ( frac exp | frac | exp ) -int := (`-`|`+`) (`0`..`9`)+ -frac := `.` (`0`..`9`)+ -exp := (`e`|`E`) (`-`|`+`) (`0`..`9`)+ -hex := `A`..`F` | `a`..`f` | `0`..`9` - -ws := (space | tab | cr | lf)* -delimiter := ws | `<` | `>` | `[` | `]` | `{` | `}` - | `#` | `:` | `"` | `|` | `@` | `;` | `,` -linecomment := «any unicode scalar except cr or lf»* -``` diff --git a/implementations/rust/preserves/doc/value-grammar.md b/implementations/rust/preserves/doc/value-grammar.md deleted file mode 100644 index 21f8762..0000000 --- a/implementations/rust/preserves/doc/value-grammar.md +++ /dev/null @@ -1,17 +0,0 @@ -```text - Value = Atom - | Compound - | Embedded - - Atom = Boolean - | Double - | SignedInteger - | String - | ByteString - | Symbol - - Compound = Record - | Sequence - | Set - | Dictionary -``` diff --git a/implementations/rust/preserves/doc/what-is-preserves.md b/implementations/rust/preserves/doc/what-is-preserves.md deleted file mode 100644 index 3c8d1bc..0000000 --- a/implementations/rust/preserves/doc/what-is-preserves.md +++ /dev/null @@ -1,12 +0,0 @@ -*Preserves* is a data model, with associated serialization formats. - -It supports *records* with user-defined *labels*, embedded -*references*, and the usual suite of atomic and compound data types, -including *binary* data as a distinct type from text strings. Its -*annotations* allow separation of data from metadata such as comments, -trace information, and provenance information. - -Preserves departs from many other data languages in defining how to -*compare* two values. Comparison is based on the data model, not on -syntax or on data structures of any particular implementation -language. diff --git a/implementations/rust/preserves/examples/Makefile b/implementations/rust/preserves/examples/Makefile deleted file mode 100644 index 5ff7815..0000000 --- a/implementations/rust/preserves/examples/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -BINARY_FILES=known-data.bin unknown-data.bin - -all: $(BINARY_FILES) - -%.bin: %.txt Makefile - racket ../../../racket/preserves/preserves/tool.rkt --atob --no-annotations < $< > $@.tmp || (rm -f $@.tmp; false) - mv $@.tmp $@ - -clean: - rm -f $(BINARY_FILES) diff --git a/implementations/rust/preserves/examples/extensibility.rs b/implementations/rust/preserves/examples/extensibility.rs deleted file mode 100644 index 94e72a5..0000000 --- a/implementations/rust/preserves/examples/extensibility.rs +++ /dev/null @@ -1,57 +0,0 @@ -use preserves::{ - de, - value::{self, BinarySource, IOBinarySource, Reader}, -}; -use serde::{Deserialize, Serialize}; -use std::fs::File; -use std::io; - -#[derive(Debug, Serialize, Deserialize, PartialEq)] -enum Fruit { - Apple(Colour), - Pear(Variety), - Banana(Weight, Colour, u8), - - // Peach, - #[serde(other)] - Unknown, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq)] -#[serde(rename = "kilograms")] -struct Weight(f32); - -#[derive(Debug, Serialize, Deserialize, PartialEq)] -struct Colour { - name: String, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq)] -enum Variety { - Conference, - Bosc, - European, - Anjou, -} - -fn try_file(kind: &str, path: &str) -> io::Result<()> { - let fruits_value = IOBinarySource::new(&mut File::open(path)?) - .packed_iovalues() - .demand_next(true)?; - println!("{:#?}", fruits_value); - - let fruits1: Vec = value::de::from_value(&fruits_value)?; - println!("(via generic decoding) {}: {:?}", kind, fruits1); - - let fruits2: Vec = de::from_read(&mut File::open(path)?)?; - println!("(direct from binary) {}: {:?}\n", kind, fruits2); - - assert_eq!(fruits1, fruits2); - Ok(()) -} - -fn main() -> io::Result<()> { - try_file("KNOWN", "examples/known-data.bin")?; - try_file("UNKNOWN", "examples/unknown-data.bin")?; - Ok(()) -} diff --git a/implementations/rust/preserves/examples/known-data.bin b/implementations/rust/preserves/examples/known-data.bin deleted file mode 100644 index adbd836..0000000 --- a/implementations/rust/preserves/examples/known-data.bin +++ /dev/null @@ -1,2 +0,0 @@ -µ´³Apple´³Colour±red„„´³Apple´³Colour±green„„´³Banana´³ kilogramsƒ?¾¸Që…¸„´³Colour±brownish„•„´³Pear´³ -Conference„„„ \ No newline at end of file diff --git a/implementations/rust/preserves/examples/known-data.txt b/implementations/rust/preserves/examples/known-data.txt deleted file mode 100644 index 96ed208..0000000 --- a/implementations/rust/preserves/examples/known-data.txt +++ /dev/null @@ -1,7 +0,0 @@ -@ -[ - > - > - 5> - > -] diff --git a/implementations/rust/preserves/examples/unknown-data.bin b/implementations/rust/preserves/examples/unknown-data.bin deleted file mode 100644 index 0cc8b25..0000000 --- a/implementations/rust/preserves/examples/unknown-data.bin +++ /dev/null @@ -1,2 +0,0 @@ -µ´³Apple´³Colour±red„„´³Peach„´³Apple´³Colour±green„„´³Banana´³ kilogramsƒ?¾¸Që…¸„´³Colour±brownish„•·³ripeness´³Squishy„„„´³Pear´³ -Conference„„„ \ No newline at end of file diff --git a/implementations/rust/preserves/examples/unknown-data.txt b/implementations/rust/preserves/examples/unknown-data.txt deleted file mode 100644 index fce3d3a..0000000 --- a/implementations/rust/preserves/examples/unknown-data.txt +++ /dev/null @@ -1,8 +0,0 @@ -@ -[ - > - - > - 5 {ripeness: }> - > -] diff --git a/implementations/rust/preserves/src/de.rs b/implementations/rust/preserves/src/de.rs deleted file mode 100644 index aa8a41a..0000000 --- a/implementations/rust/preserves/src/de.rs +++ /dev/null @@ -1,479 +0,0 @@ -//! Support for Serde deserialization of Preserves terms described by Rust data types. - -use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor}; -use serde::Deserialize; - -use std::borrow::Cow; -use std::io; -use std::marker::PhantomData; - -use super::value::boundary as B; -use super::value::reader::{BytesBinarySource, IOBinarySource, Reader}; -use super::value::{IOValue, IOValueDomainCodec, PackedReader, TextReader, ViaCodec}; - -pub use super::error::Error; - -/// A [std::result::Result] type including [Error], the Preserves Serde deserialization error -/// type, as its error. -pub type Result = std::result::Result; - -/// Serde deserializer for Preserves-encoded Rust data. Use [Deserializer::from_reader] to -/// construct instances, or [from_bytes]/[from_text]/[from_read]/[from_reader] etc to -/// deserialize single terms directly. -pub struct Deserializer<'de, 'r, R: Reader<'de, IOValue>> { - /// The underlying Preserves [reader][crate::value::reader::Reader]. - pub read: &'r mut R, - phantom: PhantomData<&'de ()>, -} - -/// Deserialize a `T` from `bytes`, which must contain a Preserves [machine-oriented binary -/// syntax][crate::value::packed] term corresponding to the Serde serialization of a `T`. -pub fn from_bytes<'de, T>(bytes: &'de [u8]) -> Result -where - T: Deserialize<'de>, -{ - from_reader(&mut PackedReader::new( - &mut BytesBinarySource::new(bytes), - IOValueDomainCodec, - )) -} - -/// Deserialize a `T` from `text`, which must contain a Preserves [text -/// syntax][crate::value::text] term corresponding to the Serde serialization of a `T`. -pub fn from_text<'de, T>(text: &'de str) -> Result -where - T: Deserialize<'de>, -{ - from_reader(&mut TextReader::new( - &mut BytesBinarySource::new(text.as_bytes()), - ViaCodec::new(IOValueDomainCodec), - )) -} - -/// Deserialize a `T` from `read`, which must yield a Preserves [machine-oriented binary -/// syntax][crate::value::packed] term corresponding to the Serde serialization of a `T`. -pub fn from_read<'de, 'r, IOR: io::Read + io::Seek, T>(read: &'r mut IOR) -> Result -where - T: Deserialize<'de>, -{ - from_reader(&mut PackedReader::new( - &mut IOBinarySource::new(read), - IOValueDomainCodec, - )) -} - -/// Deserialize a `T` from `read`, which must yield a Preserves term corresponding to the Serde -/// serialization of a `T`. -pub fn from_reader<'r, 'de, R: Reader<'de, IOValue>, T>(read: &'r mut R) -> Result -where - T: Deserialize<'de>, -{ - let mut de = Deserializer::from_reader(read); - let t = T::deserialize(&mut de)?; - Ok(t) -} - -impl<'r, 'de, R: Reader<'de, IOValue>> Deserializer<'de, 'r, R> { - /// Construct a Deserializer from `read`, a Preserves [reader][crate::value::Reader]. - pub fn from_reader(read: &'r mut R) -> Self { - Deserializer { - read, - phantom: PhantomData, - } - } -} - -impl<'r, 'de, 'a, R: Reader<'de, IOValue>> serde::de::Deserializer<'de> - for &'a mut Deserializer<'de, 'r, R> -{ - type Error = Error; - - fn deserialize_any(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - // Won't support this here -- use value::de::Deserializer for this - Err(Error::CannotDeserializeAny) - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_bool(self.read.next_boolean()?) - } - - fn deserialize_i8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i8(self.read.next_i8()?) - } - - fn deserialize_i16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i16(self.read.next_i16()?) - } - - fn deserialize_i32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i32(self.read.next_i32()?) - } - - fn deserialize_i64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i64(self.read.next_i64()?) - } - - fn deserialize_u8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u8(self.read.next_u8()?) - } - - fn deserialize_u16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u16(self.read.next_u16()?) - } - - fn deserialize_u32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u32(self.read.next_u32()?) - } - - fn deserialize_u64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u64(self.read.next_u64()?) - } - - fn deserialize_f32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_f32(self.read.next_f64()? as f32) - } - - fn deserialize_f64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_f64(self.read.next_f64()?) - } - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_char(self.read.next_char()?) - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.read.next_str()? { - Cow::Borrowed(s) => visitor.visit_borrowed_str(s), - Cow::Owned(s) => visitor.visit_str(&s), - } - } - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_str(visitor) - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.read.next_bytestring()? { - Cow::Borrowed(bs) => visitor.visit_borrowed_bytes(bs), - Cow::Owned(bs) => visitor.visit_bytes(&bs), - } - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_byte_buf(self.read.next_bytestring()?.into_owned()) - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - if let Some(mut b) = self.read.open_option()? { - self.read - .ensure_more_expected(&mut b, &B::Item::RecordField)?; - let result = visitor.visit_some(&mut *self)?; - self.read.ensure_complete(b, &B::Item::RecordField)?; - Ok(result) - } else { - Ok(visitor.visit_none::()?) - } - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let b = self.read.open_simple_record("tuple", Some(0))?; - let result = visitor.visit_unit::()?; - self.read.ensure_complete(b, &B::Item::RecordField)?; - Ok(result) - } - - fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result - where - V: Visitor<'de>, - { - let b = self.read.open_simple_record(name, Some(0))?; - let result = visitor.visit_unit::()?; - self.read.ensure_complete(b, &B::Item::RecordField)?; - Ok(result) - } - - fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result - where - V: Visitor<'de>, - { - match super::value::magic::transmit_input_value(name, || { - Ok(self.read.demand_next(true)?) - })? { - Some(v) => visitor.visit_u64(v), - None => { - let mut b = self.read.open_simple_record(name, Some(1))?; - self.read - .ensure_more_expected(&mut b, &B::Item::RecordField)?; - let result = visitor.visit_newtype_struct(&mut *self)?; - self.read.ensure_complete(b, &B::Item::RecordField)?; - Ok(result) - } - } - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - // Hack around serde's model: Deserialize *sets* as sequences, - // too, and reconstruct them as Rust Sets on the visitor side. - let i = self.read.open_sequence_or_set()?; - visitor.visit_seq(Seq::new(self, B::Type::default(), i)) - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - let b = self.read.open_simple_record("tuple", Some(len))?; - let mut seq = Seq::new(self, b, B::Item::RecordField); - let result = visitor.visit_seq(&mut seq)?; - seq.skip_remainder()?; - Ok(result) - } - - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let b = self.read.open_simple_record(name, Some(len))?; - let mut seq = Seq::new(self, b, B::Item::RecordField); - let result = visitor.visit_seq(&mut seq)?; - seq.skip_remainder()?; - Ok(result) - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.read.open_dictionary()?; - let mut seq = Seq::new(self, B::Type::default(), B::Item::DictionaryKey); - let result = visitor.visit_map(&mut seq)?; - Ok(result) - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let b = self.read.open_simple_record(name, Some(fields.len()))?; - let mut seq = Seq::new(self, b, B::Item::RecordField); - let result = visitor.visit_seq(&mut seq)?; - seq.skip_remainder()?; - Ok(result) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - visitor.visit_enum(self) - } - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.read.next_symbol()? { - Cow::Borrowed(s) => visitor.visit_borrowed_str(s), - Cow::Owned(s) => visitor.visit_str(&s), - } - } - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_none() - } -} - -#[doc(hidden)] -pub struct Seq<'de, 'r, 'a, R: Reader<'de, IOValue>> { - b: B::Type, - i: B::Item, - de: &'a mut Deserializer<'de, 'r, R>, -} - -impl<'de, 'r, 'a, R: Reader<'de, IOValue>> Seq<'de, 'r, 'a, R> { - fn new(de: &'a mut Deserializer<'de, 'r, R>, b: B::Type, i: B::Item) -> Self { - Seq { b, i, de } - } - - fn skip_remainder(&mut self) -> Result<()> { - while !self.de.read.close_compound(&mut self.b, &self.i)? { - self.de.read.skip_value()?; - } - Ok(()) - } - - fn next_item(&mut self, seed: T) -> Result> - where - T: DeserializeSeed<'de>, - { - match self.de.read.close_compound(&mut self.b, &self.i)? { - true => Ok(None), - false => Ok(Some(seed.deserialize(&mut *self.de)?)), - } - } -} - -impl<'de, 'r, 'a, R: Reader<'de, IOValue>> SeqAccess<'de> for Seq<'de, 'r, 'a, R> { - type Error = Error; - - fn next_element_seed(&mut self, seed: T) -> Result> - where - T: DeserializeSeed<'de>, - { - Ok(self.next_item(seed)?) - } -} - -impl<'de, 'r, 'a, R: Reader<'de, IOValue>> MapAccess<'de> for Seq<'de, 'r, 'a, R> { - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> Result> - where - K: DeserializeSeed<'de>, - { - self.i = B::Item::DictionaryKey; - self.next_item(seed) - } - - fn next_value_seed(&mut self, seed: V) -> Result - where - V: DeserializeSeed<'de>, - { - self.i = B::Item::DictionaryValue; - match self.next_item(seed)? { - Some(item) => Ok(item), - None => Err(Error::MissingItem), - } - } -} - -impl<'de, 'r, 'a, R: Reader<'de, IOValue>> EnumAccess<'de> for &'a mut Deserializer<'de, 'r, R> { - type Error = Error; - type Variant = Seq<'de, 'r, 'a, R>; - - fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> - where - V: DeserializeSeed<'de>, - { - let b = self.read.open_record(None)?; - let variant = seed.deserialize(&mut *self)?; - Ok((variant, Seq::new(self, b, B::Item::RecordField))) - } -} - -impl<'de, 'r, 'a, R: Reader<'de, IOValue>> VariantAccess<'de> for Seq<'de, 'r, 'a, R> { - type Error = Error; - - fn unit_variant(mut self) -> Result<()> { - self.skip_remainder() - } - - fn newtype_variant_seed(mut self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - match self.next_item(seed)? { - None => Err(Error::MissingItem), - Some(v) => { - self.skip_remainder()?; - Ok(v) - } - } - } - - fn tuple_variant(mut self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - let result = visitor.visit_seq(&mut self)?; - self.skip_remainder()?; - Ok(result) - } - - fn struct_variant(mut self, _fields: &'static [&'static str], visitor: V) -> Result - where - V: Visitor<'de>, - { - let result = visitor.visit_seq(&mut self)?; - self.skip_remainder()?; - Ok(result) - } -} diff --git a/implementations/rust/preserves/src/error.rs b/implementations/rust/preserves/src/error.rs deleted file mode 100644 index c67638a..0000000 --- a/implementations/rust/preserves/src/error.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! Serde and plain-Preserves codec errors. - -use num::bigint::BigInt; -use std::convert::From; -use std::io; - -/// Representation of parse, deserialization, and other conversion errors. -#[derive(Debug)] -pub enum Error { - /// Generic IO error. - Io(io::Error), - /// Generic message for the user. - Message(String), - /// Invalid unicode scalar `n` found during interpretation of a `` record - /// as a Rust `char`. - InvalidUnicodeScalar(u32), - /// Preserves supports arbitrary integers; when these are converted to specific Rust - /// machine word types, sometimes they exceed the available range. - NumberOutOfRange(BigInt), - /// Serde has limited support for deserializing free-form data; this error is signalled - /// when one of the limits is hit. - CannotDeserializeAny, - /// Syntax error: missing closing delimiter (`)`, `]`, `}`, `>` in text syntax; `0x84` in binary syntax; etc.) - MissingCloseDelimiter, - /// Signalled when an expected term is not present. - MissingItem, - /// Signalled when what was received did not match expectations. - Expected(ExpectedKind, Received), - #[doc(hidden)] // TODO remove this enum variant? It isn't used - StreamingSerializationUnsupported, -} - -/// Used in [Error::Expected] to indicate what was received. -#[derive(Debug)] -pub enum Received { - #[doc(hidden)] // TODO remove this enum variant? It isn't used - ReceivedSomethingElse, - /// Received a record with the given label symbol text. - ReceivedRecordWithLabel(String), - /// Received some other value, described in the `String` - ReceivedOtherValue(String), -} - -/// Used in [Error::Expected] to indicate what was expected. -#[derive(Debug, PartialEq)] -pub enum ExpectedKind { - Boolean, - Float, - Double, - - SignedIntegerI128, - SignedIntegerU128, - SignedInteger, - String, - ByteString, - Symbol, - - /// Expected a record, either of a specific arity (length) or of no specific arity - Record(Option), - /// Expected a record with a symbol label with text `String`, perhaps of some specific arity - SimpleRecord(String, Option), - Sequence, - Set, - Dictionary, - - Embedded, - - SequenceOrSet, // Because of hacking up serde's data model: see open_sequence_or_set etc. - - Option, - UnicodeScalar, -} - -impl From for Error { - fn from(e: io::Error) -> Self { - Error::Io(e) - } -} - -impl From for io::Error { - fn from(e: Error) -> Self { - match e { - Error::Io(ioe) => ioe, - Error::Message(str) => io::Error::new(io::ErrorKind::Other, str), - _ => io::Error::new(io::ErrorKind::Other, e.to_string()), - } - } -} - -impl serde::ser::Error for Error { - fn custom(msg: T) -> Self { - Self::Message(msg.to_string()) - } -} - -impl serde::de::Error for Error { - fn custom(msg: T) -> Self { - Self::Message(msg.to_string()) - } -} - -impl std::error::Error for Error {} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - -//--------------------------------------------------------------------------- - -/// True iff `e` is `Error::Io` -pub fn is_io_error(e: &Error) -> bool { - matches!(e, Error::Io(_)) -} - -/// Produce the generic "end of file" error, `Error::Io(`[io_eof]`())` -pub fn eof() -> Error { - Error::Io(io_eof()) -} - -/// True iff `e` is an "end of file" error; see [is_eof_io_error] -pub fn is_eof_error(e: &Error) -> bool { - if let Error::Io(ioe) = e { - is_eof_io_error(ioe) - } else { - false - } -} - -/// Produce a syntax error bearing the message `s` -pub fn syntax_error(s: &str) -> Error { - Error::Io(io_syntax_error(s)) -} - -/// True iff `e` is a syntax error; see [is_syntax_io_error] -pub fn is_syntax_error(e: &Error) -> bool { - if let Error::Io(ioe) = e { - is_syntax_io_error(ioe) - } else { - false - } -} - -//--------------------------------------------------------------------------- - -/// Produce an [io::Error] of [io::ErrorKind::UnexpectedEof]. -pub fn io_eof() -> io::Error { - io::Error::new(io::ErrorKind::UnexpectedEof, "EOF") -} - -/// True iff `e` is [io::ErrorKind::UnexpectedEof] -pub fn is_eof_io_error(e: &io::Error) -> bool { - matches!(e.kind(), io::ErrorKind::UnexpectedEof) -} - -/// Produce a syntax error ([io::ErrorKind::InvalidData]) bearing the message `s` -pub fn io_syntax_error(s: &str) -> io::Error { - io::Error::new(io::ErrorKind::InvalidData, s) -} - -/// True iff `e` is an [io::ErrorKind::InvalidData] (a syntax error) -pub fn is_syntax_io_error(e: &io::Error) -> bool { - matches!(e.kind(), io::ErrorKind::InvalidData) -} diff --git a/implementations/rust/preserves/src/hex.rs b/implementations/rust/preserves/src/hex.rs deleted file mode 100644 index 94f1f76..0000000 --- a/implementations/rust/preserves/src/hex.rs +++ /dev/null @@ -1,188 +0,0 @@ -//! Utilities for producing and flexibly parsing strings containing hexadecimal binary data. - -/// Utility for parsing hex binary data from strings. -pub enum HexParser { - /// "Liberal" parsing simply ignores characters that are not (case-insensitive) hex digits. - Liberal, - /// "Whitespace allowed" parsing ignores whitespace, but fails a parse on anything other - /// than hex or whitespace. - WhitespaceAllowed, - /// "Strict" parsing accepts only (case-insensitive) hex digits; no whitespace, no other - /// characters. - Strict, -} - -/// Utility for formatting binary data as hex. -pub enum HexFormatter { - /// Produces LF-separated lines with a maximum of `usize` hex digits in each line. - Lines(usize), - /// Simply packs hex digits in as tightly as possible. - Packed, -} - -/// Convert a number 0..15 to a hex digit [char]. -/// -/// # Panics -/// -/// Panics if given `v` outside the range 0..15 inclusive. -/// -pub fn hexdigit(v: u8) -> char { - char::from_digit(v as u32, 16).expect("hexadecimal digit value") -} - -impl HexParser { - /// Decode `s` according to the given rules for `self`; see [HexParser]. - /// If the parse fails, yield `None`. - pub fn decode(&self, s: &str) -> Option> { - let mut result = Vec::new(); - let mut buf: u8 = 0; - let mut buf_full = false; - for c in s.chars() { - match c.to_digit(16) { - None => match self { - HexParser::Liberal => (), - HexParser::WhitespaceAllowed => { - if !c.is_whitespace() { - return None; - } - } - HexParser::Strict => return None, - }, - Some(nibble) => { - if buf_full { - result.push(buf << 4 | (nibble as u8)); - buf_full = false; - } else { - buf = nibble as u8; - buf_full = true; - } - } - } - } - if buf_full { - None // odd number of hexits - } else { - Some(result) - } - } -} - -impl HexFormatter { - /// Encode `bs` according to the given rules for `self; see [HexFormatter]. - pub fn encode(&self, bs: &[u8]) -> String { - match self { - HexFormatter::Lines(max_line_length) => { - let mut lines = Vec::new(); - let mut line = String::new(); - for b in bs { - if line.len() + 2 > *max_line_length { - lines.push(std::mem::take(&mut line)); - } - line.push(hexdigit(b >> 4)); - line.push(hexdigit(b & 15)); - } - lines.push(std::mem::take(&mut line)); - lines.join("\n") - } - HexFormatter::Packed => { - let mut result = String::new(); - for b in bs { - result.push(hexdigit(b >> 4)); - result.push(hexdigit(b & 15)); - } - result - } - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_decode_packed() { - let s = "01ab00ff"; - assert_eq!(HexParser::Strict.decode(s), Some(vec![1, 171, 0, 255])); - assert_eq!( - HexParser::WhitespaceAllowed.decode(s), - Some(vec![1, 171, 0, 255]) - ); - assert_eq!(HexParser::Liberal.decode(s), Some(vec![1, 171, 0, 255])); - } - - #[test] - fn test_decode_whitespace() { - let s = "01ab 00ff"; - assert_eq!(HexParser::Strict.decode(s), None); - assert_eq!( - HexParser::WhitespaceAllowed.decode(s), - Some(vec![1, 171, 0, 255]) - ); - assert_eq!(HexParser::Liberal.decode(s), Some(vec![1, 171, 0, 255])); - } - - #[test] - fn test_decode_liberal() { - let s = "01ab zz 00ff"; - assert_eq!(HexParser::Strict.decode(s), None); - assert_eq!(HexParser::WhitespaceAllowed.decode(s), None); - assert_eq!(HexParser::Liberal.decode(s), Some(vec![1, 171, 0, 255])); - } - - #[test] - fn test_encode_lines() { - assert_eq!( - HexFormatter::Lines(10).encode(&vec![0x5a; 11]), - "5a5a5a5a5a\n5a5a5a5a5a\n5a" - ); - assert_eq!( - HexFormatter::Lines(10).encode(&vec![0x5a; 10]), - "5a5a5a5a5a\n5a5a5a5a5a" - ); - assert_eq!( - HexFormatter::Lines(10).encode(&vec![0x5a; 9]), - "5a5a5a5a5a\n5a5a5a5a" - ); - assert_eq!( - HexFormatter::Lines(9).encode(&vec![0x5a; 11]), - "5a5a5a5a\n5a5a5a5a\n5a5a5a" - ); - assert_eq!( - HexFormatter::Lines(9).encode(&vec![0x5a; 10]), - "5a5a5a5a\n5a5a5a5a\n5a5a" - ); - assert_eq!( - HexFormatter::Lines(9).encode(&vec![0x5a; 9]), - "5a5a5a5a\n5a5a5a5a\n5a" - ); - assert_eq!( - HexFormatter::Lines(8).encode(&vec![0x5a; 11]), - "5a5a5a5a\n5a5a5a5a\n5a5a5a" - ); - assert_eq!( - HexFormatter::Lines(8).encode(&vec![0x5a; 10]), - "5a5a5a5a\n5a5a5a5a\n5a5a" - ); - assert_eq!( - HexFormatter::Lines(8).encode(&vec![0x5a; 9]), - "5a5a5a5a\n5a5a5a5a\n5a" - ); - } - - #[test] - fn test_encode_packed() { - assert_eq!( - HexFormatter::Packed.encode(&vec![0x5a; 11]), - "5a5a5a5a5a5a5a5a5a5a5a" - ); - assert_eq!( - HexFormatter::Packed.encode(&vec![0x5a; 10]), - "5a5a5a5a5a5a5a5a5a5a" - ); - assert_eq!( - HexFormatter::Packed.encode(&vec![0x5a; 9]), - "5a5a5a5a5a5a5a5a5a" - ); - } -} diff --git a/implementations/rust/preserves/src/lib.rs b/implementations/rust/preserves/src/lib.rs deleted file mode 100644 index 686e78b..0000000 --- a/implementations/rust/preserves/src/lib.rs +++ /dev/null @@ -1,810 +0,0 @@ -#![doc = concat!( - include_str!("../README.md"), - "# What is Preserves?\n\n", - include_str!("../doc/what-is-preserves.md"), -)] - -pub mod de; -pub mod error; -pub mod hex; -pub mod ser; -pub mod set; -pub mod symbol; -pub mod value; - -#[cfg(test)] -mod dom { - use super::value::*; - use std::io; - - #[derive(Debug, Hash, Clone, Ord, PartialEq, Eq, PartialOrd)] - pub enum Dom { - One, - Two, - } - - impl Domain for Dom {} - - impl std::str::FromStr for Dom { - type Err = io::Error; - fn from_str(s: &str) -> Result { - match s { - "One" => Ok(Dom::One), - "Two" => Ok(Dom::Two), - _ => Err(io::Error::new( - io::ErrorKind::Other, - "cannot parse preserves test domain", - )), - } - } - } - - fn dom_as_preserves(v: &Dom) -> io::Result { - Ok(match v { - Dom::One => Value::bytestring(vec![255, 255, 255, 255]), - Dom::Two => Value::symbol(&format!("Dom::{:?}", v)), - }) - } - - #[test] - fn test_one() { - let v: PlainValue<_> = Value::from(vec![ - Value::from(1).wrap(), - Value::Embedded(Dom::One).wrap(), - Value::from(2).wrap(), - ]) - .wrap(); - assert_eq!( - PackedWriter::encode_iovalue(&v.copy_via(&mut dom_as_preserves).unwrap()).unwrap(), - [0xb5, 0xb0, 0x01, 0x01, 0xb2, 0x04, 255, 255, 255, 255, 0xb0, 0x01, 0x02, 0x84] - ); - } - - #[test] - fn test_two() { - let v: PlainValue<_> = Value::from(vec![ - Value::from(1).wrap(), - Value::Embedded(Dom::Two).wrap(), - Value::from(2).wrap(), - ]) - .wrap(); - assert_eq!( - PackedWriter::encode_iovalue(&v.copy_via(&mut dom_as_preserves).unwrap()).unwrap(), - [0xb5, 0xb0, 0x01, 0x01, 0xb3, 0x08, 68, 111, 109, 58, 58, 84, 119, 111, 0xb0, 0x01, 0x02, 0x84] - ); - } -} - -#[cfg(test)] -mod ieee754_section_5_10_total_order_tests { - use super::dom::Dom; - use std::cmp::Ordering::{Equal, Greater, Less}; - - use crate::value::{PlainValue, Value}; - fn d(val: f64) -> Value> { - Value::from(val) - } - - // TODO: Test cases with a few different signalling and non-signalling NaNs - - #[test] - fn case64_a_1() { - assert_eq!(d(1.0).cmp(&d(2.0)), Less) - } - #[test] - fn case64_a_2() { - assert_eq!(d(-1.0).cmp(&d(1.0)), Less) - } - #[test] - fn case64_a_3() { - assert_eq!(d(0.0).cmp(&d(1.0)), Less) - } - #[test] - fn case64_a_4() { - assert_eq!(d(-1.0).cmp(&d(0.0)), Less) - } - #[test] - fn case64_a_5() { - assert_eq!(d(-1e32).cmp(&d(-1e31)), Less) - } - #[test] - fn case64_a_6() { - assert_eq!(d(-1e32).cmp(&d(1e33)), Less) - } - #[test] - fn case64_a_7() { - assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(std::f64::INFINITY)), Less) - } - #[test] - fn case64_a_8() { - assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(0.0)), Less) - } - #[test] - fn case64_a_9() { - assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(1.0)), Less) - } - #[test] - fn case64_a_10() { - assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(1e33)), Less) - } - #[test] - fn case64_a_11() { - assert_eq!(d(0.0).cmp(&d(std::f64::INFINITY)), Less) - } - #[test] - fn case64_a_12() { - assert_eq!(d(1.0).cmp(&d(std::f64::INFINITY)), Less) - } - #[test] - fn case64_a_13() { - assert_eq!(d(1e33).cmp(&d(std::f64::INFINITY)), Less) - } - - #[test] - fn case64_b_1() { - assert_eq!(d(2.0).cmp(&d(1.0)), Greater) - } - #[test] - fn case64_b_2() { - assert_eq!(d(1.0).cmp(&d(-1.0)), Greater) - } - #[test] - fn case64_b_3() { - assert_eq!(d(1.0).cmp(&d(0.0)), Greater) - } - #[test] - fn case64_b_4() { - assert_eq!(d(0.0).cmp(&d(-1.0)), Greater) - } - #[test] - fn case64_b_5() { - assert_eq!(d(-1e31).cmp(&d(-1e32)), Greater) - } - #[test] - fn case64_b_6() { - assert_eq!(d(1e33).cmp(&d(-1e32)), Greater) - } - #[test] - fn case64_b_7() { - assert_eq!( - d(std::f64::INFINITY).cmp(&d(std::f64::NEG_INFINITY)), - Greater - ) - } - #[test] - fn case64_b_8() { - assert_eq!(d(std::f64::INFINITY).cmp(&d(0.0)), Greater) - } - #[test] - fn case64_b_9() { - assert_eq!(d(std::f64::INFINITY).cmp(&d(1.0)), Greater) - } - #[test] - fn case64_b_10() { - assert_eq!(d(std::f64::INFINITY).cmp(&d(1e33)), Greater) - } - #[test] - fn case64_b_11() { - assert_eq!(d(0.0).cmp(&d(std::f64::NEG_INFINITY)), Greater) - } - #[test] - fn case64_b_12() { - assert_eq!(d(1.0).cmp(&d(std::f64::NEG_INFINITY)), Greater) - } - #[test] - fn case64_b_13() { - assert_eq!(d(1e33).cmp(&d(std::f64::NEG_INFINITY)), Greater) - } - - #[test] - fn case64_c1() { - assert_eq!(d(-0.0).cmp(&d(0.0)), Less) - } - #[test] - fn case64_c2() { - assert_eq!(d(0.0).cmp(&d(-0.0)), Greater) - } - #[test] - fn case64_c3_1() { - assert_eq!(d(-0.0).cmp(&d(-0.0)), Equal) - } - #[test] - fn case64_c3_2() { - assert_eq!(d(0.0).cmp(&d(0.0)), Equal) - } - #[test] - fn case64_c3_3() { - assert_eq!(d(1.0).cmp(&d(1.0)), Equal) - } - #[test] - fn case64_c3_4() { - assert_eq!(d(-1.0).cmp(&d(-1.0)), Equal) - } - #[test] - fn case64_c3_5() { - assert_eq!(d(-1e32).cmp(&d(-1e32)), Equal) - } - #[test] - fn case64_c3_6() { - assert_eq!(d(1e33).cmp(&d(1e33)), Equal) - } -} - -#[cfg(test)] -mod value_tests { - use super::dom::Dom; - use crate::value::{repr::Record, signed_integer::SignedInteger, PlainValue, Value}; - - type VV = Value>; - - #[test] - fn boolean_mut() { - let mut b = VV::Boolean(true); - assert!(b.is_boolean()); - *(b.as_boolean_mut().unwrap()) = false; - assert_eq!(b, VV::Boolean(false)); - } - - #[test] - fn double_mut() { - let mut f = VV::from(1.0); - assert!(f.is_f64()); - *(f.as_f64_mut().unwrap()) = 123.45; - assert_eq!(f, VV::from(123.45)); - assert_eq!( - (f.as_f64().unwrap() - 123.45).abs() < std::f64::EPSILON, - true - ); - } - - #[test] - fn signedinteger_mut() { - let mut i = VV::from(123); - assert!(i.is_signedinteger()); - *(i.as_signedinteger_mut().unwrap()) = SignedInteger::from(234i128); - assert_eq!(i, VV::from(234)); - assert_eq!(i.as_i().unwrap(), 234); - } - - #[test] - fn string_mut() { - let mut s = VV::from("hello, world!"); - assert!(s.is_string()); - s.as_string_mut().unwrap().replace_range(7..12, "there"); - assert_eq!(s, VV::from("hello, there!")); - } - - #[test] - fn bytes_mut() { - let mut b = VV::from(&b"hello, world!"[..]); - assert!(b.is_bytestring()); - b.as_bytestring_mut() - .unwrap() - .splice(7..12, Vec::from(&b"there"[..])); - assert_eq!(b, VV::from(&b"hello, there!"[..])); - } - - #[test] - fn symbol_mut() { - let mut s = VV::symbol("abcd"); - assert!(s.is_symbol()); - s.as_symbol_mut().unwrap().replace_range(..2, "AB"); - assert_eq!(s, VV::symbol("ABcd")); - } - - #[test] - fn record_mut() { - let says = VV::symbol("says").wrap(); - let mut r = VV::Record(Record(vec![ - says.clone(), - VV::from("Tony").wrap(), - VV::from("Hello!").wrap(), - ])); - assert_eq!(r.as_record_mut(Some(0)), None); - assert_eq!(r.as_record_mut(Some(1)), None); - assert!(r.as_record_mut(Some(2)).is_some()); - assert_eq!(r.as_record_mut(Some(3)), None); - r.as_record_mut(None).unwrap().fields_mut()[0] = VV::from("Alice").wrap(); - assert_eq!( - r, - VV::Record(Record(vec![ - says, - VV::from("Alice").wrap(), - VV::from("Hello!").wrap() - ])) - ); - } - - #[test] - fn sequence_mut() { - let mut s = VV::Sequence(vec![ - VV::from(1).wrap(), - VV::from(2).wrap(), - VV::from(3).wrap(), - ]); - let r = VV::Sequence(vec![ - VV::from(1).wrap(), - VV::from(99).wrap(), - VV::from(3).wrap(), - ]); - s.as_sequence_mut().unwrap()[1] = VV::from(99).wrap(); - assert_eq!(r, s); - } -} - -#[cfg(test)] -mod decoder_tests { - use crate::de::from_bytes; - use crate::error::{is_eof_io_error, Error, ExpectedKind}; - use crate::value::{BinarySource, BytesBinarySource, ConfiguredReader, NestedValue, Value}; - - fn expect_number_out_of_range(r: Result) { - match r { - Ok(v) => panic!("Expected NumberOutOfRange, but got a parse of {:?}", v), - Err(Error::NumberOutOfRange(_)) => (), - Err(e) => panic!("Expected NumberOutOfRange, but got an error of {:?}", e), - } - } - - fn expect_expected(k: ExpectedKind, r: Result) { - match r { - Ok(v) => panic!("Expected Expected({:?}), but got a parse of {:?}", k, v), - Err(Error::Expected(k1, _)) if k1 == k => (), - Err(e) => panic!("Expected Expected({:?}), but got an error of {:?}", k, e), - } - } - - #[test] - fn skip_annotations_noskip() { - let buf = &b"\x85\xB0\x01\x02\xB0\x01\x01"[..]; - let mut src = BytesBinarySource::new(&buf); - let mut d = ConfiguredReader::new(src.packed_iovalues()); - let v = d.demand_next().unwrap(); - assert_eq!(v.annotations().slice().len(), 1); - assert_eq!(v.annotations().slice()[0], Value::from(2).wrap()); - assert_eq!(v.value(), &Value::from(1)); - } - - #[test] - fn skip_annotations_skip() { - let buf = &b"\x85\xB0\x01\x02\xB0\x01\x01"[..]; - let mut src = BytesBinarySource::new(&buf); - let mut d = ConfiguredReader::new(src.packed_iovalues()); - d.set_read_annotations(false); - let v = d.demand_next().unwrap(); - assert_eq!(v.annotations().slice().len(), 0); - assert_eq!(v.value(), &Value::from(1)); - } - - #[test] - fn multiple_values_buf_advanced() { - let buf = &b"\xb4\xb3\x04Ping\x84\xb4\xb3\x04Pong\x84"[..]; - assert_eq!(buf.len(), 16); - let mut src = BytesBinarySource::new(&buf); - let mut d = ConfiguredReader::new(src.packed_iovalues()); - assert_eq!(d.reader.source.index, 0); - assert_eq!( - d.demand_next().unwrap().value(), - &Value::simple_record0("Ping") - ); - assert_eq!(d.reader.source.index, 8); - assert_eq!( - d.demand_next().unwrap().value(), - &Value::simple_record0("Pong") - ); - assert_eq!(d.reader.source.index, 16); - assert!(d.next().is_none()); - assert!(if let Err(e) = d.demand_next() { - is_eof_io_error(&e) - } else { - false - }); - } - - #[test] - fn direct_i8_format_a_positive() { - assert_eq!(from_bytes::(b"\xB0\x01\x01").unwrap(), 1) - } - #[test] - fn direct_i8_format_a_zero() { - assert_eq!(from_bytes::(b"\xB0\x00").unwrap(), 0) - } - #[test] - fn direct_i8_format_a_negative() { - assert_eq!(from_bytes::(b"\xB0\x01\xff").unwrap(), -1) - } - #[test] - fn direct_i8_format_b() { - assert_eq!(from_bytes::(b"\xb0\x01\xfe").unwrap(), -2) - } - #[test] - fn direct_i8_format_b_too_long() { - assert_eq!(from_bytes::(b"\xb0\x03\xff\xff\xfe").unwrap(), -2) - } - #[test] - fn direct_i8_format_b_much_too_long() { - assert_eq!( - from_bytes::(b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe").unwrap(), - -2 - ) - } - - #[test] - fn direct_u8_format_a_positive() { - assert_eq!(from_bytes::(b"\xB0\x01\x01").unwrap(), 1) - } - #[test] - fn direct_u8_format_a_zero() { - assert_eq!(from_bytes::(b"\xB0\x00").unwrap(), 0) - } - #[test] - fn direct_u8_format_b() { - assert_eq!(from_bytes::(b"\xb0\x011").unwrap(), 49) - } - #[test] - fn direct_u8_format_b_too_long() { - assert_eq!(from_bytes::(b"\xb0\x04\0\0\01").unwrap(), 49) - } - #[test] - fn direct_u8_format_b_much_too_long() { - assert_eq!(from_bytes::(b"\xb0\x0a\0\0\0\0\0\0\0\0\01").unwrap(), 49) - } - - #[test] - fn direct_i16_format_a() { - assert_eq!(from_bytes::(b"\xB0\x01\xfe").unwrap(), -2) - } - #[test] - fn direct_i16_format_b() { - assert_eq!(from_bytes::(b"\xb0\x02\xfe\xff").unwrap(), -257) - } - - #[test] - fn direct_u8_wrong_format() { - expect_expected( - ExpectedKind::SignedInteger, - from_bytes::(b"\xb1\x05bogus"), - ) - } - - #[test] - fn direct_u8_format_b_too_large() { - expect_number_out_of_range(from_bytes::(b"\xb0\x04\0\011")) - } - - #[test] - fn direct_i8_format_b_too_large() { - expect_number_out_of_range(from_bytes::(b"\xb0\x02\xfe\xff")) - } - - #[test] - fn direct_i16_format_b_too_large() { - expect_number_out_of_range(from_bytes::(b"\xb0\x03\xfe\xff\xff")); - } - - #[test] - fn direct_i32_format_b_ok() { - assert_eq!(from_bytes::(b"\xb0\x03\xfe\xff\xff").unwrap(), -65537); - } - - #[test] - fn direct_i32_format_b_ok_2() { - assert_eq!( - from_bytes::(b"\xb0\x04\xfe\xff\xff\xff").unwrap(), - -16777217 - ); - } - - #[test] - fn direct_i64_format_b() { - assert_eq!(from_bytes::(b"\xb0\x01\xff").unwrap(), -1); - assert_eq!(from_bytes::(b"\xb0\x03\xff\xff\xff").unwrap(), -1); - assert_eq!( - from_bytes::(b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff").unwrap(), - -1 - ); - assert_eq!(from_bytes::(b"\xb0\x01\xfe").unwrap(), -2); - assert_eq!(from_bytes::(b"\xb0\x03\xff\xfe\xff").unwrap(), -257); - assert_eq!(from_bytes::(b"\xb0\x03\xfe\xff\xff").unwrap(), -65537); - assert_eq!( - from_bytes::(b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff").unwrap(), - -16777217 - ); - assert_eq!( - from_bytes::(b"\xb0\x0a\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff").unwrap(), - -72057594037927937 - ); - expect_number_out_of_range(from_bytes::( - b"\xb0\x0a\xff\xff\x0e\xff\xff\xff\xff\xff\xff\xff", - )); - expect_number_out_of_range(from_bytes::( - b"\xb0\x09\xff\x0e\xff\xff\xff\xff\xff\xff\xff", - )); - expect_number_out_of_range(from_bytes::( - b"\xb0\x09\x80\x0e\xff\xff\xff\xff\xff\xff\xff", - )); - expect_number_out_of_range(from_bytes::( - b"\xb0\x0a\xff\x00\x0e\xff\xff\xff\xff\xff\xff\xff", - )); - assert_eq!( - from_bytes::(b"\xb0\x08\xfe\xff\xff\xff\xff\xff\xff\xff").unwrap(), - -72057594037927937 - ); - assert_eq!( - from_bytes::(b"\xb0\x08\x0e\xff\xff\xff\xff\xff\xff\xff").unwrap(), - 1080863910568919039 - ); - assert_eq!( - from_bytes::(b"\xb0\x08\x80\0\0\0\0\0\0\0").unwrap(), - -9223372036854775808 - ); - assert_eq!(from_bytes::(b"\xb0\x08\0\0\0\0\0\0\0\0").unwrap(), 0); - assert_eq!(from_bytes::(b"\xB0\x00").unwrap(), 0); - assert_eq!( - from_bytes::(b"\xb0\x08\x7f\xff\xff\xff\xff\xff\xff\xff").unwrap(), - 9223372036854775807 - ); - } - - #[test] - fn direct_u64_format_b() { - expect_number_out_of_range(from_bytes::(b"\xb0\x01\xff")); - assert_eq!(from_bytes::(b"\xb0\x02\0\xff").unwrap(), 255); - expect_number_out_of_range(from_bytes::(b"\xb0\x03\xff\xff\xff")); - assert_eq!(from_bytes::(b"\xb0\x04\0\xff\xff\xff").unwrap(), 0xffffff); - expect_number_out_of_range(from_bytes::( - b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", - )); - assert_eq!(from_bytes::(b"\xb0\x01\x02").unwrap(), 2); - assert_eq!(from_bytes::(b"\xb0\x03\x00\x01\x00").unwrap(), 256); - assert_eq!(from_bytes::(b"\xb0\x03\x01\x00\x00").unwrap(), 65536); - assert_eq!( - from_bytes::(b"\xb0\x0a\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00").unwrap(), - 16777216 - ); - assert_eq!( - from_bytes::(b"\xb0\x0a\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00").unwrap(), - 72057594037927936 - ); - assert_eq!( - from_bytes::(b"\xb0\x0a\x00\x00\xf2\x00\x00\x00\x00\x00\x00\x00").unwrap(), - 0xf200000000000000 - ); - assert_eq!( - from_bytes::(b"\xb0\x0a\x00\x00\x72\x00\x00\x00\x00\x00\x00\x00").unwrap(), - 0x7200000000000000 - ); - expect_number_out_of_range(from_bytes::( - b"\xb0\x0a\x00\xf2\x00\x00\x00\x00\x00\x00\x00\x00", - )); - assert_eq!( - from_bytes::(b"\xb0\x09\x00\xf2\x00\x00\x00\x00\x00\x00\x00").unwrap(), - 0xf200000000000000 - ); - expect_number_out_of_range(from_bytes::( - b"\xb0\x09\x7f\xf2\x00\x00\x00\x00\x00\x00\x00", - )); - expect_number_out_of_range(from_bytes::( - b"\xb0\x0a\x00\xff\xf2\x00\x00\x00\x00\x00\x00\x00", - )); - assert_eq!( - from_bytes::(b"\xb0\x08\x01\x00\x00\x00\x00\x00\x00\x00").unwrap(), - 72057594037927936 - ); - assert_eq!( - from_bytes::(b"\xb0\x08\x0e\xff\xff\xff\xff\xff\xff\xff").unwrap(), - 1080863910568919039 - ); - expect_number_out_of_range(from_bytes::(b"\xb0\x08\x80\0\0\0\0\0\0\0")); - assert_eq!( - from_bytes::(b"\xb0\x09\0\x80\0\0\0\0\0\0\0").unwrap(), - 9223372036854775808 - ); - assert_eq!(from_bytes::(b"\xb0\x08\0\0\0\0\0\0\0\0").unwrap(), 0); - assert_eq!(from_bytes::(b"\xB0\x00").unwrap(), 0); - assert_eq!( - from_bytes::(b"\xb0\x08\x7f\xff\xff\xff\xff\xff\xff\xff").unwrap(), - 9223372036854775807 - ); - } -} - -#[cfg(test)] -mod formatting_tests { - use super::dom::Dom; - use super::value::ArcValue; - use super::value::IOValue; - use super::value::Value; - - #[test] - fn format_debug_and_parse() { - let v = "[1, {z: 2, a: #!\"One\"}, 3]" - .parse::>>() - .unwrap(); - assert_eq!(format!("{:?}", &v), "[1, {a: #!\"One\", z: 2}, 3]"); - } - - #[test] - fn format_pretty_debug_and_parse() { - let v = "[1, {z: 2, a: #!\"One\"}, 3]" - .parse::>>() - .unwrap(); - assert_eq!( - format!("{:#?}", &v), - concat!( - "[\n", - " 1,\n", - " {\n", - " a: #!\"One\",\n", - " z: 2\n", - " },\n", - " 3\n", - "]" - ) - ); - } - - #[test] - fn iovalue_parse() { - let v = "[1 @{a:b c:d} @\"foo\" #![2 3] 4]" - .parse::() - .unwrap(); - assert_eq!( - format!("{:#?}", &v), - concat!( - "[\n", - " 1,\n", - " @{\n", - " a: b,\n", - " c: d\n", - " } @\"foo\" #![\n", - " 2,\n", - " 3\n", - " ],\n", - " 4\n", - "]" - ) - ); - } -} - -#[cfg(test)] -mod serde_tests { - use crate::de::from_bytes as deserialize_from_bytes; - use crate::symbol::Symbol; - use crate::value::de::from_value as deserialize_from_value; - use crate::value::packed::PackedWriter; - use crate::value::to_value; - use crate::value::{IOValue, Map, Set, Value}; - - #[test] - fn simple_to_value() { - use serde::Serialize; - #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] - struct Colour { - red: u8, - green: u8, - blue: u8, - } - #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)] - struct SimpleValue<'a>( - String, - #[serde(with = "crate::symbol")] String, - Symbol, - #[serde(with = "crate::symbol")] String, - Symbol, - &'a str, - #[serde(with = "serde_bytes")] &'a [u8], - #[serde(with = "serde_bytes")] Vec, - Vec, - #[serde(with = "crate::set")] Set, - i16, - IOValue, - Map, - f32, - f64, - ); - let mut str_set = Set::new(); - str_set.insert("one".to_owned()); - str_set.insert("two".to_owned()); - str_set.insert("three".to_owned()); - let mut colours = Map::new(); - colours.insert( - "red".to_owned(), - Colour { - red: 255, - green: 0, - blue: 0, - }, - ); - colours.insert( - "green".to_owned(), - Colour { - red: 0, - green: 255, - blue: 0, - }, - ); - colours.insert( - "blue".to_owned(), - Colour { - red: 0, - green: 0, - blue: 255, - }, - ); - let v = SimpleValue( - "hello".to_string(), - "sym1".to_string(), - Symbol("sym2".to_string()), - "sym3".to_string(), - Symbol("sym4".to_string()), - "world", - &b"slice"[..], - b"vec".to_vec(), - vec![false, true, false, true], - str_set, - 12345, - Value::from("hi").wrap(), - colours, - 12.345f32, - 12.3456789, - ); - println!("== v: {:#?}", v); - let w: IOValue = to_value(&v); - println!("== w: {:#?}", w); - let x = deserialize_from_value(&w).unwrap(); - println!("== x: {:#?}", &x); - assert_eq!(v, x); - - let expected_bytes = vec![ - 0xb4, // Struct - 0xb3, 0x0b, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, // SimpleValue - 0xb1, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // "hello" - 0xb3, 0x04, 0x73, 0x79, 0x6d, 0x31, // sym1 - 0xb3, 0x04, 0x73, 0x79, 0x6d, 0x32, // sym2 - 0xb3, 0x04, 0x73, 0x79, 0x6d, 0x33, // sym3 - 0xb3, 0x04, 0x73, 0x79, 0x6d, 0x34, // sym4 - 0xb1, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // "world" - 0xb2, 0x05, 0x73, 0x6c, 0x69, 0x63, 0x65, // #"slice" - 0xb2, 0x03, 0x76, 0x65, 0x63, // #"vec" - 0xb5, // Sequence - 0x80, // false - 0x81, // true - 0x80, // false - 0x81, // true - 0x84, 0xb6, // Set - 0xb1, 0x03, 0x6f, 0x6e, 0x65, 0xb1, 0x03, 0x74, 0x77, 0x6f, 0xb1, 0x05, 0x74, 0x68, - 0x72, 0x65, 0x65, 0x84, 0xb0, 0x02, 0x30, 0x39, // 12345 - 0xb1, 0x02, 0x68, 0x69, // "hi" - 0xb7, // Dictionary - 0xb1, 0x03, 0x72, 0x65, 0x64, // "red" - 0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0xb0, 0x02, 0x00, 0xff, 0xb0, 0x00, 0xb0, 0x00, - 0x84, 0xb1, 0x04, 0x62, 0x6c, 0x75, 0x65, // "blue" - 0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0xb0, 0x00, 0xb0, 0x00, 0xb0, 0x02, 0x00, 0xff, - 0x84, 0xb1, 0x05, 0x67, 0x72, 0x65, 0x65, 0x6e, // "green" - 0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0xb0, 0x00, 0xb0, 0x02, 0x00, 0xff, 0xb0, 0x00, - 0x84, 0x84, - 0x87, 0x08, 0x40, 0x28, 0xb0, 0xa3, 0xe0, 0x00, 0x00, 0x00, // 12.345f32 - 0x87, 0x08, 0x40, 0x28, 0xb0, 0xfc, 0xd3, 0x24, 0xd5, 0xa2, // 12.3456789 - 0x84, - ]; - - let y = deserialize_from_bytes(&expected_bytes).unwrap(); - println!("== y: {:#?}", &y); - assert_eq!(v, y); - - let v_bytes_1 = PackedWriter::encode_iovalue(&w).unwrap(); - println!("== w bytes = {:?}", v_bytes_1); - assert_eq!(expected_bytes, v_bytes_1); - - let mut v_bytes_2 = Vec::new(); - v.serialize(&mut crate::ser::Serializer::new(&mut PackedWriter::new( - &mut v_bytes_2, - ))) - .unwrap(); - println!("== v bytes = {:?}", v_bytes_2); - assert_eq!(v_bytes_1, v_bytes_2); - } -} diff --git a/implementations/rust/preserves/src/ser.rs b/implementations/rust/preserves/src/ser.rs deleted file mode 100644 index 6aea76b..0000000 --- a/implementations/rust/preserves/src/ser.rs +++ /dev/null @@ -1,458 +0,0 @@ -//! Support for Serde serialization of Rust data types into Preserves terms. - -use super::value::boundary as B; -use super::value::writer::{CompoundWriter, Writer}; -use super::value::IOValueDomainCodec; -use serde::Serialize; - -pub use super::error::Error; -type Result = std::result::Result; - -#[derive(Debug)] -/// Serde serializer for Preserves-encoding Rust data. Construct via [Serializer::new], and use -/// with [serde::Serialize::serialize] methods. -pub struct Serializer<'w, W: Writer> { - /// The underlying Preserves [writer][crate::value::writer::Writer]. - pub write: &'w mut W, -} - -impl<'w, W: Writer> Serializer<'w, W> { - /// Construct a new [Serializer] targetting the given - /// [writer][crate::value::writer::Writer]. - pub fn new(write: &'w mut W) -> Self { - Serializer { write } - } -} - -enum SequenceVariant { - Sequence(W::SeqWriter), - Record(W::RecWriter), -} - -#[doc(hidden)] -pub struct SerializeCompound<'a, 'w, W: Writer> { - b: B::Type, - i: B::Item, - ser: &'a mut Serializer<'w, W>, - c: SequenceVariant, -} - -#[doc(hidden)] -pub struct SerializeDictionary<'a, 'w, W: Writer> { - b: B::Type, - ser: &'a mut Serializer<'w, W>, - d: W::DictWriter, -} - -impl<'a, 'w, W: Writer> serde::Serializer for &'a mut Serializer<'w, W> { - type Ok = (); - type Error = Error; - type SerializeSeq = SerializeCompound<'a, 'w, W>; - type SerializeTuple = SerializeCompound<'a, 'w, W>; - type SerializeTupleStruct = SerializeCompound<'a, 'w, W>; - type SerializeTupleVariant = SerializeCompound<'a, 'w, W>; - type SerializeMap = SerializeDictionary<'a, 'w, W>; - type SerializeStruct = SerializeCompound<'a, 'w, W>; - type SerializeStructVariant = SerializeCompound<'a, 'w, W>; - - fn serialize_bool(self, v: bool) -> Result { - Ok(self.write.write_bool(v)?) - } - - fn serialize_i8(self, v: i8) -> Result { - Ok(self.write.write_i8(v)?) - } - - fn serialize_i16(self, v: i16) -> Result { - Ok(self.write.write_i16(v)?) - } - - fn serialize_i32(self, v: i32) -> Result { - Ok(self.write.write_i32(v)?) - } - - fn serialize_i64(self, v: i64) -> Result { - Ok(self.write.write_i64(v)?) - } - - fn serialize_u8(self, v: u8) -> Result { - Ok(self.write.write_u8(v)?) - } - - fn serialize_u16(self, v: u16) -> Result { - Ok(self.write.write_u16(v)?) - } - - fn serialize_u32(self, v: u32) -> Result { - Ok(self.write.write_u32(v)?) - } - - fn serialize_u64(self, v: u64) -> Result { - Ok(self.write.write_u64(v)?) - } - - fn serialize_f32(self, v: f32) -> Result { - Ok(self.write.write_f64(v as f64)?) - } - - fn serialize_f64(self, v: f64) -> Result { - Ok(self.write.write_f64(v)?) - } - - fn serialize_char(self, v: char) -> Result { - let mut c = self.write.start_record(Some(1))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol("UnicodeScalar")?; - c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?; - c.write_u32(v as u32)?; - c.boundary(&B::end(B::Item::RecordField))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_str(self, v: &str) -> Result { - Ok(self.write.write_string(v)?) - } - - fn serialize_bytes(self, v: &[u8]) -> Result { - Ok(self.write.write_bytes(v)?) - } - - fn serialize_none(self) -> Result { - let mut c = self.write.start_record(Some(0))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol("None")?; - c.boundary(&B::end(B::Item::RecordLabel))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_some(self, v: &T) -> Result - where - T: Serialize, - { - let mut c = self.write.start_record(Some(1))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol("Some")?; - c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?; - to_writer(&mut c, v)?; - c.boundary(&B::end(B::Item::RecordField))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_unit(self) -> Result { - let mut c = self.write.start_record(Some(0))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol("tuple")?; - c.boundary(&B::end(B::Item::RecordLabel))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_unit_struct(self, name: &'static str) -> Result { - let mut c = self.write.start_record(Some(0))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(name)?; - c.boundary(&B::end(B::Item::RecordLabel))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - ) -> Result { - let mut c = self.write.start_record(Some(0))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(variant_name)?; - c.boundary(&B::end(B::Item::RecordLabel))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result - where - T: Serialize, - { - match super::value::magic::receive_output_value(name, value) { - Some(v) => Ok(self.write.write(&mut IOValueDomainCodec, &v)?), - None => { - // TODO: This is apparently discouraged, and we should apparently just serialize `value`? - let mut c = self.write.start_record(Some(1))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(name)?; - c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?; - to_writer(&mut c, value)?; - c.boundary(&B::end(B::Item::RecordField))?; - Ok(self.write.end_record(c)?) - } - } - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - let mut c = self.write.start_record(Some(1))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(variant_name)?; - c.boundary(&B::mid(B::Item::RecordLabel, B::Item::RecordField))?; - to_writer(&mut c, value)?; - c.boundary(&B::end(B::Item::RecordField))?; - Ok(self.write.end_record(c)?) - } - - fn serialize_seq(self, count: Option) -> Result { - let c = self.write.start_sequence(count)?; - Ok(SerializeCompound::seq(self, c)) - } - - fn serialize_tuple(self, count: usize) -> Result { - let mut c = self.write.start_record(Some(count))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol("tuple")?; - Ok(SerializeCompound::rec(self, c)) - } - - fn serialize_tuple_struct( - self, - name: &'static str, - count: usize, - ) -> Result { - let mut c = self.write.start_record(Some(count))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(name)?; - Ok(SerializeCompound::rec(self, c)) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - count: usize, - ) -> Result { - let mut c = self.write.start_record(Some(count))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(variant_name)?; - Ok(SerializeCompound::rec(self, c)) - } - - fn serialize_map(self, count: Option) -> Result { - let d = self.write.start_dictionary(count)?; - Ok(SerializeDictionary { - b: B::Type::default(), - ser: self, - d, - }) - } - - fn serialize_struct(self, name: &'static str, count: usize) -> Result { - let mut c = self.write.start_record(Some(count))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(name)?; - Ok(SerializeCompound::rec(self, c)) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - count: usize, - ) -> Result { - let mut c = self.write.start_record(Some(count))?; - c.boundary(&B::start(B::Item::RecordLabel))?; - c.write_symbol(variant_name)?; - Ok(SerializeCompound::rec(self, c)) - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeMap for SerializeDictionary<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, key: &T) -> Result<()> - where - T: Serialize, - { - self.b.opening = Some(B::Item::DictionaryKey); - self.d.boundary(&self.b)?; - to_writer(&mut self.d, key)?; - self.b.shift(None); - Ok(()) - } - - fn serialize_value(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.b.opening = Some(B::Item::DictionaryValue); - self.d.boundary(&self.b)?; - to_writer(&mut self.d, value)?; - self.b.shift(None); - Ok(()) - } - - fn end(mut self) -> Result { - self.d.boundary(&self.b)?; - Ok(self.ser.write.end_dictionary(self.d)?) - } -} - -impl<'a, 'w, W: Writer> SerializeCompound<'a, 'w, W> { - fn seq(ser: &'a mut Serializer<'w, W>, c: W::SeqWriter) -> Self { - SerializeCompound { - b: B::Type::default(), - i: B::Item::SequenceValue, - ser, - c: SequenceVariant::Sequence(c), - } - } - - fn rec(ser: &'a mut Serializer<'w, W>, c: W::RecWriter) -> Self { - SerializeCompound { - b: B::end(B::Item::RecordLabel), - i: B::Item::RecordField, - ser, - c: SequenceVariant::Record(c), - } - } - - fn extend(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.b.opening = Some(self.i.clone()); - match &mut self.c { - SequenceVariant::Sequence(w) => { - w.boundary(&self.b)?; - to_writer(w, value)?; - } - SequenceVariant::Record(w) => { - w.boundary(&self.b)?; - to_writer(w, value)?; - } - } - self.b.shift(None); - Ok(()) - } - - fn complete(self) -> Result<()> { - match self.c { - SequenceVariant::Sequence(mut w) => { - w.boundary(&self.b)?; - Ok(self.ser.write.end_sequence(w)?) - } - SequenceVariant::Record(mut w) => { - w.boundary(&self.b)?; - Ok(self.ser.write.end_record(w)?) - } - } - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeStruct for SerializeCompound<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, _name: &'static str, value: &T) -> Result<()> - where - T: Serialize, - { - self.extend(value) - } - - fn end(self) -> Result { - self.complete() - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeStructVariant for SerializeCompound<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, _name: &'static str, value: &T) -> Result<()> - where - T: Serialize, - { - self.extend(value) - } - - fn end(self) -> Result { - self.complete() - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeTuple for SerializeCompound<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.extend(value) - } - - fn end(self) -> Result { - self.complete() - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeTupleStruct for SerializeCompound<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.extend(value) - } - - fn end(self) -> Result { - self.complete() - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeTupleVariant for SerializeCompound<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.extend(value) - } - - fn end(self) -> Result { - self.complete() - } -} - -impl<'a, 'w, W: Writer> serde::ser::SerializeSeq for SerializeCompound<'a, 'w, W> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.extend(value) - } - - fn end(self) -> Result { - self.complete() - } -} - -/// Convenience function for directly serializing a Serde-serializable `T` to the given -/// `write`, a Preserves [writer][crate::value::writer::Writer]. -pub fn to_writer(write: &mut W, value: &T) -> Result<()> { - Ok(value.serialize(&mut Serializer::new(write))?) -} diff --git a/implementations/rust/preserves/src/set.rs b/implementations/rust/preserves/src/set.rs deleted file mode 100644 index 001ab51..0000000 --- a/implementations/rust/preserves/src/set.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! Serde support for serializing Rust collections as Preserves sets. -//! -//! Serde doesn't include sets in its data model, so we do some somewhat awful tricks to force -//! things to come out the way we want them. -//! -//! # Example -//! -//! Annotate collection-valued fields that you want to (en|de)code as Preserves `Set`s with -//! `#[serde(with = "preserves::set")]`: -//! -//! ```rust -//! #[derive(serde::Serialize, serde::Deserialize)] -//! struct Example { -//! #[serde(with = "preserves::set")] -//! items: preserves::value::Set, -//! } -//! ``` - -use crate::value::{self, to_value, IOValue, UnwrappedIOValue}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::iter::IntoIterator; - -#[doc(hidden)] -pub fn serialize(s: T, serializer: S) -> Result -where - S: Serializer, - T: IntoIterator, - Item: Serialize, -{ - let s = s.into_iter().map(to_value).collect::>(); - UnwrappedIOValue::from(s).wrap().serialize(serializer) -} - -#[doc(hidden)] -pub fn deserialize<'de, D, T>(deserializer: D) -> Result -where - D: Deserializer<'de>, - T: Deserialize<'de>, -{ - // Relies on the way we hack around serde's data model in de.rs and value/de.rs. - T::deserialize(deserializer) -} diff --git a/implementations/rust/preserves/src/symbol.rs b/implementations/rust/preserves/src/symbol.rs deleted file mode 100644 index b275256..0000000 --- a/implementations/rust/preserves/src/symbol.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Serde support for serializing Rust data as Preserves symbols. -//! -//! Serde doesn't include symbols in its data model, so we do some somewhat awful tricks to -//! force things to come out the way we want them. -//! -//! # Example -//! -//! Either use [Symbol] directly in your data types, or annotate [String]-valued fields that -//! you want to (en|de)code as Preserves `Symbol`s with `#[serde(with = "preserves::symbol")]`: -//! -//! ```rust -//! #[derive(serde::Serialize, serde::Deserialize)] -//! struct Example { -//! sym1: preserves::symbol::Symbol, -//! #[serde(with = "preserves::symbol")] -//! sym2: String, -//! } -//! ``` - -use crate::value::{IOValue, NestedValue}; - -/// Wrapper for a string to coerce its Preserves-serialization to `Symbol`. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub struct Symbol(pub String); - -impl serde::Serialize for Symbol { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - IOValue::symbol(&self.0).serialize(serializer) - } -} - -impl<'de> serde::Deserialize<'de> for Symbol { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let v = IOValue::deserialize(deserializer)?; - let s = v - .value() - .as_symbol() - .ok_or_else(|| serde::de::Error::custom("Expected symbol"))?; - Ok(Symbol(s.clone())) - } -} - -#[doc(hidden)] -pub fn serialize(s: &str, serializer: S) -> Result -where - S: serde::Serializer, -{ - use serde::Serialize; - Symbol(s.to_string()).serialize(serializer) -} - -#[doc(hidden)] -pub fn deserialize<'de, D>(deserializer: D) -> Result -where - D: serde::Deserializer<'de>, -{ - use serde::Deserialize; - Symbol::deserialize(deserializer).map(|v| v.0) -} diff --git a/implementations/rust/preserves/src/value/boundary.rs b/implementations/rust/preserves/src/value/boundary.rs deleted file mode 100644 index 24f7f77..0000000 --- a/implementations/rust/preserves/src/value/boundary.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![doc(hidden)] - -#[derive(Default, Clone, Debug)] -pub struct Type { - pub closing: Option, - pub opening: Option, -} - -#[derive(Clone, Debug)] -pub enum Item { - Annotation, - AnnotatedValue, - DictionaryKey, - DictionaryValue, - RecordField, - RecordLabel, - SequenceValue, - SetValue, -} - -impl Type { - #[inline] - pub fn shift(&mut self, i: Option) { - let tmp = std::mem::replace(&mut self.opening, i); - self.closing = tmp; - } -} - -pub fn start(i: Item) -> Type { - Type { - closing: None, - opening: Some(i), - } -} - -pub fn mid(c: Item, o: Item) -> Type { - Type { - closing: Some(c), - opening: Some(o), - } -} - -pub fn end(i: Item) -> Type { - Type { - closing: Some(i), - opening: None, - } -} diff --git a/implementations/rust/preserves/src/value/de.rs b/implementations/rust/preserves/src/value/de.rs deleted file mode 100644 index 27e2655..0000000 --- a/implementations/rust/preserves/src/value/de.rs +++ /dev/null @@ -1,465 +0,0 @@ -//! Support Serde deserialization of Rust data types from Preserves *values* (not syntax). - -use crate::error::{Error, ExpectedKind, Received}; -use crate::value::repr::Double; -use crate::value::{IOValue, Map, NestedValue, UnwrappedIOValue, Value}; -use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor}; -use serde::Deserialize; -use std::iter::Iterator; - -pub type Result = std::result::Result; - -/// Serde deserializer for constructing Rust data from an in-memory Preserves value. Use -/// [Deserializer::from_value] to construct instances, or [from_value] to deserialize single -/// values directly. -pub struct Deserializer<'de> { - input: &'de IOValue, -} - -/// Deserialize a `T` from `v`, a Preserves [IOValue]. -pub fn from_value<'a, T>(v: &'a IOValue) -> Result -where - T: Deserialize<'a>, -{ - let mut de = Deserializer::from_value(v); - let t = T::deserialize(&mut de)?; - Ok(t) -} - -impl<'de> Deserializer<'de> { - /// Construct a Deserializer from `v`, an [IOValue]. - pub fn from_value(v: &'de IOValue) -> Self { - Deserializer { input: v } - } - - fn check<'a, T, F>(&'a mut self, f: F, k: ExpectedKind) -> Result - where - F: FnOnce(&'de UnwrappedIOValue) -> Option, - { - f(self.input.value()).ok_or_else(|| { - Error::Expected(k, Received::ReceivedOtherValue(format!("{:?}", self.input))) - }) - } -} - -impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut Deserializer<'de> { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let v = self.input.value(); - match v { - Value::Boolean(b) => visitor.visit_bool(*b), - Value::Double(Double(d)) => visitor.visit_f64(*d), - Value::String(ref s) => visitor.visit_str(&s), - Value::ByteString(_) => self.deserialize_bytes(visitor), - Value::Record(_) => { - if v.is_simple_record("tuple", Some(0)) { - self.deserialize_unit(visitor) - } else if v.is_simple_record("UnicodeScalar", Some(1)) { - self.deserialize_char(visitor) - } else if v.is_simple_record("None", Some(0)) || v.is_simple_record("Some", Some(1)) - { - self.deserialize_option(visitor) - } else if v.is_simple_record("tuple", None) { - visitor.visit_seq(VecSeq::new( - self, - v.as_simple_record("tuple", None).unwrap().iter(), - )) - } else { - Err(Error::CannotDeserializeAny) - } - } - Value::Sequence(ref v) => visitor.visit_seq(VecSeq::new(self, v.iter())), - Value::Dictionary(ref d) => visitor.visit_map(DictMap::new(self, d)), - _ => match v.as_i64() { - Some(i) => visitor.visit_i64(i), - None => match v.as_u64() { - Some(u) => visitor.visit_u64(u), - None => match v.as_signedinteger() { - Some(n) => Err(Error::NumberOutOfRange(n.into())), - None => Err(Error::CannotDeserializeAny), - }, - }, - }, - } - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_bool(self.input.value().to_boolean()?) - } - - fn deserialize_i8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i8(self.input.value().to_i8()?) - } - - fn deserialize_i16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i16(self.input.value().to_i16()?) - } - - fn deserialize_i32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i32(self.input.value().to_i32()?) - } - - fn deserialize_i64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i64(self.input.value().to_i64()?) - } - - fn deserialize_u8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u8(self.input.value().to_u8()?) - } - - fn deserialize_u16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u16(self.input.value().to_u16()?) - } - - fn deserialize_u32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u32(self.input.value().to_u32()?) - } - - fn deserialize_u64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u64(self.input.value().to_u64()?) - } - - fn deserialize_f32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_f32(self.input.value().to_f64()? as f32) - } - - fn deserialize_f64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_f64(self.input.value().to_f64()?) - } - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_char(self.input.value().to_char()?) - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let s: &'de str = &self.input.value().to_string()?; - visitor.visit_borrowed_str(s) - } - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_str(visitor) - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let bs: &'de [u8] = &self.input.value().to_bytestring()?; - visitor.visit_borrowed_bytes(bs) - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_byte_buf(self.input.value().to_bytestring()?.clone()) - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.input.value().to_option()? { - None => visitor.visit_none(), - Some(v) => { - self.input = v; - visitor.visit_some(self) - } - } - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let _fs = self.input.value().to_simple_record("tuple", Some(0))?; - visitor.visit_unit() - } - - fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result - where - V: Visitor<'de>, - { - let _fs = self.input.value().to_simple_record(name, Some(0))?; - visitor.visit_unit() - } - - fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result - where - V: Visitor<'de>, - { - match super::magic::transmit_input_value(name, || Ok(self.input.clone()))? { - Some(v) => visitor.visit_u64(v), - None => { - let fs = self.input.value().to_simple_record(name, Some(1))?; - self.input = &fs[0]; - visitor.visit_newtype_struct(self) - } - } - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.input.value().as_sequence() { - Some(vs) => visitor.visit_seq(VecSeq::new(self, vs.iter())), - None => { - // Hack around serde's model: Deserialize *sets* as - // sequences, too, and reconstruct them as Rust Sets - // on the visitor side. - visitor.visit_seq(VecSeq::new(self, self.input.value().to_set()?.iter())) - } - } - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - let fs = self.input.value().to_simple_record("tuple", Some(len))?; - visitor.visit_seq(VecSeq::new(self, fs.iter())) - } - - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let fs = self.input.value().to_simple_record(name, Some(len))?; - visitor.visit_seq(VecSeq::new(self, fs.iter())) - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let d = self.input.value().to_dictionary()?; - visitor.visit_map(DictMap::new(self, d)) - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let fs = self - .input - .value() - .to_simple_record(name, Some(fields.len()))?; - visitor.visit_seq(VecSeq::new(self, fs.iter())) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - visitor.visit_enum(self) - } - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_str(&self.input.value().to_symbol()?) - } - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_none() - } -} - -#[doc(hidden)] -pub struct VecSeq<'a, 'de: 'a, I: Iterator> { - iter: I, - de: &'a mut Deserializer<'de>, -} - -impl<'de, 'a, I: Iterator> VecSeq<'a, 'de, I> { - fn new(de: &'a mut Deserializer<'de>, iter: I) -> Self { - VecSeq { iter, de } - } -} - -impl<'de, 'a, I: Iterator> SeqAccess<'de> for VecSeq<'a, 'de, I> { - type Error = Error; - - fn next_element_seed(&mut self, seed: T) -> Result> - where - T: DeserializeSeed<'de>, - { - match self.iter.next() { - None => Ok(None), - Some(v) => { - self.de.input = v; - Ok(Some(seed.deserialize(&mut *self.de)?)) - } - } - } -} - -#[doc(hidden)] -pub struct DictMap<'a, 'de: 'a> { - pending: Option<&'de IOValue>, - iter: Box + 'a>, - de: &'a mut Deserializer<'de>, -} - -impl<'de, 'a> DictMap<'a, 'de> { - fn new(de: &'a mut Deserializer<'de>, d: &'de Map) -> Self { - DictMap { - pending: None, - iter: Box::new(d.iter()), - de, - } - } -} - -impl<'de, 'a> MapAccess<'de> for DictMap<'a, 'de> { - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> Result> - where - K: DeserializeSeed<'de>, - { - match self.iter.next() { - None => Ok(None), - Some((k, v)) => { - self.pending = Some(v); - self.de.input = k; - Ok(Some(seed.deserialize(&mut *self.de)?)) - } - } - } - - fn next_value_seed(&mut self, seed: V) -> Result - where - V: DeserializeSeed<'de>, - { - let v = self.pending.unwrap(); - self.pending = None; - self.de.input = v; - Ok(seed.deserialize(&mut *self.de)?) - } -} - -impl<'a, 'de> EnumAccess<'de> for &'a mut Deserializer<'de> { - type Error = Error; - type Variant = Self; - - fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> - where - V: DeserializeSeed<'de>, - { - let r = self.check(|v| v.as_record(None), ExpectedKind::Record(None))?; - let v = self.input; - self.input = r.label(); - let variant = seed.deserialize(&mut *self)?; - self.input = v; - Ok((variant, self)) - } -} - -impl<'a, 'de> VariantAccess<'de> for &'a mut Deserializer<'de> { - type Error = Error; - - fn unit_variant(self) -> Result<()> { - Ok(()) - } - - fn newtype_variant_seed(self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - let r = self.check(|v| v.as_record(Some(1)), ExpectedKind::Record(Some(1)))?; - self.input = &r.fields()[0]; - seed.deserialize(&mut *self) - } - - fn tuple_variant(self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_seq(VecSeq::new( - self, - self.input.value().as_record(None).unwrap().fields().iter(), - )) - } - - fn struct_variant(self, fields: &'static [&'static str], visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_seq(VecSeq::new( - self, - self.input - .value() - .as_record(Some(fields.len())) - .unwrap() - .fields() - .iter(), - )) - } -} diff --git a/implementations/rust/preserves/src/value/domain.rs b/implementations/rust/preserves/src/value/domain.rs deleted file mode 100644 index 1374c2e..0000000 --- a/implementations/rust/preserves/src/value/domain.rs +++ /dev/null @@ -1,148 +0,0 @@ -//! Traits for working with Preserves [embedded -//! values](https://preserves.dev/preserves.html#embeddeds). - -use std::io; - -use super::packed; -use super::BinarySource; -use super::BytesBinarySource; -use super::Embeddable; -use super::IOValue; -use super::NestedValue; -use super::Reader; -use super::Writer; - -/// Implementations parse [IOValue]s to their own particular [Embeddable] values of type `D`. -pub trait DomainParse { - fn parse_embedded(&mut self, v: &IOValue) -> io::Result; -} - -/// Implementations read and parse from `src` to produce [Embeddable] values of type `D`. -pub trait DomainDecode { - fn decode_embedded<'de, 'src, S: BinarySource<'de>>( - &mut self, - src: &'src mut S, - read_annotations: bool, - ) -> io::Result; -} - -/// Implementations unparse and write `D`s to `w`, a [writer][crate::value::writer::Writer]. -pub trait DomainEncode { - fn encode_embedded(&mut self, w: &mut W, d: &D) -> io::Result<()>; -} - -impl<'a, D: Embeddable, T: DomainParse> DomainParse for &'a mut T { - fn parse_embedded(&mut self, v: &IOValue) -> io::Result { - (**self).parse_embedded(v) - } -} - -impl<'a, D: Embeddable, T: DomainDecode> DomainDecode for &'a mut T { - fn decode_embedded<'de, 'src, S: BinarySource<'de>>( - &mut self, - src: &'src mut S, - read_annotations: bool, - ) -> io::Result { - (**self).decode_embedded(src, read_annotations) - } -} - -/// Convenience codec: use this as embedded codec for encoding (only) when embedded values -/// should be serialized as Preserves `String`s holding their Rust [std::fmt::Debug] -/// representation. -pub struct DebugDomainEncode; - -impl DomainEncode for DebugDomainEncode { - fn encode_embedded(&mut self, w: &mut W, d: &D) -> io::Result<()> { - d.debug_encode(w) - } -} - -/// Convenience codec: use this as embedded codec for decoding (only) when embedded values are -/// expected to conform to the syntax implicit in their [std::str::FromStr] implementation. -pub struct FromStrDomainParse; - -impl, D: Embeddable + std::str::FromStr> DomainParse - for FromStrDomainParse -{ - fn parse_embedded(&mut self, v: &IOValue) -> io::Result { - Ok(D::from_str(v.value().to_string()?).map_err(|e| e.into())?) - } -} - -/// Use this as embedded codec when embedded data are already [IOValue]s that can be directly -/// serialized and deserialized without further transformation. -pub struct IOValueDomainCodec; - -impl DomainDecode for IOValueDomainCodec { - fn decode_embedded<'de, 'src, S: BinarySource<'de>>( - &mut self, - src: &'src mut S, - read_annotations: bool, - ) -> io::Result { - packed::PackedReader::new(src, IOValueDomainCodec).demand_next(read_annotations) - } -} - -impl DomainEncode for IOValueDomainCodec { - fn encode_embedded(&mut self, w: &mut W, d: &IOValue) -> io::Result<()> { - w.write(self, d) - } -} - -/// Use this as embedded codec to forbid use of embedded values; an [io::Error] is signalled. -pub struct NoEmbeddedDomainCodec; - -impl DomainDecode for NoEmbeddedDomainCodec { - fn decode_embedded<'de, 'src, S: BinarySource<'de>>( - &mut self, - _src: &'src mut S, - _read_annotations: bool, - ) -> io::Result { - Err(io::Error::new( - io::ErrorKind::Unsupported, - "Embedded values not supported here", - )) - } -} - -impl DomainEncode for NoEmbeddedDomainCodec { - fn encode_embedded(&mut self, _w: &mut W, _d: &D) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Unsupported, - "Embedded values not supported here", - )) - } -} - -/// If some `C` implements [DomainDecode] but not [DomainParse], or vice versa, use `ViaCodec` -/// to promote the one to the other. Construct instances with [ViaCodec::new]. -pub struct ViaCodec(C); - -impl ViaCodec { - /// Constructs a `ViaCodec` wrapper around an underlying codec of type `C`. - pub fn new(c: C) -> Self { - ViaCodec(c) - } -} - -impl> DomainParse for ViaCodec { - fn parse_embedded(&mut self, v: &IOValue) -> io::Result { - let bs = packed::PackedWriter::encode_iovalue(v)?; - self.0 - .decode_embedded(&mut BytesBinarySource::new(&bs), true) - } -} - -impl> DomainDecode for ViaCodec { - fn decode_embedded<'de, 'src, S: BinarySource<'de>>( - &mut self, - src: &'src mut S, - read_annotations: bool, - ) -> io::Result { - let v = src - .packed(IOValueDomainCodec) - .demand_next(read_annotations)?; - self.0.parse_embedded(&v) - } -} diff --git a/implementations/rust/preserves/src/value/magic.rs b/implementations/rust/preserves/src/value/magic.rs deleted file mode 100644 index 966e343..0000000 --- a/implementations/rust/preserves/src/value/magic.rs +++ /dev/null @@ -1,64 +0,0 @@ -#![doc(hidden)] - -//! A horrifying hack to Serde-serialize [IOValue] instances to Preserves *as themselves*. -//! -//! Frankly I think this portion of the codebase might not survive for long. I can't think of a -//! better way of achieving this, but the drawbacks of having this functionality are *severe*. -//! -//! See . - -use super::repr::IOValue; - -pub static MAGIC: &str = "$____Preserves_Serde_Magic"; - -struct IOValueVisitor; -impl<'de> serde::de::Visitor<'de> for IOValueVisitor { - type Value = IOValue; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "a magic encoding of an embedded Preserves Value") - } - fn visit_u64(self, v: u64) -> Result - where - E: serde::de::Error, - { - let b = unsafe { Box::from_raw(v as *mut IOValue) }; - Ok(*b) - } -} - -#[inline(always)] -pub fn output_value(serializer: S, v: IOValue) -> Result { - serializer.serialize_newtype_struct(MAGIC, &(Box::into_raw(Box::new(v)) as u64)) -} - -#[inline(always)] -pub fn input_value<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { - deserializer.deserialize_newtype_struct(MAGIC, IOValueVisitor) -} - -//--------------------------------------------------------------------------- - -#[inline] -pub fn receive_output_value(name: &'static str, magic_value: &T) -> Option { - if name == MAGIC { - let b = - unsafe { Box::from_raw(*((magic_value as *const T) as *const u64) as *mut IOValue) }; - let v: IOValue = *b; - Some(v) - } else { - None - } -} - -#[inline] -pub fn transmit_input_value(name: &'static str, f: F) -> Result, crate::error::Error> -where - F: FnOnce() -> Result, -{ - if name == MAGIC { - let b: Box = Box::new(f()?); - Ok(Some(Box::into_raw(b) as u64)) - } else { - Ok(None) - } -} diff --git a/implementations/rust/preserves/src/value/merge.rs b/implementations/rust/preserves/src/value/merge.rs deleted file mode 100644 index 3243be3..0000000 --- a/implementations/rust/preserves/src/value/merge.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Implements the Preserves -//! [merge](https://preserves.dev/preserves.html#appendix-merging-values) of values. - -use super::Map; -use super::NestedValue; -use super::Record; -use super::Value; - -/// Merge two sequences of values according to [the -/// specification](https://preserves.dev/preserves.html#appendix-merging-values). -pub fn merge_seqs(mut a: Vec, mut b: Vec) -> Option> { - if a.len() > b.len() { - std::mem::swap(&mut a, &mut b); - } - let mut r = vec![]; - let mut bi = b.into_iter(); - for av in a.into_iter() { - r.push(merge2(av, bi.next().unwrap())?); - } - r.extend(bi); - Some(r) -} - -/// Merge two values according to [the -/// specification](https://preserves.dev/preserves.html#appendix-merging-values). -pub fn merge2(v: N, w: N) -> Option { - let (mut v_anns, v_val) = v.pieces(); - let (w_anns, w_val) = w.pieces(); - v_anns.modify(|anns| anns.extend(w_anns.to_vec().into_iter())); - if v_val == w_val { - Some(N::wrap(v_anns, v_val)) - } else { - let maybe_merged = match v_val { - Value::Record(rv) => Some(Value::Record(Record(merge_seqs( - rv.0, - w_val.into_record()?.0, - )?))), - Value::Sequence(vs) => Some(Value::Sequence(merge_seqs(vs, w_val.into_sequence()?)?)), - Value::Set(_vs) => None, // unsure how to merge sets - Value::Dictionary(vs) => { - let mut ws = w_val.into_dictionary()?; - let mut rs = Map::new(); - for (k, vv) in vs.into_iter() { - match ws.remove(&k) { - Some(wv) => { - rs.insert(k, merge2(vv, wv)?); - } - None => { - rs.insert(k, vv); - } - } - } - rs.extend(ws.into_iter()); - Some(Value::Dictionary(rs)) - } - _ => None, - }; - maybe_merged.map(|vw| N::wrap(v_anns, vw)) - } -} - -/// Merge several values into a single value according to [the -/// specification](https://preserves.dev/preserves.html#appendix-merging-values). -pub fn merge>(vs: I) -> Option { - let mut vs = vs.into_iter(); - let mut v = vs.next().expect("at least one value in merge()"); - for w in vs { - match merge2(v, w) { - Some(merged) => v = merged, - None => return None, - } - } - Some(v) -} diff --git a/implementations/rust/preserves/src/value/mod.rs b/implementations/rust/preserves/src/value/mod.rs deleted file mode 100644 index f9fd867..0000000 --- a/implementations/rust/preserves/src/value/mod.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! # Representing, reading, and writing Preserves `Value`s as Rust data -//! -//! ``` -//! use preserves::value::{IOValue, text, packed}; -//! let v: IOValue = text::iovalue_from_str("")?; -//! let w: IOValue = packed::iovalue_from_bytes(b"\xb4\xb3\x02hi\x84")?; -//! assert_eq!(v, w); -//! assert_eq!(text::TextWriter::encode_iovalue(&v)?, ""); -//! assert_eq!(packed::PackedWriter::encode_iovalue(&v)?, b"\xb4\xb3\x02hi\x84"); -//! # Ok::<(), std::io::Error>(()) -//! ``` -//! -//! Preserves `Value`s are categorized in the following way. The core representation type, -//! [crate::value::repr::Value], reflects this structure. However, most of the time you will -//! work with [IOValue] or some other implementation of trait [NestedValue], which augments an -//! underlying [Value] with [*annotations*][crate::value::repr::Annotations] (e.g. comments) and fixes a strategy -//! for memory management. -//! -#![doc = include_str!("../../doc/value-grammar.md")] -//! -//! ## Memory management -//! -//! Each implementation of [NestedValue] chooses a different point in the space of possible -//! approaches to memory management for `Value`s. -//! -//! ##### `IOValue` -//! -//! The most commonly-used and versatile implementation, [IOValue], uses [std::sync::Arc] for -//! internal links in compound `Value`s. Unlike many of the other implementations of -//! [NestedValue], [IOValue] doesn't offer flexibility in the Rust data type to be used for -//! Preserves [embedded values](https://preserves.dev/preserves.html#embeddeds): instead, -//! embedded values in an [IOValue] are themselves [IOValue]s. -//! -//! ##### `ArcValue`, `RcValue`, and `PlainValue` -//! -//! For control over the Rust type to use for embedded values, choose [ArcValue], [RcValue], or -//! [PlainValue]. Use [ArcValue] when you wish to transfer values among threads. [RcValue] is -//! more niche; it may be useful for complex terms that do not need to cross thread boundaries. -//! [PlainValue] is even more niche: it does not use a reference-counted pointer type, meaning -//! it does not offer any kind of aliasing or sharing among subterms at all. -//! -//! # Parsing, pretty-printing, encoding and decoding `Value`s -//! -//! Modules [reader] and [writer] supply generic [Reader] and [Writer] traits for parsing and -//! unparsing Preserves data. Implementations of [Reader] and [Writer] connect Preserves data -//! to specific transfer syntaxes: -//! -//! - module [packed] supplies tools for working with the machine-oriented binary syntax -//! - module [text] supplies tools for working with human-readable text syntax - -pub mod boundary; -pub mod de; -pub mod domain; -pub mod magic; -pub mod merge; -pub mod packed; -pub mod reader; -pub mod repr; -pub mod ser; -pub mod signed_integer; -pub mod suspendable; -pub mod text; -pub mod writer; - -pub use de::from_value; -pub use de::Deserializer; -pub use domain::DebugDomainEncode; -pub use domain::DomainDecode; -pub use domain::DomainEncode; -pub use domain::DomainParse; -pub use domain::FromStrDomainParse; -pub use domain::IOValueDomainCodec; -pub use domain::NoEmbeddedDomainCodec; -pub use domain::ViaCodec; -pub use merge::merge; -pub use packed::PackedReader; -pub use packed::PackedWriter; -pub use reader::BinarySource; -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::DummyValue; -pub use repr::Embeddable; -pub use repr::IOValue; -pub use repr::Map; -pub use repr::NestedValue; -pub use repr::PlainValue; -pub use repr::RcValue; -pub use repr::Record; -pub use repr::Set; -pub use repr::UnwrappedIOValue; -pub use repr::Value; -pub use repr::ValueClass; -pub use ser::to_value; -pub use ser::Serializer; -pub use text::TextReader; -pub use text::ToplevelWhitespaceMode; -pub use text::TextWriter; -pub use writer::Writer; - -#[doc(hidden)] -pub fn invert_map(m: &Map) -> Map -where - A: Clone, - B: Clone + Ord, -{ - m.iter().map(|(a, b)| (b.clone(), a.clone())).collect() -} diff --git a/implementations/rust/preserves/src/value/packed/constants.rs b/implementations/rust/preserves/src/value/packed/constants.rs deleted file mode 100644 index a9cb44c..0000000 --- a/implementations/rust/preserves/src/value/packed/constants.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! Definitions of the tags used in the binary encoding. - -use std::convert::{From, TryFrom}; -use std::io; - -/// Rust representation of tags used in the binary encoding. -#[derive(Debug, PartialEq, Eq)] -pub enum Tag { - False, - True, - End, - Annotation, - Embedded, - Ieee754, - SignedInteger, - String, - ByteString, - Symbol, - Record, - Sequence, - Set, - Dictionary, -} - -/// Error value representing failure to decode a byte into a [Tag]. -#[derive(Debug, PartialEq, Eq)] -pub struct InvalidTag(pub u8); - -impl From for io::Error { - fn from(v: InvalidTag) -> Self { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Invalid Preserves tag {}", v.0), - ) - } -} - -impl From for crate::error::Error { - fn from(v: InvalidTag) -> Self { - crate::error::Error::Io(v.into()) - } -} - -impl TryFrom for Tag { - type Error = InvalidTag; - fn try_from(v: u8) -> Result { - match v { - 0x80 => Ok(Self::False), - 0x81 => Ok(Self::True), - 0x84 => Ok(Self::End), - 0x85 => Ok(Self::Annotation), - 0x86 => Ok(Self::Embedded), - 0x87 => Ok(Self::Ieee754), - 0xb0 => Ok(Self::SignedInteger), - 0xb1 => Ok(Self::String), - 0xb2 => Ok(Self::ByteString), - 0xb3 => Ok(Self::Symbol), - 0xb4 => Ok(Self::Record), - 0xb5 => Ok(Self::Sequence), - 0xb6 => Ok(Self::Set), - 0xb7 => Ok(Self::Dictionary), - _ => Err(InvalidTag(v)), - } - } -} - -impl From for u8 { - fn from(v: Tag) -> Self { - match v { - Tag::False => 0x80, - Tag::True => 0x81, - Tag::End => 0x84, - Tag::Annotation => 0x85, - Tag::Embedded => 0x86, - Tag::Ieee754 => 0x87, - Tag::SignedInteger => 0xb0, - Tag::String => 0xb1, - Tag::ByteString => 0xb2, - Tag::Symbol => 0xb3, - Tag::Record => 0xb4, - Tag::Sequence => 0xb5, - Tag::Set => 0xb6, - Tag::Dictionary => 0xb7, - } - } -} diff --git a/implementations/rust/preserves/src/value/packed/mod.rs b/implementations/rust/preserves/src/value/packed/mod.rs deleted file mode 100644 index a450e99..0000000 --- a/implementations/rust/preserves/src/value/packed/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Implements the Preserves [machine-oriented binary -//! syntax](https://preserves.dev/preserves-binary.html). -//! -//! The main entry points for reading are functions [iovalue_from_bytes], -//! [annotated_iovalue_from_bytes], [from_bytes], and [annotated_from_bytes]. -//! -//! The main entry points for writing are [PackedWriter::encode_iovalue] and -//! [PackedWriter::encode]. -//! -//! # Summary of Binary Syntax -#![doc = include_str!("../../../doc/cheatsheet-binary-plaintext.md")] - -pub mod constants; -pub mod reader; -pub mod writer; - -pub use reader::PackedReader; -pub use writer::PackedWriter; - -use std::io; - -use super::{BinarySource, DomainDecode, IOValue, IOValueDomainCodec, NestedValue, Reader}; - -/// Reads a value from the given byte vector `bs` using the binary encoding, discarding -/// annotations. -pub fn from_bytes>( - bs: &[u8], - decode_embedded: Dec, -) -> io::Result { - super::BytesBinarySource::new(bs) - .packed(decode_embedded) - .demand_next(false) -} - -/// Reads an [IOValue] from the given byte vector `bs` using the binary encoding, discarding -/// annotations. -pub fn iovalue_from_bytes(bs: &[u8]) -> io::Result { - from_bytes(bs, IOValueDomainCodec) -} - -/// As [from_bytes], but includes annotations. -pub fn annotated_from_bytes>( - bs: &[u8], - decode_embedded: Dec, -) -> io::Result { - super::BytesBinarySource::new(bs) - .packed(decode_embedded) - .demand_next(true) -} - -/// As [iovalue_from_bytes], but includes annotations. -pub fn annotated_iovalue_from_bytes(bs: &[u8]) -> io::Result { - annotated_from_bytes(bs, IOValueDomainCodec) -} diff --git a/implementations/rust/preserves/src/value/packed/reader.rs b/implementations/rust/preserves/src/value/packed/reader.rs deleted file mode 100644 index a7ab086..0000000 --- a/implementations/rust/preserves/src/value/packed/reader.rs +++ /dev/null @@ -1,616 +0,0 @@ -//! Implementation of [Reader] for the binary encoding. - -use crate::error::{self, io_syntax_error, is_eof_io_error, ExpectedKind, Received}; - -use num::bigint::BigInt; -use num::traits::cast::{FromPrimitive, ToPrimitive}; - -use std::borrow::Cow; -use std::convert::TryFrom; -use std::convert::TryInto; -use std::io; -use std::marker::PhantomData; - -use super::super::{ - boundary as B, - reader::{BinarySource, Reader, ReaderResult, Token}, - repr::Annotations, - signed_integer::SignedInteger, - CompoundClass, DomainDecode, Map, NestedValue, Record, Set, Value, -}; -use super::constants::Tag; - -/// The binary encoding Preserves reader. -pub struct PackedReader< - 'de, - 'src, - N: NestedValue, - Dec: DomainDecode, - S: BinarySource<'de>, -> { - /// Underlying source of bytes. - pub source: &'src mut S, - /// Decoder for producing Rust values embedded in the binary data. - pub decode_embedded: Dec, - phantom: PhantomData<&'de N>, -} - -impl<'de, 'src, N: NestedValue, Dec: DomainDecode, S: BinarySource<'de>> - BinarySource<'de> for PackedReader<'de, 'src, N, Dec, S> -{ - type Mark = S::Mark; - #[inline(always)] - fn mark(&mut self) -> io::Result { - self.source.mark() - } - #[inline(always)] - fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { - self.source.restore(mark) - } - #[inline(always)] - fn skip(&mut self) -> io::Result<()> { - self.source.skip() - } - #[inline(always)] - fn peek(&mut self) -> io::Result { - self.source.peek() - } - #[inline(always)] - fn readbytes(&mut self, count: usize) -> io::Result> { - self.source.readbytes(count) - } - #[inline(always)] - fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()> { - self.source.readbytes_into(bs) - } -} - -fn out_of_range>(i: I) -> error::Error { - error::Error::NumberOutOfRange(i.into()) -} - -impl<'de, 'src, N: NestedValue, Dec: DomainDecode, S: BinarySource<'de>> - PackedReader<'de, 'src, N, Dec, S> -{ - /// Construct a new reader from a byte source and embedded-value decoder. - #[inline(always)] - pub fn new(source: &'src mut S, decode_embedded: Dec) -> Self { - PackedReader { - source, - decode_embedded, - phantom: PhantomData, - } - } - - #[inline(always)] - fn read(&mut self) -> io::Result { - let v = self.peek()?; - self.skip()?; - Ok(v) - } - - fn expected(&mut self, k: ExpectedKind) -> error::Error { - match self.demand_next(true) { - Ok(v) => error::Error::Expected(k, Received::ReceivedOtherValue(format!("{:?}", v))), - Err(e) => e.into(), - } - } - - #[inline(always)] - fn varint(&mut self) -> io::Result { - let mut shift = 0; - let mut acc: usize = 0; - loop { - let v = self.read()?; - acc |= ((v & 0x7f) as usize) << shift; - shift += 7; - if v & 0x80 == 0 { - return Ok(acc); - } - } - } - - #[inline(always)] - fn peekend(&mut self) -> io::Result { - if self.peek()? == Tag::End.into() { - self.skip()?; - Ok(true) - } else { - Ok(false) - } - } - - #[inline(always)] - fn try_next_nonannotation(&mut self, f: F) -> ReaderResult - where - F: FnOnce(&mut Self, Tag) -> ReaderResult, - { - let m = self.source.mark()?; - loop { - match Tag::try_from(self.peek()?)? { - Tag::Annotation => { - self.skip()?; - self.skip_value()?; - } - tag => match f(self, tag) { - Ok(v) => return Ok(v), - Err(e) => { - self.source.restore(&m)?; - return Err(e); - } - } - } - } - } - - fn next_atomic(&mut self, expected_tag: Tag, k: ExpectedKind) -> ReaderResult> { - self.try_next_nonannotation(|r, actual_tag| { - if actual_tag == expected_tag { - r.skip()?; - let count = r.varint()?; - Ok(r.readbytes(count)?) - } else { - Err(r.expected(k)) - } - }) - } - - fn next_compound(&mut self, expected_tag: Tag, k: ExpectedKind) -> ReaderResult<()> { - self.try_next_nonannotation(|r, actual_tag| { - if actual_tag == expected_tag { - r.skip()?; - Ok(()) - } else { - Err(r.expected(k)) - } - }) - } - - #[inline(always)] - fn read_signed_integer(&mut self, count: usize) -> io::Result { - if count == 0 { - return Ok(SignedInteger::from(0_i128)); - } - - if count > 16 { - let bs = self.readbytes(count)?; - if (bs[0] & 0x80) == 0 { - // Positive or zero. - let mut i = 0; - while i < count && bs[i] == 0 { - i += 1; - } - if count - i <= 16 { - Ok(SignedInteger::from(u128::from_be_bytes( - bs[bs.len() - 16..].try_into().unwrap(), - ))) - } else { - Ok(SignedInteger::from(Cow::Owned(BigInt::from_bytes_be( - num::bigint::Sign::Plus, - &bs[i..], - )))) - } - } else { - // Negative. - let mut i = 0; - while i < count && bs[i] == 0xff { - i += 1; - } - if count - i <= 16 { - Ok(SignedInteger::from(i128::from_be_bytes( - bs[bs.len() - 16..].try_into().unwrap(), - ))) - } else { - Ok(SignedInteger::from(Cow::Owned( - BigInt::from_signed_bytes_be(&bs), - ))) - } - } - } else { - let first_byte = self.read()?; - let prefix_byte = if (first_byte & 0x80) == 0 { 0x00 } else { 0xff }; - let mut bs = [prefix_byte; 16]; - bs[16 - count] = first_byte; - self.readbytes_into(&mut bs[16 - (count - 1)..])?; - Ok(SignedInteger::from(i128::from_be_bytes(bs))) - } - } - - #[inline(always)] - fn next_unsigned(&mut self, f: F) -> ReaderResult - where - F: FnOnce(u128) -> Option, - { - self.try_next_nonannotation(|r, tag| { - match tag { - Tag::SignedInteger => { - r.skip()?; - let count = r.varint()?; - let n = &r.read_signed_integer(count)?; - let i = n.try_into().map_err(|_| out_of_range(n))?; - f(i).ok_or_else(|| out_of_range(i)) - } - _ => Err(r.expected(ExpectedKind::SignedInteger)), - } - }) - } - - #[inline(always)] - fn next_signed(&mut self, f: F) -> ReaderResult - where - F: FnOnce(i128) -> Option, - { - self.try_next_nonannotation(|r, tag| { - match tag { - Tag::SignedInteger => { - r.skip()?; - let count = r.varint()?; - let n = &r.read_signed_integer(count)?; - let i = n.try_into().map_err(|_| out_of_range(n))?; - f(i).ok_or_else(|| out_of_range(i)) - } - _ => Err(r.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(()) - } - - fn next_upto_end(&mut self, read_annotations: bool) -> io::Result> { - match self.peekend()? { - true => Ok(None), - false => Ok(Some(self.demand_next(read_annotations)?)), - } - } -} - -impl<'de, 'src, N: NestedValue, Dec: DomainDecode, S: BinarySource<'de>> Reader<'de, N> - for PackedReader<'de, 'src, N, Dec, S> -{ - fn next(&mut self, read_annotations: bool) -> io::Result> { - match self.peek() { - Err(e) if is_eof_io_error(&e) => return Ok(None), - Err(e) => return Err(e), - Ok(_) => (), - } - Ok(Some(match Tag::try_from(self.read()?)? { - Tag::False => N::new(false), - Tag::True => N::new(true), - Tag::Annotation => { - if 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_annotations()?; - self.demand_next(read_annotations)? - } - } - Tag::Embedded => Value::Embedded( - self.decode_embedded - .decode_embedded(self.source, read_annotations)?, - ).wrap(), - Tag::Ieee754 => match self.varint()? { - 8 => { - let mut bs = [0; 8]; - self.readbytes_into(&mut bs)?; - Value::from(f64::from_bits(u64::from_be_bytes(bs))).wrap() - } - _ => return Err(io_syntax_error("Invalid IEEE754 size")) - } - Tag::SignedInteger => { - let count = self.varint()?; - let n = self.read_signed_integer(count)?; - Value::SignedInteger(n).wrap() - } - Tag::String => { - let count = self.varint()?; - Value::String(decodestr(self.readbytes(count)?)?.into_owned()).wrap() - } - Tag::ByteString => { - let count = self.varint()?; - Value::ByteString(self.readbytes(count)?.into_owned()).wrap() - } - Tag::Symbol => { - let count = self.varint()?; - Value::Symbol(decodestr(self.readbytes(count)?)?.into_owned()).wrap() - } - Tag::Record => { - let mut vs = Vec::new(); - while let Some(v) = self.next_upto_end(read_annotations)? { - vs.push(v); - } - if vs.is_empty() { - return Err(io_syntax_error("Too few elements in encoded record")); - } - Value::Record(Record(vs)).wrap() - } - Tag::Sequence => { - let mut vs = Vec::new(); - while let Some(v) = self.next_upto_end(read_annotations)? { - vs.push(v); - } - Value::Sequence(vs).wrap() - } - Tag::Set => { - let mut s = Set::new(); - while let Some(v) = self.next_upto_end(read_annotations)? { - s.insert(v); - } - Value::Set(s).wrap() - } - Tag::Dictionary => { - let mut d = Map::new(); - while let Some(k) = self.next_upto_end(read_annotations)? { - match self.next_upto_end(read_annotations)? { - Some(v) => { - d.insert(k, v); - } - None => return Err(io_syntax_error("Missing dictionary value")), - } - } - Value::Dictionary(d).wrap() - } - tag @ Tag::End => { - return Err(io_syntax_error(&format!("Invalid tag: {:?}", tag))); - } - })) - } - - #[inline(always)] - fn open_record(&mut self, arity: Option) -> ReaderResult { - self.next_compound(Tag::Record, ExpectedKind::Record(arity))?; - let mut b = B::Type::default(); - self.ensure_more_expected(&mut b, &B::Item::RecordLabel)?; - Ok(b) - } - - #[inline(always)] - fn open_sequence_or_set(&mut self) -> ReaderResult { - self.try_next_nonannotation(|r, tag| { - match tag { - Tag::Sequence => { - r.skip()?; - Ok(B::Item::SequenceValue) - } - Tag::Set => { - r.skip()?; - Ok(B::Item::SetValue) - } - _ => Err(r.expected(ExpectedKind::SequenceOrSet)), - } - }) - } - - #[inline(always)] - fn open_sequence(&mut self) -> ReaderResult<()> { - self.next_compound(Tag::Sequence, ExpectedKind::Sequence) - } - - #[inline(always)] - fn open_set(&mut self) -> ReaderResult<()> { - self.next_compound(Tag::Set, ExpectedKind::Set) - } - - #[inline(always)] - fn open_dictionary(&mut self) -> ReaderResult<()> { - self.next_compound(Tag::Dictionary, ExpectedKind::Dictionary) - } - - #[inline(always)] - fn boundary(&mut self, _b: &B::Type) -> ReaderResult<()> { - Ok(()) - } - - #[inline(always)] - fn close_compound(&mut self, _b: &mut B::Type, _i: &B::Item) -> ReaderResult { - Ok(self.peekend()?) - } - - #[inline(always)] - fn open_embedded(&mut self) -> ReaderResult<()> { - self.next_compound(Tag::Embedded, ExpectedKind::Embedded) - } - - #[inline(always)] - fn close_embedded(&mut self) -> ReaderResult<()> { - Ok(()) - } - - type Mark = S::Mark; - - #[inline(always)] - fn mark(&mut self) -> io::Result { - self.source.mark() - } - - #[inline(always)] - 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::Ieee754 - | 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_value()?; - 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)?)), - } - } - - #[inline(always)] - fn next_boolean(&mut self) -> ReaderResult { - self.try_next_nonannotation(|r, tag| { - match tag { - Tag::False => { - r.skip()?; - Ok(false) - }, - Tag::True => { - r.skip()?; - Ok(true) - }, - _ => Err(r.expected(ExpectedKind::Boolean)), - } - }) - } - - fn next_signedinteger(&mut self) -> ReaderResult { - self.try_next_nonannotation(|r, tag| { - match tag { - Tag::SignedInteger => { - r.skip()?; - let count = r.varint()?; - Ok(r.read_signed_integer(count)?) - } - _ => Err(r.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()) - } - fn next_i64(&mut self) -> ReaderResult { - self.next_signed(|n| n.to_i64()) - } - fn next_i128(&mut self) -> ReaderResult { - self.next_signed(|n| n.to_i128()) - } - - fn next_u8(&mut self) -> ReaderResult { - self.next_unsigned(|n| n.to_u8()) - } - fn next_u16(&mut self) -> ReaderResult { - self.next_unsigned(|n| n.to_u16()) - } - fn next_u32(&mut self) -> ReaderResult { - self.next_unsigned(|n| n.to_u32()) - } - fn next_u64(&mut self) -> ReaderResult { - self.next_unsigned(|n| n.to_u64()) - } - fn next_u128(&mut self) -> ReaderResult { - self.next_unsigned(|n| n.to_u128()) - } - - fn next_f64(&mut self) -> ReaderResult { - self.try_next_nonannotation(|r, tag| { - if tag == Tag::Ieee754 { - r.skip()?; - match r.varint()? { - 8 => { - let mut bs = [0; 8]; - r.readbytes_into(&mut bs)?; - Ok(f64::from_bits(u64::from_be_bytes(bs))) - } - _ => Err(io_syntax_error("Invalid IEEE754 size"))?, - } - } else { - Err(r.expected(ExpectedKind::Double)) - } - }) - } - - fn next_str(&mut self) -> ReaderResult> { - Ok(decodestr( - self.next_atomic(Tag::String, ExpectedKind::Symbol)?, - )?) - } - - fn next_bytestring(&mut self) -> ReaderResult> { - self.next_atomic(Tag::ByteString, ExpectedKind::Symbol) - } - - fn next_symbol(&mut self) -> ReaderResult> { - Ok(decodestr( - self.next_atomic(Tag::Symbol, ExpectedKind::Symbol)?, - )?) - } -} - -#[inline(always)] -fn decodestr(cow: Cow<'_, [u8]>) -> io::Result> { - match cow { - Cow::Borrowed(bs) => Ok(Cow::Borrowed( - std::str::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?, - )), - Cow::Owned(bs) => Ok(Cow::Owned( - String::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?, - )), - } -} diff --git a/implementations/rust/preserves/src/value/packed/writer.rs b/implementations/rust/preserves/src/value/packed/writer.rs deleted file mode 100644 index 0509c80..0000000 --- a/implementations/rust/preserves/src/value/packed/writer.rs +++ /dev/null @@ -1,583 +0,0 @@ -//! Implementation of [Writer] for the binary encoding. - -use super::super::boundary as B; -use super::super::suspendable::Suspendable; -use super::super::DomainEncode; -use super::super::IOValue; -use super::super::IOValueDomainCodec; -use super::super::NestedValue; -use super::constants::Tag; -use num::bigint::BigInt; -use num::cast::ToPrimitive; -use std::convert::TryInto; -use std::io; -use std::ops::DerefMut; - -use super::super::writer::{varint, CompoundWriter, Writer}; - -/// The binary encoding Preserves writer. -pub struct PackedWriter(Suspendable); - -impl PackedWriter<&mut Vec> { - /// Encodes `v` to a byte vector. - #[inline(always)] - pub fn encode>( - enc: &mut Enc, - v: &N, - ) -> io::Result> { - let mut buf: Vec = Vec::new(); - PackedWriter::new(&mut buf).write(enc, v)?; - Ok(buf) - } - - /// Encodes `v` to a byte vector. - #[inline(always)] - pub fn encode_iovalue(v: &IOValue) -> io::Result> { - Self::encode(&mut IOValueDomainCodec, v) - } -} - -impl PackedWriter { - /// Construct a writer from the given byte sink `write`. - #[inline(always)] - pub fn new(write: W) -> Self { - PackedWriter(Suspendable::new(write)) - } - - /// Retrieve a mutable reference to the underlying byte sink. - #[inline(always)] - pub fn w(&mut self) -> &mut W { - self.0.deref_mut() - } - - #[doc(hidden)] - #[inline(always)] - pub fn write_byte(&mut self, b: u8) -> io::Result<()> { - self.w().write_all(&[b]) - } - - #[doc(hidden)] - #[inline(always)] - pub fn write_integer(&mut self, bs: &[u8]) -> io::Result<()> { - self.write_atom(Tag::SignedInteger, bs) - } - - #[doc(hidden)] - #[inline(always)] - pub fn write_atom(&mut self, tag: Tag, bs: &[u8]) -> io::Result<()> { - self.write_byte(tag.into())?; - varint(&mut self.w(), bs.len().try_into().unwrap())?; - self.w().write_all(bs) - } - - #[doc(hidden)] - #[inline(always)] - pub fn suspend(&mut self) -> Self { - PackedWriter(self.0.suspend()) - } - - #[doc(hidden)] - #[inline(always)] - pub fn resume(&mut self, other: Self) { - self.0.resume(other.0) - } -} - -#[doc(hidden)] -pub struct BinaryOrderWriter(Vec>); - -impl BinaryOrderWriter { - #[inline(always)] - fn new() -> Self { - BinaryOrderWriter(vec![vec![]]) - } - - #[inline(always)] - fn pop(&mut self) -> PackedWriter> { - PackedWriter::new(self.0.pop().unwrap()) - } - - #[inline(always)] - fn push(&mut self, w: PackedWriter>) { - self.0.push(w.0.take()) - } - - #[inline(always)] - fn items(&self) -> &Vec> { - &self.0 - } - - #[inline(always)] - fn items_mut(&mut self) -> &mut Vec> { - &mut self.0 - } - - #[inline(always)] - fn buffer(&mut self) -> &mut Vec { - self.0.last_mut().unwrap() - } - - #[inline(always)] - fn finish(mut self, w: &mut W) -> io::Result<()> { - if !self.buffer().is_empty() { - panic!("Missing final boundary()"); - } - self.items_mut().pop(); - self.items_mut().sort(); - for bs in self.items() { - w.write_raw_bytes(&bs)?; - } - w.write_tag(Tag::End)?; - Ok(()) - } -} - -#[doc(hidden)] -pub trait WriteWriter: Writer { - fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()>; - - #[inline(always)] - fn write_tag(&mut self, tag: Tag) -> io::Result<()> { - self.write_raw_bytes(&[tag.into()]) - } -} - -impl WriteWriter for PackedWriter { - #[inline(always)] - fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> { - self.w().write_all(v) - } -} - -impl WriteWriter for BinaryOrderWriter { - #[inline(always)] - fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> { - use io::Write; - self.buffer().write_all(v) - } -} - -impl CompoundWriter for PackedWriter { - #[inline(always)] - fn boundary(&mut self, b: &B::Type) -> io::Result<()> { - if let Some(B::Item::Annotation) = b.opening { - self.write_tag(Tag::Annotation)?; - } - Ok(()) - } -} - -impl CompoundWriter for BinaryOrderWriter { - #[inline(always)] - fn boundary(&mut self, b: &B::Type) -> io::Result<()> { - match b.closing { - Some(B::Item::DictionaryValue) - | Some(B::Item::RecordField) - | Some(B::Item::SequenceValue) - | Some(B::Item::SetValue) => self.items_mut().push(vec![]), - _ => (), - } - Ok(()) - } -} - -macro_rules! binary_order_writer_method { - (mut $n:ident ($($argname:ident : $argty:ty),*) -> $retty:ty) => - (#[inline(always)] fn $n (&mut self, $($argname : $argty),*) -> $retty { - (&mut PackedWriter::new(self.buffer())).$n($($argname),*) - }); -} - -impl Writer for BinaryOrderWriter { - type AnnWriter = PackedWriter>; - type RecWriter = PackedWriter>; - type SeqWriter = PackedWriter>; - type SetWriter = BinaryOrderWriter; - type DictWriter = BinaryOrderWriter; - type EmbeddedWriter = PackedWriter>; - - #[inline(always)] - fn start_annotations(&mut self) -> io::Result { - Ok(self.pop()) - } - #[inline(always)] - fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()> { - self.push(ann); - Ok(()) - } - - binary_order_writer_method!(mut write_bool(v: bool) -> io::Result<()>); - - binary_order_writer_method!(mut write_f64(v: f64) -> io::Result<()>); - - binary_order_writer_method!(mut write_i8(v: i8) -> io::Result<()>); - binary_order_writer_method!(mut write_u8(v: u8) -> io::Result<()>); - binary_order_writer_method!(mut write_i16(v: i16) -> io::Result<()>); - binary_order_writer_method!(mut write_u16(v: u16) -> io::Result<()>); - binary_order_writer_method!(mut write_i32(v: i32) -> io::Result<()>); - binary_order_writer_method!(mut write_u32(v: u32) -> io::Result<()>); - binary_order_writer_method!(mut write_i64(v: i64) -> io::Result<()>); - binary_order_writer_method!(mut write_u64(v: u64) -> io::Result<()>); - binary_order_writer_method!(mut write_i128(v: i128) -> io::Result<()>); - binary_order_writer_method!(mut write_u128(v: u128) -> io::Result<()>); - binary_order_writer_method!(mut write_int(v: &BigInt) -> io::Result<()>); - - binary_order_writer_method!(mut write_string(v: &str) -> io::Result<()>); - binary_order_writer_method!(mut write_bytes(v: &[u8]) -> io::Result<()>); - binary_order_writer_method!(mut write_symbol(v: &str) -> io::Result<()>); - - #[inline(always)] - fn start_record(&mut self, _field_count: Option) -> io::Result { - self.write_tag(Tag::Record)?; - Ok(self.pop()) - } - #[inline(always)] - fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> { - self.push(rec); - self.write_tag(Tag::End) - } - - #[inline(always)] - fn start_sequence(&mut self, _item_count: Option) -> io::Result { - self.write_tag(Tag::Sequence)?; - Ok(self.pop()) - } - #[inline(always)] - fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> { - self.push(seq); - self.write_tag(Tag::End) - } - - #[inline(always)] - fn start_set(&mut self, _item_count: Option) -> io::Result { - self.write_tag(Tag::Set)?; - Ok(BinaryOrderWriter::new()) - } - #[inline(always)] - fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> { - set.finish(self) - } - - #[inline(always)] - fn start_dictionary(&mut self, _entry_count: Option) -> io::Result { - self.write_tag(Tag::Dictionary)?; - Ok(BinaryOrderWriter::new()) - } - #[inline(always)] - fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> { - dict.finish(self) - } - - #[inline(always)] - fn start_embedded(&mut self) -> io::Result { - self.write_tag(Tag::Embedded)?; - Ok(self.pop()) - } - #[inline(always)] - fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()> { - self.push(ptr); - Ok(()) - } - - #[inline(always)] - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -macro_rules! fits_in_bytes { - ($v:ident, $limit:literal) => {{ - let bits = $limit * 8 - 1; - $v >= -(1 << bits) && $v < (1 << bits) - }}; -} - -impl Writer for PackedWriter { - type AnnWriter = Self; - type RecWriter = Self; - type SeqWriter = Self; - type SetWriter = BinaryOrderWriter; - type DictWriter = BinaryOrderWriter; - type EmbeddedWriter = Self; - - #[inline(always)] - fn start_annotations(&mut self) -> io::Result { - Ok(self.suspend()) - } - - #[inline(always)] - fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()> { - self.resume(ann); - Ok(()) - } - - #[inline(always)] - fn write_bool(&mut self, v: bool) -> io::Result<()> { - self.write_tag(if v { Tag::True } else { Tag::False }) - } - - #[inline(always)] - fn write_f64(&mut self, v: f64) -> io::Result<()> { - self.write_tag(Tag::Ieee754)?; - self.write_byte(8)?; - self.write_raw_bytes(&u64::to_be_bytes(f64::to_bits(v))) - } - - #[inline(always)] - fn write_i8(&mut self, v: i8) -> io::Result<()> { - if v == 0 { - return self.write_integer(&[]); - } - self.write_integer(&[v as u8]) - } - - #[inline(always)] - fn write_u8(&mut self, v: u8) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i8(w); - } - self.write_integer(&[0, v]) - } - - #[inline(always)] - fn write_i16(&mut self, v: i16) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i8(w); - } - self.write_integer(&[(v >> 8) as u8, (v & 255) as u8]) - } - - #[inline(always)] - fn write_u16(&mut self, v: u16) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i16(w); - } - self.write_integer(&[0, (v >> 8) as u8, (v & 255) as u8]) - } - - #[inline(always)] - fn write_i32(&mut self, v: i32) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i16(w); - } - if fits_in_bytes!(v, 3) { - return self.write_integer(&[(v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8]); - } - self.write_integer(&[ - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]) - } - - #[inline(always)] - fn write_u32(&mut self, v: u32) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i32(w); - } - self.write_integer(&[ - 0, - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]) - } - - #[inline(always)] - fn write_i64(&mut self, v: i64) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i32(w); - } - if fits_in_bytes!(v, 5) { - return self.write_integer(&[ - (v >> 32) as u8, - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]); - } - if fits_in_bytes!(v, 6) { - return self.write_integer(&[ - (v >> 40) as u8, - (v >> 32) as u8, - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]); - } - if fits_in_bytes!(v, 7) { - return self.write_integer(&[ - (v >> 48) as u8, - (v >> 40) as u8, - (v >> 32) as u8, - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]); - } - self.write_integer(&[ - (v >> 56) as u8, - (v >> 48) as u8, - (v >> 40) as u8, - (v >> 32) as u8, - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]) - } - - #[inline(always)] - fn write_u64(&mut self, v: u64) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i64(w); - } - self.write_integer(&[ - 0, - (v >> 56) as u8, - (v >> 48) as u8, - (v >> 40) as u8, - (v >> 32) as u8, - (v >> 24) as u8, - (v >> 16) as u8, - (v >> 8) as u8, - (v & 255) as u8, - ]) - } - - #[inline(always)] - fn write_i128(&mut self, v: i128) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i64(w); - } - let bs: [u8; 16] = v.to_be_bytes(); - if fits_in_bytes!(v, 9) { - return self.write_integer(&bs[7..]); - } - if fits_in_bytes!(v, 10) { - return self.write_integer(&bs[6..]); - } - if fits_in_bytes!(v, 11) { - return self.write_integer(&bs[5..]); - } - if fits_in_bytes!(v, 12) { - return self.write_integer(&bs[4..]); - } - if fits_in_bytes!(v, 13) { - return self.write_integer(&bs[3..]); - } - if fits_in_bytes!(v, 14) { - return self.write_integer(&bs[2..]); - } - if fits_in_bytes!(v, 15) { - return self.write_integer(&bs[1..]); - } - self.write_integer(&bs) - } - - #[inline(always)] - fn write_u128(&mut self, v: u128) -> io::Result<()> { - if let Ok(w) = v.try_into() { - return self.write_i128(w); - } - let bs: [u8; 16] = v.to_be_bytes(); - self.write_tag(Tag::SignedInteger)?; - varint(&mut self.w(), 17)?; - self.write_byte(0)?; - self.write_raw_bytes(&bs) - } - - #[inline(always)] - fn write_int(&mut self, v: &BigInt) -> io::Result<()> { - match v.to_i8() { - Some(n) => self.write_i8(n), - None => match v.to_i128() { - Some(n) => self.write_i128(n), - None => self.write_integer(&v.to_signed_bytes_be()), - }, - } - } - - #[inline(always)] - fn write_string(&mut self, v: &str) -> io::Result<()> { - self.write_atom(Tag::String, v.as_bytes()) - } - - #[inline(always)] - fn write_bytes(&mut self, v: &[u8]) -> io::Result<()> { - self.write_atom(Tag::ByteString, v) - } - - #[inline(always)] - fn write_symbol(&mut self, v: &str) -> io::Result<()> { - self.write_atom(Tag::Symbol, v.as_bytes()) - } - - #[inline(always)] - fn start_record(&mut self, _field_count: Option) -> io::Result { - self.write_tag(Tag::Record)?; - Ok(self.suspend()) - } - - #[inline(always)] - fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> { - self.resume(rec); - self.write_tag(Tag::End) - } - - #[inline(always)] - fn start_sequence(&mut self, _item_count: Option) -> io::Result { - self.write_tag(Tag::Sequence)?; - Ok(self.suspend()) - } - - #[inline(always)] - fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> { - self.resume(seq); - self.write_tag(Tag::End) - } - - #[inline(always)] - fn start_set(&mut self, _item_count: Option) -> io::Result { - self.write_tag(Tag::Set)?; - Ok(BinaryOrderWriter::new()) - } - - #[inline(always)] - fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> { - set.finish(self) - } - - #[inline(always)] - fn start_dictionary(&mut self, _entry_count: Option) -> io::Result { - self.write_tag(Tag::Dictionary)?; - Ok(BinaryOrderWriter::new()) - } - - #[inline(always)] - fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> { - dict.finish(self) - } - - #[inline(always)] - fn start_embedded(&mut self) -> io::Result { - self.write_tag(Tag::Embedded)?; - Ok(self.suspend()) - } - - #[inline(always)] - fn end_embedded(&mut self, ann: Self::EmbeddedWriter) -> io::Result<()> { - self.resume(ann); - Ok(()) - } - - #[inline(always)] - fn flush(&mut self) -> io::Result<()> { - self.0.flush() - } -} diff --git a/implementations/rust/preserves/src/value/reader.rs b/implementations/rust/preserves/src/value/reader.rs deleted file mode 100644 index d07999e..0000000 --- a/implementations/rust/preserves/src/value/reader.rs +++ /dev/null @@ -1,567 +0,0 @@ -//! Generic [Reader] trait for parsing Preserves [Value][crate::value::repr::Value]s, -//! implemented by code that provides each specific transfer syntax. - -use crate::error::{self, io_eof, ExpectedKind, Received}; - -use std::borrow::Cow; -use std::io; -use std::marker::PhantomData; - -use super::boundary as B; -use super::signed_integer::SignedInteger; -use super::CompoundClass; -use super::DomainDecode; -use super::DomainParse; -use super::Double; -use super::IOValue; -use super::IOValueDomainCodec; -use super::NestedValue; -use super::ViaCodec; - -pub type ReaderResult = std::result::Result; - -/// Tokens produced when performing -/// [SAX](https://en.wikipedia.org/wiki/Simple_API_for_XML)-style reading of terms. -pub enum Token { - /// An embedded value was seen and completely decoded. - Embedded(N::Embedded), - /// An atomic value was seen and completely decoded. - Atom(N), - /// A compound value has been opened; its contents follow, and it will be terminated by - /// [Token::End]. - Compound(CompoundClass), - /// Closes a previously-opened compound value. - End, -} - -/// Generic parser for Preserves. -pub trait Reader<'de, N: NestedValue> { - /// Retrieve the next parseable value or an indication of end-of-input. - /// - /// Yields `Ok(Some(...))` if a complete value is available, `Ok(None)` if the end of - /// stream has been reached, or `Err(...)` for parse or IO errors, including - /// incomplete/partial input. See also [Reader::demand_next]. - fn next(&mut self, read_annotations: bool) -> io::Result>; - - // Hiding these from the documentation for the moment because I don't want to have to - // document the whole Boundary thing. - #[doc(hidden)] - fn open_record(&mut self, arity: Option) -> ReaderResult; - #[doc(hidden)] - fn open_sequence_or_set(&mut self) -> ReaderResult; - #[doc(hidden)] - fn open_sequence(&mut self) -> ReaderResult<()>; - #[doc(hidden)] - fn open_set(&mut self) -> ReaderResult<()>; - #[doc(hidden)] - fn open_dictionary(&mut self) -> ReaderResult<()>; - #[doc(hidden)] - fn boundary(&mut self, b: &B::Type) -> ReaderResult<()>; - - #[doc(hidden)] - // close_compound implies a b.shift(...) and a self.boundary(b). - fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult; - - #[doc(hidden)] - fn open_embedded(&mut self) -> ReaderResult<()>; - #[doc(hidden)] - fn close_embedded(&mut self) -> ReaderResult<()>; - - /// Allows structured backtracking to an earlier stage in a parse. Useful for layering - /// parser combinators atop a Reader. - type Mark; - /// Retrieve a marker for the current position in the input. - fn mark(&mut self) -> io::Result; - /// Seek the input to a previously-saved position. - fn restore(&mut self, mark: &Self::Mark) -> io::Result<()>; - - /// Get the next [SAX](https://en.wikipedia.org/wiki/Simple_API_for_XML)-style event, - /// discarding annotations. - /// - /// The `read_embedded_annotations` controls whether annotations are also skipped on - /// *embedded* values or not. - fn next_token(&mut self, read_embedded_annotations: bool) -> io::Result>; - /// Get the next [SAX](https://en.wikipedia.org/wiki/Simple_API_for_XML)-style event, plus - /// a vector containing any annotations that preceded it. - fn next_annotations_and_token(&mut self) -> io::Result<(Vec, Token)>; - - //--------------------------------------------------------------------------- - - /// Skips the next available complete value. Yields an error if no such value exists. - fn skip_value(&mut self) -> io::Result<()> { - // TODO efficient skipping in specific impls of this trait - let _ = self.demand_next(false)?; - Ok(()) - } - - /// Retrieve the next parseable value, treating end-of-input as an error. - /// - /// Yields `Ok(...)` if a complete value is available or `Err(...)` for parse or IO errors, - /// including incomplete/partial input or end of stream. See also [Reader::next]. - fn demand_next(&mut self, read_annotations: bool) -> io::Result { - self.next(read_annotations)?.ok_or_else(io_eof) - } - - /// Yields the next value, if it is a `Boolean`, or an error otherwise. - fn next_boolean(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_boolean() - } - - /// Yields the next value, if it is a `Double`, or an error otherwise. - fn next_double(&mut self) -> ReaderResult { - Ok(self.demand_next(false)?.value().to_double()?.to_owned()) - } - - /// Yields the next value, if it is a `SignedInteger`, or an error otherwise. - fn next_signedinteger(&mut self) -> ReaderResult { - Ok(self - .demand_next(false)? - .value() - .to_signedinteger()? - .to_owned()) - } - - /// Yields the next value, if it is a `SignedInteger` that fits in [i8], or an error - /// otherwise. - fn next_i8(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_i8() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [u8], or an error - /// otherwise. - fn next_u8(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_u8() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [i16], or an error - /// otherwise. - fn next_i16(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_i16() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [u16], or an error - /// otherwise. - fn next_u16(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_u16() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [i32], or an error - /// otherwise. - fn next_i32(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_i32() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [u32], or an error - /// otherwise. - fn next_u32(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_u32() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [i64], or an error - /// otherwise. - fn next_i64(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_i64() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [u64], or an error - /// otherwise. - fn next_u64(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_u64() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [i128], or an error - /// otherwise. - fn next_i128(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_i128() - } - /// Yields the next value, if it is a `SignedInteger` that fits in [u128], or an error - /// otherwise. - fn next_u128(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_u128() - } - /// Yields the next value as an [f64], if it is a `Double`, or an error otherwise. - fn next_f64(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_f64() - } - /// Yields the next value as a [char], if it is parseable by - /// [Value::to_char][crate::value::Value::to_char], or an error otherwise. - fn next_char(&mut self) -> ReaderResult { - self.demand_next(false)?.value().to_char() - } - - /// Yields the next value, if it is a `String`, or an error otherwise. - fn next_str(&mut self) -> ReaderResult> { - Ok(Cow::Owned( - self.demand_next(false)?.value().to_string()?.to_owned(), - )) - } - - /// Yields the next value, if it is a `ByteString`, or an error otherwise. - fn next_bytestring(&mut self) -> ReaderResult> { - Ok(Cow::Owned( - self.demand_next(false)?.value().to_bytestring()?.to_owned(), - )) - } - - /// Yields the next value, if it is a `Symbol`, or an error otherwise. - fn next_symbol(&mut self) -> ReaderResult> { - Ok(Cow::Owned( - self.demand_next(false)?.value().to_symbol()?.to_owned(), - )) - } - - #[doc(hidden)] - fn open_option(&mut self) -> ReaderResult> { - let b = self.open_record(None)?; - let label: &str = &self.next_symbol()?; - match label { - "None" => { - self.ensure_complete(b, &B::Item::RecordField)?; - Ok(None) - } - "Some" => Ok(Some(b)), - _ => Err(error::Error::Expected( - ExpectedKind::Option, - Received::ReceivedRecordWithLabel(label.to_owned()), - )), - } - } - - #[doc(hidden)] - fn open_simple_record(&mut self, name: &str, arity: Option) -> ReaderResult { - let b = self.open_record(arity)?; - let label: &str = &self.next_symbol()?; - if label == name { - Ok(b) - } else { - Err(error::Error::Expected( - ExpectedKind::SimpleRecord(name.to_owned(), arity), - Received::ReceivedRecordWithLabel(label.to_owned()), - )) - } - } - - /// Constructs a [ConfiguredReader] set with the given value for `read_annotations`. - fn configured(self, read_annotations: bool) -> ConfiguredReader<'de, N, Self> - where - Self: std::marker::Sized, - { - ConfiguredReader { - reader: self, - read_annotations, - phantom: PhantomData, - } - } - - #[doc(hidden)] - fn ensure_more_expected(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<()> { - if !self.close_compound(b, i)? { - Ok(()) - } else { - Err(error::Error::MissingItem) - } - } - - #[doc(hidden)] - fn ensure_complete(&mut self, mut b: B::Type, i: &B::Item) -> ReaderResult<()> { - if !self.close_compound(&mut b, i)? { - Err(error::Error::MissingCloseDelimiter) - } else { - Ok(()) - } - } -} - -impl<'r, 'de, N: NestedValue, R: Reader<'de, N>> Reader<'de, N> for &'r mut R { - fn next(&mut self, read_annotations: bool) -> io::Result> { - (*self).next(read_annotations) - } - - fn open_record(&mut self, arity: Option) -> ReaderResult { - (*self).open_record(arity) - } - - fn open_sequence_or_set(&mut self) -> ReaderResult { - (*self).open_sequence_or_set() - } - - fn open_sequence(&mut self) -> ReaderResult<()> { - (*self).open_sequence() - } - - fn open_set(&mut self) -> ReaderResult<()> { - (*self).open_set() - } - - fn open_dictionary(&mut self) -> ReaderResult<()> { - (*self).open_dictionary() - } - - fn boundary(&mut self, b: &B::Type) -> ReaderResult<()> { - (*self).boundary(b) - } - - fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult { - (*self).close_compound(b, i) - } - - fn open_embedded(&mut self) -> ReaderResult<()> { - (*self).open_embedded() - } - - 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() - } -} - -/// Generic seekable stream of input bytes. -pub trait BinarySource<'de>: Sized { - /// Allows structured backtracking to an earlier position in an input. - type Mark; - /// Retrieve a marker for the current position in the input. - fn mark(&mut self) -> io::Result; - /// Seek the input to a previously-saved position. - fn restore(&mut self, mark: &Self::Mark) -> io::Result<()>; - - /// Skip the next byte. - fn skip(&mut self) -> io::Result<()>; - /// Returns the next byte without advancing over it. - fn peek(&mut self) -> io::Result; - /// Returns and consumes the next `count` bytes, which must all be available. Always yields - /// exactly `count` bytes or an error. - fn readbytes(&mut self, count: usize) -> io::Result>; - /// As [BinarySource::readbytes], but uses `bs` as destination for the read bytes as well - /// as taking the size of `bs` as the count of bytes to read. - fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()>; - - /// Constructs a [PackedReader][super::PackedReader] that will read from `self`. - fn packed>( - &mut self, - decode_embedded: Dec, - ) -> super::PackedReader<'de, '_, N, Dec, Self> { - super::PackedReader::new(self, decode_embedded) - } - - /// Constructs a [PackedReader][super::PackedReader] that will read [IOValue]s from `self`. - fn packed_iovalues( - &mut self, - ) -> super::PackedReader<'de, '_, IOValue, IOValueDomainCodec, Self> { - self.packed(IOValueDomainCodec) - } - - /// Constructs a [TextReader][super::TextReader] that will read from `self`. - fn text>( - &mut self, - decode_embedded: Dec, - ) -> super::TextReader<'de, '_, N, Dec, Self> { - super::TextReader::new(self, decode_embedded) - } - - /// Constructs a [TextReader][super::TextReader] that will read [IOValue]s from `self`. - fn text_iovalues( - &mut self, - ) -> super::TextReader<'de, '_, IOValue, ViaCodec, Self> { - self.text::(ViaCodec::new(IOValueDomainCodec)) - } -} - -/// Implementation of [BinarySource] backed by an [`io::Read`]` + `[`io::Seek`] implementation. -pub struct IOBinarySource { - /// The underlying byte source. - pub read: R, - #[doc(hidden)] - /// One-place buffer for peeked bytes. - pub buf: Option, -} - -impl IOBinarySource { - /// Constructs an [IOBinarySource] from the given [`io::Read`]` + `[`io::Seek`] - /// implementation. - #[inline(always)] - pub fn new(read: R) -> Self { - IOBinarySource { read, buf: None } - } -} - -impl<'de, R: io::Read + io::Seek> BinarySource<'de> for IOBinarySource { - type Mark = u64; - - #[inline(always)] - fn mark(&mut self) -> io::Result { - Ok(self.read.stream_position()? - (if self.buf.is_some() { 1 } else { 0 })) - } - - #[inline(always)] - fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { - self.read.seek(io::SeekFrom::Start(*mark))?; - self.buf = None; - Ok(()) - } - - #[inline(always)] - fn skip(&mut self) -> io::Result<()> { - if self.buf.is_none() { - unreachable!(); - } - self.buf = None; - Ok(()) - } - - #[inline(always)] - fn peek(&mut self) -> io::Result { - match self.buf { - Some(b) => Ok(b), - None => { - let b = &mut [0]; - match self.read.read(b)? { - 0 => Err(io_eof()), - 1 => { - self.buf = Some(b[0]); - Ok(b[0]) - } - _ => unreachable!(), - } - } - } - } - - #[inline(always)] - fn readbytes(&mut self, count: usize) -> io::Result> { - if self.buf.is_some() { - unreachable!(); - } - let mut bs = vec![0; count]; - self.read.read_exact(&mut bs)?; - Ok(Cow::Owned(bs)) - } - - #[inline(always)] - fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()> { - if self.buf.is_some() { - unreachable!(); - } - self.read.read_exact(bs) - } -} - -/// Implementation of [BinarySource] backed by a slice of [u8]. -pub struct BytesBinarySource<'de> { - /// The underlying byte source. - pub bytes: &'de [u8], - #[doc(hidden)] - /// Current position within `bytes`. - pub index: usize, -} - -impl<'de> BytesBinarySource<'de> { - /// Constructs a [BytesBinarySource] from the given `u8` slice. - #[inline(always)] - pub fn new(bytes: &'de [u8]) -> Self { - BytesBinarySource { bytes, index: 0 } - } -} - -impl<'de> BinarySource<'de> for BytesBinarySource<'de> { - type Mark = usize; - - #[inline(always)] - fn mark(&mut self) -> io::Result { - Ok(self.index) - } - - #[inline(always)] - fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { - self.index = *mark; - Ok(()) - } - - #[inline(always)] - fn skip(&mut self) -> io::Result<()> { - if self.index >= self.bytes.len() { - unreachable!(); - } - self.index += 1; - Ok(()) - } - - #[inline(always)] - fn peek(&mut self) -> io::Result { - if self.index >= self.bytes.len() { - Err(io_eof()) - } else { - Ok(self.bytes[self.index]) - } - } - - #[inline(always)] - fn readbytes(&mut self, count: usize) -> io::Result> { - if self.index + count > self.bytes.len() { - Err(io_eof()) - } else { - let bs = &self.bytes[self.index..self.index + count]; - self.index += count; - Ok(Cow::Borrowed(bs)) - } - } - - #[inline(always)] - fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()> { - let count = bs.len(); - if self.index + count > self.bytes.len() { - Err(io_eof()) - } else { - bs.copy_from_slice(&self.bytes[self.index..self.index + count]); - self.index += count; - Ok(()) - } - } -} - -/// A combination of a [Reader] with presets governing its operation. -pub struct ConfiguredReader<'de, N: NestedValue, R: Reader<'de, N>> { - /// The underlying [Reader]. - pub reader: R, - /// Configuration as to whether to include or discard annotations while reading. - pub read_annotations: bool, - phantom: PhantomData<&'de N>, -} - -impl<'de, N: NestedValue, R: Reader<'de, N>> ConfiguredReader<'de, N, R> { - /// Constructs a [ConfiguredReader] based on the given `reader`. - pub fn new(reader: R) -> Self { - reader.configured(true) - } - - /// Updates the `read_annotations` field of `self`. - pub fn set_read_annotations(&mut self, read_annotations: bool) { - self.read_annotations = read_annotations - } - - /// Retrieve the next parseable value, treating end-of-input as an error. - /// - /// Delegates directly to [Reader::demand_next]. - pub fn demand_next(&mut self) -> io::Result { - self.reader.demand_next(self.read_annotations) - } -} - -impl<'de, N: NestedValue, R: Reader<'de, N>> std::iter::Iterator for ConfiguredReader<'de, N, R> { - type Item = io::Result; - fn next(&mut self) -> Option { - match self.reader.next(self.read_annotations) { - Err(e) => Some(Err(e)), - Ok(None) => None, - Ok(Some(v)) => Some(Ok(v)), - } - } -} diff --git a/implementations/rust/preserves/src/value/repr.rs b/implementations/rust/preserves/src/value/repr.rs deleted file mode 100644 index c44de49..0000000 --- a/implementations/rust/preserves/src/value/repr.rs +++ /dev/null @@ -1,1877 +0,0 @@ -//! In-memory representation of Preserves `Value`s. - -use num::bigint::BigInt; -use num::traits::cast::ToPrimitive; -use std::borrow::Cow; -use std::cmp::Ordering; -use std::convert::From; -use std::convert::TryFrom; -use std::convert::TryInto; -use std::fmt::Debug; -use std::hash::{Hash, Hasher}; -use std::io; -use std::ops::Index; -use std::ops::IndexMut; -use std::string::String; -use std::sync::Arc; -use std::vec::Vec; - -pub use std::collections::BTreeMap as Map; -pub use std::collections::BTreeSet as Set; - -use super::signed_integer::SignedInteger; -use super::text; -use super::DebugDomainEncode; -use super::FromStrDomainParse; -use super::IOValueDomainCodec; -use super::TextWriter; -use super::Writer; -use crate::error::{Error, ExpectedKind, Received}; - -/// A `Domain` implementation allows a Rust value to be placed as a Preserves [embedded -/// value](https://preserves.dev/preserves.html#embeddeds) inside a Preserves term. (See also -/// [Embeddable].) -pub trait Domain: Sized + Debug + Eq + Hash + Ord { - fn debug_encode(&self, w: &mut W) -> io::Result<()> { - w.write_string(&format!("{:?}", self)) - } -} - -/// Any Rust value that implements [`Domain`] and `Clone` is automatically `Embeddable`, and -/// may be placed as a Preserves [embedded -/// value](https://preserves.dev/preserves.html#embeddeds) inside a Preserves term. (See also -/// [Domain].) -pub trait Embeddable: Domain + Clone {} -impl Embeddable for T where T: Domain + Clone {} - -impl Domain for Arc { - fn debug_encode(&self, w: &mut W) -> io::Result<()> { - self.as_ref().debug_encode(w) - } -} - -/// This is the **primary programming interface** to Preserves values. The most common and -/// useful implementations of this trait are first [IOValue] and second [ArcValue]. -pub trait NestedValue: Sized + Debug + Clone + Eq + Hash + Ord { - /// Every representation of Preserves values has an associated type: that of the Rust data - /// able to be [embedded](https://preserves.dev/preserves.html#embeddeds) inside a value. - type Embedded: Embeddable; - - /// `v` can be converted to a [Value]; `new` does this and then [wrap][Value::wrap]s it to - /// yield an instance of [Self]. - #[inline(always)] - fn new(v: V) -> Self - where - Value: From, - { - Value::from(v).wrap() - } - - /// [Embeds](https://preserves.dev/preserves.html#embeddeds) `e` to a Preserves embedded - /// value; `e` is first converted to [Self::Embedded]. - #[inline(always)] - fn domain(e: E) -> Self - where - Self::Embedded: From, - { - Value::Embedded(e.into()).wrap() - } - - /// Yields a Preserves `Symbol` embodying the given text, `n`. - #[inline(always)] - fn symbol(n: &str) -> Self { - Value::symbol(n).wrap() - } - - /// Yields a Preserves `ByteString`. - #[inline(always)] - fn bytestring<'a, V: Into>>(v: V) -> Self { - Value::bytestring(v).wrap() - } - - /// Attaches the given [Annotations] to the [Value]. - fn wrap(anns: Annotations, v: Value) -> Self; - - /// Retrieves any annotations attached to `self`. - fn annotations(&self) -> &Annotations; - /// Retrieves the underlying [Value] represented by `self`. - fn value(&self) -> &Value; - /// Consumes `self`, yielding its annotations and underlying [Value]. - fn pieces(self) -> (Annotations, Value); - /// Consumes `self`, yielding its underlying [Value] and discarding its annotations. - fn value_owned(self) -> Value; - - /// Retrieves the [ValueClass] of `self`. - #[inline(always)] - fn value_class(&self) -> ValueClass { - self.value().value_class() - } - - /// Supplies an opportunity to customize debug formatting for `self`. Defaults to writing - /// `@`-prefixed annotations followed by the underlying value. - fn debug_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for ann in self.annotations().slice() { - write!(f, "@{:?} ", ann)?; - } - self.value().fmt(f) - } - - /// Yields a deep copy of `self` with all annotations (recursively) removed. - fn strip_annotations>(&self) -> M { - M::wrap(Annotations::empty(), self.value().strip_annotations()) - } - - /// Yields a deep copy of `self`, mapping embedded values to a new type via `f`. - fn copy_via(&self, f: &mut F) -> Result - where - F: FnMut(&Self::Embedded) -> Result, Err>, - { - Ok(M::wrap( - self.annotations().copy_via(f)?, - self.value().copy_via(f)?, - )) - } - - /// Calls `f` once for each (recursively) embedded [Self::Embedded] value in `self`. - fn foreach_embedded(&self, f: &mut F) -> Result<(), Err> - where - F: FnMut(&Self::Embedded) -> Result<(), Err>, - { - match &self.annotations().0 { - None => (), - Some(vs) => { - for v in vs.iter() { - v.foreach_embedded(f)? - } - } - } - self.value().foreach_embedded(f) - } -} - -/// The `Value`s from the specification. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum Value { - Boolean(bool), - Double(Double), - SignedInteger(SignedInteger), - String(String), - ByteString(Vec), - Symbol(String), - Record(Record), - Sequence(Vec), - Set(Set), - Dictionary(Map), - Embedded(N::Embedded), -} - -/// 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, - 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, -} - -/// Double-precision IEEE 754 Value -#[derive(Clone, Copy, Debug)] -pub struct Double(pub f64); - -/// A Record `Value`. -/// -/// INVARIANT: The length of the contained vector **MUST** always be non-zero. -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Record(pub Vec); - -impl Record { - /// Retrieve the record's label. - #[inline(always)] - pub fn label(&self) -> &N { - &self.0[0] - } - - /// Retrieve a mutable reference to the record's label. - #[inline(always)] - pub fn label_mut(&mut self) -> &mut N { - &mut self.0[0] - } - - /// Retrieve the arity of the record, the number of fields it has. - #[inline(always)] - pub fn arity(&self) -> usize { - self.0.len() - 1 - } - - /// Retrieve a slice containing the fields of the record. - #[inline(always)] - pub fn fields(&self) -> &[N] { - &self.0[1..] - } - - /// Retrieve a mutable slice containing the fields of the record. - #[inline(always)] - pub fn fields_mut(&mut self) -> &mut [N] { - &mut self.0[1..] - } - - /// Retrieve a reference to a vector containing the record's label and fields. - #[inline(always)] - pub fn fields_vec(&self) -> &Vec { - &self.0 - } - - /// Retrieve a mutable reference to a vector containing the record's label and fields. - #[inline(always)] - pub fn fields_vec_mut(&mut self) -> &mut Vec { - &mut self.0 - } - - /// Converts `self` into a [Value]. - #[inline(always)] - pub fn finish(self) -> Value - where - N: NestedValue, - { - Value::Record(self) - } -} - -impl From for Double { - fn from(v: f64) -> Self { - Double(v) - } -} - -impl From for f64 { - fn from(v: Double) -> Self { - v.0 - } -} - -impl Hash for Double { - fn hash(&self, state: &mut H) { - self.0.to_bits().hash(state); - } -} - -impl PartialEq for Double { - fn eq(&self, other: &Self) -> bool { - self.0.to_bits() == other.0.to_bits() - } -} - -impl Ord for Double { - fn cmp(&self, other: &Self) -> Ordering { - let mut a: u64 = self.0.to_bits(); - let mut b: u64 = other.0.to_bits(); - if a & 0x8000_0000_0000_0000 != 0 { - a ^= 0x7fff_ffff_ffff_ffff; - } - if b & 0x8000_0000_0000_0000 != 0 { - b ^= 0x7fff_ffff_ffff_ffff; - } - (a as i64).cmp(&(b as i64)) - } -} - -impl PartialOrd for Double { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Eq for Double {} - -impl From for Value { - fn from(v: bool) -> Self { - Value::Boolean(v) - } -} -impl From<&bool> for Value { - fn from(v: &bool) -> Self { - Value::Boolean(*v) - } -} - -impl From for Value { - fn from(v: f64) -> Self { - Value::Double(Double::from(v)) - } -} -impl From<&f64> for Value { - fn from(v: &f64) -> Self { - Value::Double(Double::from(*v)) - } -} -impl From<&Double> for Value { - fn from(v: &Double) -> Self { - Value::Double(v.clone()) - } -} - -impl From for Value { - fn from(v: u8) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: i8) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: u16) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: i16) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: u32) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: i32) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: u64) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: i64) -> Self { - Value::from(i128::from(v)) - } -} -impl From for Value { - fn from(v: usize) -> Self { - Value::from(v as u128) - } -} -impl From for Value { - fn from(v: isize) -> Self { - Value::from(v as i128) - } -} -impl From for Value { - fn from(v: u128) -> Self { - Value::SignedInteger(SignedInteger::from(v)) - } -} -impl From for Value { - fn from(v: i128) -> Self { - Value::SignedInteger(SignedInteger::from(v)) - } -} -impl From<&BigInt> for Value { - fn from(v: &BigInt) -> Self { - Value::SignedInteger(SignedInteger::from(Cow::Borrowed(v))) - } -} -impl From for Value { - fn from(v: BigInt) -> Self { - Value::SignedInteger(SignedInteger::from(Cow::Owned(v))) - } -} -impl From<&SignedInteger> for Value { - fn from(v: &SignedInteger) -> Self { - Value::SignedInteger(v.clone()) - } -} - -impl From<&str> for Value { - fn from(v: &str) -> Self { - Value::String(String::from(v)) - } -} -impl From for Value { - fn from(v: String) -> Self { - Value::String(v) - } -} -impl From<&String> for Value { - fn from(v: &String) -> Self { - Value::String(v.to_owned()) - } -} - -impl From<&[u8]> for Value { - fn from(v: &[u8]) -> Self { - Value::ByteString(Vec::from(v)) - } -} -// impl From> for Value { fn from(v: Vec) -> Self { Value::ByteString(v) } } - -impl From> for Value { - fn from(v: Vec) -> Self { - Value::Sequence(v) - } -} -impl From> for Value { - fn from(v: Set) -> Self { - Value::Set(v) - } -} -impl From> for Value { - fn from(v: Map) -> Self { - Value::Dictionary(v) - } -} - -impl Debug for Value { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - TextWriter::fmt_value(f, &mut DebugDomainEncode, self).map_err(|_| std::fmt::Error) - } -} - -impl< - Err: Into, - D: Embeddable + std::str::FromStr, - N: NestedValue, - > std::str::FromStr for Value -{ - type Err = io::Error; - - fn from_str(s: &str) -> Result { - Ok(text::from_str::(s, FromStrDomainParse)?.value_owned()) - } -} - -//--------------------------------------------------------------------------- - -impl Value { - /// Converts `self` to a [NestedValue] by supplying an empty collection of annotations. - pub fn wrap(self) -> N { - N::wrap(Annotations::empty(), self) - } - - /// Retrieves the [ValueClass] of `self`. - fn value_class(&self) -> ValueClass { - match self { - Value::Boolean(_) => ValueClass::Atomic(AtomClass::Boolean), - 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, - } - } - - /// Retrieve a vector of the "children" of `self`. - /// - /// For atoms, this is an empty vector. For records, it's all the fields (but not the - /// label). For sequences and sets, it's the contained values. For dictionaries, it's all - /// the values in the key-value mappings (but not the keys). - pub fn children(&self) -> Vec { - match self { - Value::Boolean(_) - | Value::Double(_) - | Value::SignedInteger(_) - | Value::String(_) - | Value::ByteString(_) - | Value::Symbol(_) - | Value::Embedded(_) => vec![], - - Value::Record(r) => r.fields().to_vec(), - Value::Sequence(vs) => vs.clone(), - Value::Set(s) => s.iter().cloned().collect(), - Value::Dictionary(d) => d.values().cloned().collect(), - } - } - - fn expected(&self, k: ExpectedKind) -> Error { - Error::Expected( - k, - Received::ReceivedOtherValue(format!("{:?}", self.clone().wrap())), - ) - } - - /// True iff this is a [Value::Boolean]. - #[inline(always)] - pub fn is_boolean(&self) -> bool { - self.as_boolean().is_some() - } - - /// Yields `Some` iff this is a [Value::Boolean]. - #[inline(always)] - pub fn as_boolean(&self) -> Option { - if let Value::Boolean(b) = self { - Some(*b) - } else { - None - } - } - - /// Retrieve a mutable reference to the contained boolean value iff this is a [Value::Boolean]. - #[inline(always)] - pub fn as_boolean_mut(&mut self) -> Option<&mut bool> { - if let Value::Boolean(b) = self { - Some(b) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Boolean]; else [Error::Expected]. - #[inline(always)] - pub fn to_boolean(&self) -> Result { - self.as_boolean() - .ok_or_else(|| self.expected(ExpectedKind::Boolean)) - } - - /// True iff this is a [Value::Double]. - #[inline(always)] - pub fn is_double(&self) -> bool { - self.as_double().is_some() - } - - /// Yields `Some` iff this is a [Value::Double]. - #[inline(always)] - pub fn as_double(&self) -> Option<&Double> { - if let Value::Double(f) = self { - Some(f) - } else { - None - } - } - - /// Retrieve a mutable reference to the contained [Double] value iff this is a [Value::Double]. - #[inline(always)] - pub fn as_double_mut(&mut self) -> Option<&mut Double> { - if let Value::Double(f) = self { - Some(f) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Double]; else [Error::Expected]. - #[inline(always)] - pub fn to_double(&self) -> Result<&Double, Error> { - self.as_double() - .ok_or_else(|| self.expected(ExpectedKind::Double)) - } - - /// As [Self::is_double]. - #[inline(always)] - pub fn is_f64(&self) -> bool { - self.is_double() - } - - /// As [Self::as_double], but yields [f64] instead of [Double]. - #[inline(always)] - pub fn as_f64(&self) -> Option { - self.as_double().map(|f| f.0) - } - - /// As [Self::as_double_mut], but [f64] instead of [Double]. - #[inline(always)] - pub fn as_f64_mut(&mut self) -> Option<&mut f64> { - self.as_double_mut().map(|f| &mut f.0) - } - - /// As [Self::to_double], but with [f64] instead of [Double]. - #[inline(always)] - pub fn to_f64(&self) -> Result { - self.to_double().map(|f| f.0) - } - - /// True iff this is a [Value::SignedInteger]. - #[inline(always)] - pub fn is_signedinteger(&self) -> bool { - self.as_signedinteger().is_some() - } - - /// Yields `Some` iff this is a [Value::SignedInteger]. - #[inline(always)] - pub fn as_signedinteger(&self) -> Option<&SignedInteger> { - if let Value::SignedInteger(n) = self { - Some(n) - } else { - None - } - } - - /// Retrieve a mutable reference to the contained SignedInteger value iff this is a [Value::SignedInteger]. - #[inline(always)] - pub fn as_signedinteger_mut(&mut self) -> Option<&mut SignedInteger> { - if let Value::SignedInteger(n) = self { - Some(n) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::SignedInteger]; else [Error::Expected]. - #[inline(always)] - pub fn to_signedinteger(&self) -> Result<&SignedInteger, Error> { - self.as_signedinteger() - .ok_or_else(|| self.expected(ExpectedKind::SignedInteger)) - } - - /// True iff [Self::as_i] yields `Some`. - #[inline(always)] - pub fn is_i(&self) -> bool { - self.as_i().is_some() - } - - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [i128]. - #[inline(always)] - pub fn as_i(&self) -> Option { - self.as_signedinteger().and_then(|n| n.try_into().ok()) - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [i128]; else [Error::Expected]. - #[inline(always)] - pub fn to_i(&self) -> Result { - self.as_i() - .ok_or_else(|| self.expected(ExpectedKind::SignedIntegerI128)) - } - - /// True iff [Self::as_u] yields `Some`. - #[inline(always)] - pub fn is_u(&self) -> bool { - self.as_u().is_some() - } - - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [u128]. - #[inline(always)] - pub fn as_u(&self) -> Option { - self.as_signedinteger().and_then(|n| n.try_into().ok()) - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [u128]; else [Error::Expected]. - #[inline(always)] - pub fn to_u(&self) -> Result { - self.as_u() - .ok_or_else(|| self.expected(ExpectedKind::SignedIntegerU128)) - } - - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [u8]. - #[inline(always)] - pub fn as_u8(&self) -> Option { - self.as_u().and_then(|i| i.to_u8()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [i8]. - #[inline(always)] - pub fn as_i8(&self) -> Option { - self.as_i().and_then(|i| i.to_i8()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [u16]. - #[inline(always)] - pub fn as_u16(&self) -> Option { - self.as_u().and_then(|i| i.to_u16()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [i16]. - #[inline(always)] - pub fn as_i16(&self) -> Option { - self.as_i().and_then(|i| i.to_i16()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [u32]. - #[inline(always)] - pub fn as_u32(&self) -> Option { - self.as_u().and_then(|i| i.to_u32()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [i32]. - #[inline(always)] - pub fn as_i32(&self) -> Option { - self.as_i().and_then(|i| i.to_i32()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [u64]. - #[inline(always)] - pub fn as_u64(&self) -> Option { - self.as_u().and_then(|i| i.to_u64()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [i64]. - #[inline(always)] - pub fn as_i64(&self) -> Option { - self.as_i().and_then(|i| i.to_i64()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [u128]. - #[inline(always)] - pub fn as_u128(&self) -> Option { - self.as_u() - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [i128]. - #[inline(always)] - pub fn as_i128(&self) -> Option { - self.as_i() - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [usize]. - #[inline(always)] - pub fn as_usize(&self) -> Option { - self.as_u().and_then(|i| i.to_usize()) - } - /// Yields `Some` if `self` is a [Value::SignedInteger] that fits in [isize]. - #[inline(always)] - pub fn as_isize(&self) -> Option { - self.as_i().and_then(|i| i.to_isize()) - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [i8]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_i8(&self) -> Result { - match self.as_i() { - Some(i) => i - .to_i8() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [u8]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_u8(&self) -> Result { - match self.as_u() { - Some(i) => i - .to_u8() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [i16]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_i16(&self) -> Result { - match self.as_i() { - Some(i) => i - .to_i16() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [u16]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_u16(&self) -> Result { - match self.as_u() { - Some(i) => i - .to_u16() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [i32]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_i32(&self) -> Result { - match self.as_i() { - Some(i) => i - .to_i32() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [u32]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_u32(&self) -> Result { - match self.as_u() { - Some(i) => i - .to_u32() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [i64]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_i64(&self) -> Result { - match self.as_i() { - Some(i) => i - .to_i64() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [u64]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_u64(&self) -> Result { - match self.as_u() { - Some(i) => i - .to_u64() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [i128]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_i128(&self) -> Result { - match self.as_i() { - Some(i) => i - .to_i128() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [u128]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_u128(&self) -> Result { - match self.as_u() { - Some(i) => i - .to_u128() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [isize]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_isize(&self) -> Result { - match self.as_i() { - Some(i) => i - .to_isize() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a [Value::SignedInteger] that fits in [usize]; - /// otherwise, [Error::Expected] or [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_usize(&self) -> Result { - match self.as_u() { - Some(i) => i - .to_usize() - .ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))), - None => Err(self.expected(ExpectedKind::SignedInteger)), - } - } - - /// Yields `Ok` if `self` is a record with label a symbol `UnicodeScalar` and single field - /// a SignedInteger that can represent a valid Unicode scalar value. Otherwise, - /// [Error::Expected] or [Error::InvalidUnicodeScalar]. otherwise, [Error::Expected] or - /// [Error::NumberOutOfRange]. - #[inline(always)] - pub fn to_char(&self) -> Result { - let fs = self.to_simple_record("UnicodeScalar", Some(1))?; - let c = fs[0].value().to_u32()?; - char::try_from(c).map_err(|_| Error::InvalidUnicodeScalar(c)) - } - - /// True iff this is a [Value::String]. - #[inline(always)] - pub fn is_string(&self) -> bool { - self.as_string().is_some() - } - - /// Yields `Some` iff this is a [Value::String]. - #[inline(always)] - pub fn as_string(&self) -> Option<&String> { - if let Value::String(s) = self { - Some(s) - } else { - None - } - } - - /// Retrieve a mutable reference to the contained String value iff this is a [Value::String]. - #[inline(always)] - pub fn as_string_mut(&mut self) -> Option<&mut String> { - if let Value::String(s) = self { - Some(s) - } else { - None - } - } - - /// Consumes `self`, yielding a `String` iff `self` is a [Value::String]. - #[inline(always)] - pub fn into_string(self) -> Option { - match self { - Value::String(s) => Some(s), - _ => None, - } - } - - /// Yields `Ok` iff this is a [Value::String]; else [Error::Expected]. - #[inline(always)] - pub fn to_string(&self) -> Result<&String, Error> { - self.as_string() - .ok_or_else(|| self.expected(ExpectedKind::String)) - } - - /// Constructs a [Value::ByteString] from `v`. - #[inline(always)] - pub fn bytestring<'a, V: Into>>(v: V) -> Self { - Value::ByteString(v.into().into_owned()) - } - - /// True iff this is a [Value::ByteString]. - #[inline(always)] - pub fn is_bytestring(&self) -> bool { - self.as_bytestring().is_some() - } - - /// Yields `Some` iff this is a [Value::ByteString]. - #[inline(always)] - pub fn as_bytestring(&self) -> Option<&Vec> { - if let Value::ByteString(s) = self { - Some(s) - } else { - None - } - } - - /// Retrieve a mutable reference to the contained bytes value iff this is a [Value::ByteString]. - #[inline(always)] - pub fn as_bytestring_mut(&mut self) -> Option<&mut Vec> { - if let Value::ByteString(s) = self { - Some(s) - } else { - None - } - } - - /// Consumes `self`, yielding a `Vec` iff `self` is a [Value::ByteString]. - #[inline(always)] - pub fn into_bytestring(self) -> Option> { - match self { - Value::ByteString(bs) => Some(bs), - _ => None, - } - } - - /// Yields `Ok` iff this is a [Value::ByteString]; else [Error::Expected]. - #[inline(always)] - pub fn to_bytestring(&self) -> Result<&Vec, Error> { - self.as_bytestring() - .ok_or_else(|| self.expected(ExpectedKind::ByteString)) - } - - /// Constructs a [Value::Symbol] from `v`. - #[inline(always)] - pub fn symbol(s: &str) -> Value { - Value::Symbol(s.to_string()) - } - - /// True iff this is a [Value::Symbol]. - #[inline(always)] - pub fn is_symbol(&self) -> bool { - self.as_symbol().is_some() - } - - /// Yields `Some` iff this is a [Value::Symbol]. - #[inline(always)] - pub fn as_symbol(&self) -> Option<&String> { - if let Value::Symbol(s) = self { - Some(s) - } else { - None - } - } - - /// Retrieve a mutable reference to the contained Symbol's string iff this is a [Value::Symbol]. - #[inline(always)] - pub fn as_symbol_mut(&mut self) -> Option<&mut String> { - if let Value::Symbol(s) = self { - Some(s) - } else { - None - } - } - - /// Consumes `self`, yielding a `String` iff `self` is a [Value::Symbol]. - #[inline(always)] - pub fn into_symbol(self) -> Option { - match self { - Value::Symbol(s) => Some(s), - _ => None, - } - } - - /// Yields `Ok` iff this is a [Value::Symbol]; else [Error::Expected]. - #[inline(always)] - pub fn to_symbol(&self) -> Result<&String, Error> { - self.as_symbol() - .ok_or_else(|| self.expected(ExpectedKind::Symbol)) - } - - /// Constructs a record with the given label and expected arity. The new record will - /// initially not have any fields, but will be allocated with capacity for `expected_arity` - /// fields. - #[inline(always)] - pub fn record(label: N, expected_arity: usize) -> Record { - let mut v = Vec::with_capacity(expected_arity + 1); - v.push(label); - Record(v) - } - - /// True iff this is a [Value::Record]. - #[inline(always)] - pub fn is_record(&self) -> bool { - matches!(*self, Value::Record(_)) - } - - /// Yields `Some` iff this is a [Value::Record]. - #[inline(always)] - pub fn as_record(&self, arity: Option) -> Option<&Record> { - if let Value::Record(r) = self { - match arity { - Some(expected) if r.arity() == expected => Some(r), - Some(_other) => None, - None => Some(r), - } - } else { - None - } - } - - /// Consumes `self`, yielding a `Record` iff `self` is a [Value::Record]. - #[inline(always)] - pub fn into_record(self) -> Option> { - match self { - Value::Record(r) => Some(r), - _ => None, - } - } - - /// Retrieve a mutable reference to the contained Record value iff this is a [Value::Record]. - #[inline(always)] - pub fn as_record_mut(&mut self, arity: Option) -> Option<&mut Record> { - if let Value::Record(r) = self { - match arity { - Some(expected) if r.arity() == expected => Some(r), - Some(_other) => None, - None => Some(r), - } - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Record]; else [Error::Expected]. - #[inline(always)] - pub fn to_record(&self, arity: Option) -> Result<&Record, Error> { - self.as_record(arity) - .ok_or_else(|| self.expected(ExpectedKind::Record(arity))) - } - - /// Like [Self::record], but for the common case where the label is to be a `Symbol` with a - /// given text. - #[inline(always)] - pub fn simple_record(label: &str, expected_arity: usize) -> Record { - Self::record(N::symbol(label), expected_arity) - } - - /// Constructs a record with label a symbol with text `label`, and no fields. - #[inline(always)] - pub fn simple_record0(label: &str) -> Value { - Self::simple_record(label, 0).finish() - } - - /// Constructs a record with label a symbol with text `label`, and one field. - #[inline(always)] - pub fn simple_record1(label: &str, field: N) -> Value { - let mut r = Self::simple_record(label, 1); - r.fields_vec_mut().push(field); - r.finish() - } - - /// True iff `self` is a record with label a symbol with text `label` and arity matching - /// `arity`: any arity, if `arity == None`, or the specific `usize` concerned otherwise. - #[inline(always)] - pub fn is_simple_record(&self, label: &str, arity: Option) -> bool { - self.as_simple_record(label, arity).is_some() - } - - /// Yields `Some` containing a reference to the record's fields iff - /// [`Self::is_simple_record`]`(label, arity)` returns true. - #[inline(always)] - pub fn as_simple_record(&self, label: &str, arity: Option) -> Option<&[N]> { - self.as_record(arity).and_then(|r| match r.label().value() { - Value::Symbol(s) if s == label => Some(r.fields()), - _ => None, - }) - } - - /// Like [Self::as_simple_record], but yields [Error::Expected] on failure. - #[inline(always)] - pub fn to_simple_record(&self, label: &str, arity: Option) -> Result<&[N], Error> { - self.as_simple_record(label, arity) - .ok_or_else(|| self.expected(ExpectedKind::SimpleRecord(label.to_owned(), arity))) - } - - /// Serde's "option" type is incoded in Preserves as `` or ``. - #[inline(always)] - pub fn to_option(&self) -> Result, Error> { - match self.as_simple_record("None", Some(0)) { - Some(_fs) => Ok(None), - None => match self.as_simple_record("Some", Some(1)) { - Some(fs) => Ok(Some(&fs[0])), - None => Err(self.expected(ExpectedKind::Option)), - }, - } - } - - /// True iff this is a [Value::Sequence]. - #[inline(always)] - pub fn is_sequence(&self) -> bool { - self.as_sequence().is_some() - } - - /// Yields `Some` iff this is a [Value::Sequence]. - #[inline(always)] - pub fn as_sequence(&self) -> Option<&Vec> { - if let Value::Sequence(s) = self { - Some(s) - } else { - None - } - } - - /// Consumes `self`, yielding a [`Vec`] iff `self` is a [Value::Sequence]. - #[inline(always)] - pub fn into_sequence(self) -> Option> { - match self { - Value::Sequence(s) => Some(s), - _ => None, - } - } - - /// Retrieve a mutable reference to the contained [`Vec`] iff this is a [Value::Sequence]. - #[inline(always)] - pub fn as_sequence_mut(&mut self) -> Option<&mut Vec> { - if let Value::Sequence(s) = self { - Some(s) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Sequence]; else [Error::Expected]. - #[inline(always)] - pub fn to_sequence(&self) -> Result<&Vec, Error> { - self.as_sequence() - .ok_or_else(|| self.expected(ExpectedKind::Sequence)) - } - - /// True iff this is a [Value::Set]. - #[inline(always)] - pub fn is_set(&self) -> bool { - self.as_set().is_some() - } - - /// Yields `Some` iff this is a [Value::Set]. - #[inline(always)] - pub fn as_set(&self) -> Option<&Set> { - if let Value::Set(s) = self { - Some(s) - } else { - None - } - } - - /// Consumes `self`, yielding a [`Set`] iff `self` is a [Value::Set]. - #[inline(always)] - pub fn into_set(self) -> Option> { - match self { - Value::Set(s) => Some(s), - _ => None, - } - } - - /// Retrieve a mutable reference to the contained Set value iff this is a [Value::Set]. - #[inline(always)] - pub fn as_set_mut(&mut self) -> Option<&mut Set> { - if let Value::Set(s) = self { - Some(s) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Set]; else [Error::Expected]. - #[inline(always)] - pub fn to_set(&self) -> Result<&Set, Error> { - self.as_set() - .ok_or_else(|| self.expected(ExpectedKind::Set)) - } - - /// True iff this is a [Value::Dictionary]. - #[inline(always)] - pub fn is_dictionary(&self) -> bool { - self.as_dictionary().is_some() - } - - /// Yields `Some` iff this is a [Value::Dictionary]. - #[inline(always)] - pub fn as_dictionary(&self) -> Option<&Map> { - if let Value::Dictionary(s) = self { - Some(s) - } else { - None - } - } - - /// Consumes `self`, yielding a [`Map`] iff `self` is a [Value::Dictionary]. - #[inline(always)] - pub fn into_dictionary(self) -> Option> { - match self { - Value::Dictionary(s) => Some(s), - _ => None, - } - } - - /// Retrieve a mutable reference to the contained Map value iff this is a [Value::Dictionary]. - #[inline(always)] - pub fn as_dictionary_mut(&mut self) -> Option<&mut Map> { - if let Value::Dictionary(s) = self { - Some(s) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Dictionary]; else [Error::Expected]. - #[inline(always)] - pub fn to_dictionary(&self) -> Result<&Map, Error> { - self.as_dictionary() - .ok_or_else(|| self.expected(ExpectedKind::Dictionary)) - } - - /// True iff this is a [Value::Embedded]. - #[inline(always)] - pub fn is_embedded(&self) -> bool { - self.as_embedded().is_some() - } - - /// Yields `Some` iff this is a [Value::Embedded]. - #[inline(always)] - pub fn as_embedded(&self) -> Option<&N::Embedded> { - if let Value::Embedded(d) = self { - Some(d) - } else { - None - } - } - - /// Yields `Ok` iff this is a [Value::Embedded]; else [Error::Expected]. - #[inline(always)] - pub fn to_embedded(&self) -> Result<&N::Embedded, Error> { - self.as_embedded() - .ok_or_else(|| self.expected(ExpectedKind::Embedded)) - } - - /// Yields a deep copy of `self` with all annotations (recursively) removed. - pub fn strip_annotations>(&self) -> Value { - match self { - Value::Boolean(b) => Value::Boolean(*b), - Value::Double(d) => Value::Double(d.clone()), - Value::SignedInteger(n) => Value::SignedInteger(n.clone()), - Value::String(s) => Value::String(s.clone()), - Value::ByteString(v) => Value::ByteString(v.clone()), - Value::Symbol(v) => Value::Symbol(v.clone()), - Value::Record(r) => Value::Record(Record( - r.fields_vec() - .iter() - .map(|a| a.strip_annotations()) - .collect(), - )), - Value::Sequence(v) => { - Value::Sequence(v.iter().map(|a| a.strip_annotations()).collect()) - } - Value::Set(v) => Value::Set(v.iter().map(|a| a.strip_annotations()).collect()), - Value::Dictionary(v) => Value::Dictionary( - v.iter() - .map(|(a, b)| (a.strip_annotations(), b.strip_annotations())) - .collect(), - ), - Value::Embedded(d) => Value::Embedded(d.clone()), - } - } - - /// Yields a deep copy of `self`, mapping embedded values to a new type via `f`. - pub fn copy_via(&self, f: &mut F) -> Result, Err> - where - F: FnMut(&N::Embedded) -> Result, Err>, - { - Ok(match self { - Value::Boolean(b) => Value::Boolean(*b), - Value::Double(d) => Value::Double(d.clone()), - Value::SignedInteger(n) => Value::SignedInteger(n.clone()), - Value::String(s) => Value::String(s.clone()), - Value::ByteString(v) => Value::ByteString(v.clone()), - Value::Symbol(v) => Value::Symbol(v.clone()), - Value::Record(r) => Value::Record(Record( - r.fields_vec() - .iter() - .map(|a| a.copy_via(f)) - .collect::, _>>()?, - )), - Value::Sequence(v) => Value::Sequence( - v.iter() - .map(|a| a.copy_via(f)) - .collect::, _>>()?, - ), - Value::Set(v) => Value::Set( - v.iter() - .map(|a| a.copy_via(f)) - .collect::, _>>()?, - ), - Value::Dictionary(v) => Value::Dictionary( - v.iter() - .map(|(a, b)| Ok((a.copy_via(f)?, b.copy_via(f)?))) - .collect::, _>>()?, - ), - Value::Embedded(d) => f(d)?, - }) - } - - /// Calls `f` once for each (recursively) embedded value in `self`. - pub fn foreach_embedded(&self, f: &mut F) -> Result<(), Err> - where - F: FnMut(&N::Embedded) -> Result<(), Err>, - { - match self { - Value::Boolean(_) - | Value::Double(_) - | Value::SignedInteger(_) - | Value::String(_) - | Value::ByteString(_) - | Value::Symbol(_) => Ok(()), - Value::Record(r) => Ok(for v in r.fields_vec() { - v.foreach_embedded(f)? - }), - Value::Sequence(vs) => Ok(for v in vs { - v.foreach_embedded(f)? - }), - Value::Set(vs) => Ok(for v in vs { - v.foreach_embedded(f)? - }), - Value::Dictionary(d) => Ok(for (k, v) in d { - k.foreach_embedded(f)?; - v.foreach_embedded(f)?; - }), - Value::Embedded(d) => f(d), - } - } -} - -impl Index for Value { - type Output = N; - - #[inline(always)] - fn index(&self, i: usize) -> &Self::Output { - &self.as_sequence().unwrap()[i] - } -} - -impl IndexMut for Value { - #[inline(always)] - fn index_mut(&mut self, i: usize) -> &mut Self::Output { - &mut self.as_sequence_mut().unwrap()[i] - } -} - -impl Index<&N> for Value { - type Output = N; - - #[inline(always)] - fn index(&self, i: &N) -> &Self::Output { - &(*self.as_dictionary().unwrap())[i] - } -} - -//--------------------------------------------------------------------------- -// This part is a terrible hack - -#[doc(hidden)] -impl serde::Serialize for UnwrappedIOValue { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - super::magic::output_value(serializer, self.clone().wrap()) - } -} - -#[doc(hidden)] -impl<'de> serde::Deserialize<'de> for UnwrappedIOValue { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - Ok(super::magic::input_value::<'de, D>(deserializer)?.value_owned()) - } -} - -//--------------------------------------------------------------------------- - -/// Representation of a collection of annotations to be attached to a [Value] by way of an -/// implementation of trait [NestedValue]. - -#[derive(Clone)] -pub struct Annotations( - /// The complex-seeming `Option>>` is used to save memory, since a `Box` is - /// smaller than a `Vec`. - Option>>, -); - -impl Annotations { - /// Yield the empty [Annotations] sequence. - #[inline(always)] - pub fn empty() -> Self { - Annotations(None) - } - - /// Yield [Annotations] from a vector of values. - #[inline(always)] - pub fn new(anns: Option>) -> Self { - Annotations(anns.map(Box::new)) - } - - /// Extract carried annotations, if there are any. - #[inline(always)] - pub fn maybe_slice(&self) -> Option<&[N]> { - match &self.0 { - None => None, - Some(b) => Some(&b[..]), - } - } - - /// Extract carried annotations, supplying an empty slice if there are none. - #[inline(always)] - pub fn slice(&self) -> &[N] { - self.maybe_slice().unwrap_or(&[]) - } - - /// Produce a fresh [Vec] of the carried annotations. - #[inline(always)] - pub fn to_vec(self) -> Vec { - use std::ops::DerefMut; - self.0 - .map(|mut b| std::mem::take(b.deref_mut())) - .unwrap_or_default() - } - - /// Allows in-place updating of the collection of carried annotations. - pub fn modify(&mut self, f: F) -> &mut Self - where - F: FnOnce(&mut Vec), - { - match &mut self.0 { - None => { - let mut v = Vec::new(); - f(&mut v); - if !v.is_empty() { - self.0 = Some(Box::new(v)); - } - } - Some(b) => { - use std::ops::DerefMut; - f(b.deref_mut()); - if b.is_empty() { - self.0 = None; - } - } - } - self - } - - /// Yields a deep copy of `self`, mapping embedded values to a new type via `f`. - pub fn copy_via(&self, f: &mut F) -> Result, Err> - where - F: FnMut(&N::Embedded) -> Result, Err>, - { - Ok(match &self.0 { - None => Annotations(None), - Some(b) => Annotations(Some(Box::new( - b.iter() - .map(|a| a.copy_via(f)) - .collect::, _>>()?, - ))), - }) - } -} - -/// A possibly-annotated Value, with annotations (themselves -/// possibly-annotated) in order of appearance. -#[derive(Clone)] -pub struct AnnotatedValue(pub Annotations, pub Value); - -impl AnnotatedValue { - #[inline(always)] - fn new(anns: Annotations, value: Value) -> Self { - AnnotatedValue(anns, value) - } -} - -impl PartialEq for AnnotatedValue { - #[inline(always)] - fn eq(&self, other: &Self) -> bool { - self.1.eq(&other.1) - } -} - -impl Eq for AnnotatedValue {} - -impl Hash for AnnotatedValue { - #[inline(always)] - fn hash(&self, state: &mut H) { - self.1.hash(state); - } -} - -impl PartialOrd for AnnotatedValue { - #[inline(always)] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for AnnotatedValue { - #[inline(always)] - fn cmp(&self, other: &Self) -> Ordering { - self.1.cmp(&other.1) - } -} - -//--------------------------------------------------------------------------- - -/// A simple tree representation without any reference counting. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct PlainValue(AnnotatedValue>); - -impl PlainValue { - #[inline(always)] - pub fn annotations_mut(&mut self) -> &mut Annotations { - &mut (self.0).0 - } - - #[inline(always)] - pub fn value_mut(&mut self) -> &mut Value { - &mut (self.0).1 - } -} - -impl NestedValue for PlainValue { - type Embedded = D; - - #[inline(always)] - fn wrap(anns: Annotations, v: Value) -> Self { - PlainValue(AnnotatedValue::new(anns, v)) - } - - #[inline(always)] - fn annotations(&self) -> &Annotations { - &(self.0).0 - } - - #[inline(always)] - fn value(&self) -> &Value { - &(self.0).1 - } - - #[inline(always)] - fn pieces(self) -> (Annotations, Value) { - let AnnotatedValue(anns, v) = self.0; - (anns, v) - } - - #[inline(always)] - fn value_owned(self) -> Value { - (self.0).1 - } -} - -impl Debug for PlainValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.debug_fmt(f) - } -} - -//--------------------------------------------------------------------------- - -use std::rc::Rc; - -/// A representation of a Preserves Value using [Rc] for reference-counting of subvalues. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct RcValue(Rc>>); - -impl NestedValue for RcValue { - type Embedded = D; - - #[inline(always)] - fn wrap(anns: Annotations, v: Value) -> Self { - RcValue(Rc::new(AnnotatedValue::new(anns, v))) - } - - #[inline(always)] - fn annotations(&self) -> &Annotations { - &(self.0).0 - } - - #[inline(always)] - fn value(&self) -> &Value { - &(self.0).1 - } - - #[inline(always)] - fn pieces(self) -> (Annotations, Value) { - match Rc::try_unwrap(self.0) { - Ok(AnnotatedValue(anns, v)) => (anns, v), - Err(r) => (r.0.clone(), r.1.clone()), - } - } - - #[inline(always)] - fn value_owned(self) -> Value { - Rc::try_unwrap(self.0) - .unwrap_or_else(|_| panic!("value_owned on RcValue with refcount greater than one")) - .1 - } -} - -impl Debug for RcValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.debug_fmt(f) - } -} - -//--------------------------------------------------------------------------- - -/// A representation of a Preserves Value using [Arc] for reference-counting of subvalues. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ArcValue(Arc>>); - -impl NestedValue for ArcValue { - type Embedded = D; - - #[inline(always)] - fn wrap(anns: Annotations, v: Value) -> Self { - ArcValue(Arc::new(AnnotatedValue::new(anns, v))) - } - - #[inline(always)] - fn annotations(&self) -> &Annotations { - &(self.0).0 - } - - #[inline(always)] - fn value(&self) -> &Value { - &(self.0).1 - } - - #[inline(always)] - fn pieces(self) -> (Annotations, Value) { - match Arc::try_unwrap(self.0) { - Ok(AnnotatedValue(anns, v)) => (anns, v), - Err(r) => (r.0.clone(), r.1.clone()), - } - } - - #[inline(always)] - fn value_owned(self) -> Value { - match Arc::try_unwrap(self.0) { - Ok(AnnotatedValue(_anns, v)) => v, - Err(r) => r.1.clone(), - } - } -} - -impl Debug for ArcValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.debug_fmt(f) - } -} - -//--------------------------------------------------------------------------- - -/// A representation of a Preserves Value using [Arc] for reference-counting of subvalues and -/// having [IOValue] as [NestedValue::Embedded]. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct IOValue(Arc>); -pub type UnwrappedIOValue = Value; - -impl Domain for IOValue { - fn debug_encode(&self, w: &mut W) -> io::Result<()> { - w.write(&mut IOValueDomainCodec, self) - } -} - -impl NestedValue for IOValue { - type Embedded = Self; - - #[inline(always)] - fn wrap(anns: Annotations, v: Value) -> Self { - IOValue(Arc::new(AnnotatedValue::new(anns, v))) - } - - #[inline(always)] - fn annotations(&self) -> &Annotations { - &(self.0).0 - } - - #[inline(always)] - fn value(&self) -> &Value { - &(self.0).1 - } - - #[inline(always)] - fn pieces(self) -> (Annotations, Value) { - match Arc::try_unwrap(self.0) { - Ok(AnnotatedValue(anns, v)) => (anns, v), - Err(r) => (r.0.clone(), r.1.clone()), - } - } - - #[inline(always)] - fn value_owned(self) -> Value { - match Arc::try_unwrap(self.0) { - Ok(AnnotatedValue(_anns, v)) => v, - Err(r) => r.1.clone(), - } - } -} - -impl Debug for IOValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.debug_fmt(f) - } -} - -impl std::str::FromStr for IOValue { - type Err = io::Error; - fn from_str(s: &str) -> Result { - text::annotated_iovalue_from_str(s) - } -} - -impl serde::Serialize for IOValue { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - super::magic::output_value(serializer, self.clone()) - } -} - -impl<'de> serde::Deserialize<'de> for IOValue { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - super::magic::input_value(deserializer) - } -} - -//--------------------------------------------------------------------------- - -/// A "dummy" value that has no structure at all. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct DummyValue(AnnotatedValue>); - -impl Debug for DummyValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("<>") - } -} - -impl DummyValue { - #[inline(always)] - pub fn new() -> Self { - DummyValue(AnnotatedValue::new( - Annotations::empty(), - Value::Boolean(false), - )) - } -} - -impl NestedValue for DummyValue { - type Embedded = D; - - #[inline(always)] - fn wrap(_anns: Annotations, _v: Value) -> Self { - DummyValue::new() - } - - #[inline(always)] - fn annotations(&self) -> &Annotations { - &self.0 .0 - } - - #[inline(always)] - fn value(&self) -> &Value { - &self.0 .1 - } - - #[inline(always)] - fn pieces(self) -> (Annotations, Value) { - (self.0 .0, self.0 .1) - } - - #[inline(always)] - fn value_owned(self) -> Value { - self.0 .1 - } -} - -//--------------------------------------------------------------------------- - -#[doc(hidden)] -// https://stackoverflow.com/questions/34304593/counting-length-of-repetition-in-macro/34324856 -#[macro_export] -//#[allow(unused_macros)] -macro_rules! count__ { - () => (0usize); - ( $x:tt $($xs:tt)* ) => (1usize + $crate::count__!($($xs)*)); -} - -/// Convenience syntax for efficiently constructing Preserves -/// [record][crate::value::Value::record] values. -#[macro_export] -macro_rules! rec { - ( $label:expr $(, $item:expr)* ) => { - { - let mut r__ = $crate::value::Value::record($label, $crate::count__!($($item)*)); - $(r__.fields_vec_mut().push($item);)* - r__.finish().wrap() - } - } -} diff --git a/implementations/rust/preserves/src/value/ser.rs b/implementations/rust/preserves/src/value/ser.rs deleted file mode 100644 index 4fbc14a..0000000 --- a/implementations/rust/preserves/src/value/ser.rs +++ /dev/null @@ -1,377 +0,0 @@ -//! Support for Serde serialization of Rust data types into Preserves *values* (not syntax). - -use crate::value::{repr::Record, IOValue, Map, Value}; -use serde::Serialize; - -/// Empty/placeholder type for representing serialization errors: serialization to values -/// cannot fail. -#[derive(Debug)] -pub enum Error {} -impl serde::ser::Error for Error { - fn custom(_: T) -> Self - where - T: std::fmt::Display, - { - unreachable!() - } -} -impl std::error::Error for Error {} -impl std::fmt::Display for Error { - fn fmt(&self, _fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { - unreachable!() - } -} - -type Result = std::result::Result; - -/// Serde serializer for converting Rust data to in-memory Preserves values, which can then be -/// serialized using text or binary syntax, analyzed further, etc. -pub struct Serializer; - -#[doc(hidden)] -pub struct SerializeDictionary { - next_key: Option, - items: Map, -} - -#[doc(hidden)] -pub struct SerializeRecord { - r: Record, -} - -#[doc(hidden)] -pub struct SerializeSequence { - vec: Vec, -} - -impl serde::Serializer for Serializer { - type Ok = IOValue; - type Error = Error; - type SerializeSeq = SerializeSequence; - type SerializeTuple = SerializeRecord; - type SerializeTupleStruct = SerializeRecord; - type SerializeTupleVariant = SerializeRecord; - type SerializeMap = SerializeDictionary; - type SerializeStruct = SerializeRecord; - type SerializeStructVariant = SerializeRecord; - - fn serialize_bool(self, v: bool) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_i8(self, v: i8) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_i16(self, v: i16) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_i32(self, v: i32) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_i64(self, v: i64) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_u8(self, v: u8) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_u16(self, v: u16) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_u32(self, v: u32) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_u64(self, v: u64) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_f32(self, v: f32) -> Result { - Ok(Value::from(v as f64).wrap()) - } - - fn serialize_f64(self, v: f64) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_char(self, v: char) -> Result { - Ok(Value::simple_record1("UnicodeScalar", Value::from(v as u32).wrap()).wrap()) - } - - fn serialize_str(self, v: &str) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_bytes(self, v: &[u8]) -> Result { - Ok(Value::from(v).wrap()) - } - - fn serialize_none(self) -> Result { - Ok(Value::simple_record0("None").wrap()) - } - - fn serialize_some(self, v: &T) -> Result - where - T: Serialize, - { - Ok(Value::simple_record1("Some", to_value(v)).wrap()) - } - - fn serialize_unit(self) -> Result { - Ok(Value::simple_record0("tuple").wrap()) - } - - fn serialize_unit_struct(self, name: &'static str) -> Result { - Ok(Value::simple_record0(name).wrap()) - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - ) -> Result { - Ok(Value::simple_record0(variant_name).wrap()) - } - - fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result - where - T: Serialize, - { - match super::magic::receive_output_value(name, value) { - Some(v) => Ok(v), - None => { - // TODO: This is apparently discouraged, and we should apparently just serialize `value`? - Ok(Value::simple_record1(name, to_value(value)).wrap()) - } - } - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - Ok(Value::simple_record1(variant_name, to_value(value)).wrap()) - } - - fn serialize_seq(self, count: Option) -> Result { - let vec = match count { - Some(n) => Vec::with_capacity(n), - None => Vec::new(), - }; - Ok(SerializeSequence { vec }) - } - - fn serialize_tuple(self, count: usize) -> Result { - Ok(SerializeRecord { - r: Value::simple_record("tuple", count), - }) - } - - fn serialize_tuple_struct( - self, - name: &'static str, - count: usize, - ) -> Result { - Ok(SerializeRecord { - r: Value::simple_record(name, count), - }) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - count: usize, - ) -> Result { - Ok(SerializeRecord { - r: Value::simple_record(variant_name, count), - }) - } - - fn serialize_map(self, _count: Option) -> Result { - Ok(SerializeDictionary { - next_key: None, - items: Map::new(), - }) - } - - fn serialize_struct(self, name: &'static str, count: usize) -> Result { - Ok(SerializeRecord { - r: Value::simple_record(name, count), - }) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant: u32, - variant_name: &'static str, - count: usize, - ) -> Result { - Ok(SerializeRecord { - r: Value::simple_record(variant_name, count), - }) - } -} - -impl serde::ser::SerializeMap for SerializeDictionary { - type Ok = IOValue; - type Error = Error; - - fn serialize_key(&mut self, key: &T) -> Result<()> - where - T: Serialize, - { - self.next_key = Some(to_value(key)); - Ok(()) - } - - fn serialize_value(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - let key = self.next_key.take().unwrap(); - self.items.insert(key, to_value(value)); - Ok(()) - } - - fn end(self) -> Result { - Ok(Value::from(self.items).wrap()) - } -} - -impl SerializeRecord { - fn push(&mut self, value: &T) - where - T: Serialize, - { - self.r.fields_vec_mut().push(to_value(value)) - } - - fn finish(self) -> IOValue { - self.r.finish().wrap() - } -} - -impl serde::ser::SerializeStruct for SerializeRecord { - type Ok = IOValue; - type Error = Error; - - fn serialize_field(&mut self, _name: &'static str, value: &T) -> Result<()> - where - T: Serialize, - { - self.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(self.finish()) - } -} - -impl serde::ser::SerializeStructVariant for SerializeRecord { - type Ok = IOValue; - type Error = Error; - - fn serialize_field(&mut self, _name: &'static str, value: &T) -> Result<()> - where - T: Serialize, - { - self.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(self.finish()) - } -} - -impl serde::ser::SerializeTuple for SerializeRecord { - type Ok = IOValue; - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(self.finish()) - } -} - -impl serde::ser::SerializeTupleStruct for SerializeRecord { - type Ok = IOValue; - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(self.finish()) - } -} - -impl serde::ser::SerializeTupleVariant for SerializeRecord { - type Ok = IOValue; - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(self.finish()) - } -} - -impl serde::ser::SerializeSeq for SerializeSequence { - type Ok = IOValue; - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: Serialize, - { - self.vec.push(to_value(value)); - Ok(()) - } - - fn end(self) -> Result { - Ok(Value::from(self.vec).wrap()) - } -} - -/// Convenience function for directly converting a Serde-serializable `T` to an [IOValue]. -pub fn to_value(value: T) -> IOValue -where - T: Serialize, -{ - value.serialize(Serializer).unwrap() -} diff --git a/implementations/rust/preserves/src/value/signed_integer.rs b/implementations/rust/preserves/src/value/signed_integer.rs deleted file mode 100644 index a8142cd..0000000 --- a/implementations/rust/preserves/src/value/signed_integer.rs +++ /dev/null @@ -1,265 +0,0 @@ -//! Representation of Preserves `SignedInteger`s as [i128]/[u128] (if they fit) or [BigInt] (if -//! they don't). - -use num::bigint::BigInt; -use num::traits::cast::ToPrimitive; -use num::traits::sign::Signed; -use std::borrow::Cow; -use std::cmp::{Ord, Ordering, PartialOrd}; -use std::convert::TryFrom; -use std::convert::TryInto; -use std::fmt; - -/// Internal representation of Preserves `SignedInteger`s. -/// -/// Invariant: if I128 can be used, it will be; otherwise, if U128 can be used, it will be; -/// otherwise, Big will be used. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum SignedIntegerRepr { - I128(i128), - U128(u128), - Big(Box), -} - -/// Main representation of Preserves `SignedInteger`s. -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct SignedInteger(SignedIntegerRepr); - -impl fmt::Debug for SignedInteger { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{}n", self) - } -} - -impl fmt::Display for SignedInteger { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self.repr() { - SignedIntegerRepr::I128(i) => i.fmt(f), - SignedIntegerRepr::U128(u) => u.fmt(f), - SignedIntegerRepr::Big(n) => n.fmt(f), - } - } -} - -impl Ord for SignedInteger { - fn cmp(&self, other: &Self) -> Ordering { - match self.repr() { - SignedIntegerRepr::I128(i1) => match other.repr() { - SignedIntegerRepr::I128(i2) => i1.cmp(i2), - SignedIntegerRepr::U128(_) => { - if *i1 < 0 { - Ordering::Less - } else { - Ordering::Greater - } - } - SignedIntegerRepr::Big(n) => { - if n.is_negative() { - Ordering::Less - } else { - Ordering::Greater - } - } - }, - SignedIntegerRepr::U128(u1) => match other.repr() { - SignedIntegerRepr::I128(_) => Ordering::Greater, - SignedIntegerRepr::U128(u2) => u1.cmp(u2), - SignedIntegerRepr::Big(n) => { - if n.is_positive() { - Ordering::Less - } else { - Ordering::Greater - } - } - }, - SignedIntegerRepr::Big(n1) => match other.repr() { - SignedIntegerRepr::I128(_) | SignedIntegerRepr::U128(_) => { - if n1.is_negative() { - Ordering::Less - } else { - Ordering::Greater - } - } - SignedIntegerRepr::Big(n2) => n1.cmp(n2), - }, - } - } -} - -impl PartialOrd for SignedInteger { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl SignedInteger { - /// Extract the internal representation. - pub fn repr(&self) -> &SignedIntegerRepr { - &self.0 - } - - /// Does this `SignedInteger` fit in an [i128]? (See also [the TryFrom instance for - /// i128](#impl-TryFrom<%26SignedInteger>-for-i128).) - pub fn is_i(&self) -> bool { - matches!(self.0, SignedIntegerRepr::I128(_)) - } - - /// Does this `SignedInteger` fit in a [u128], but not an [i128]? (See also [the TryFrom - /// instance for u128](#impl-TryFrom<%26SignedInteger>-for-u128).) - pub fn is_u(&self) -> bool { - matches!(self.0, SignedIntegerRepr::U128(_)) - } - - /// Does this `SignedInteger` fit neither in a [u128] nor an [i128]? (See also [the TryFrom - /// instance for BigInt](#impl-From<%26'a+SignedInteger>-for-BigInt).) - pub fn is_big(&self) -> bool { - matches!(self.0, SignedIntegerRepr::Big(_)) - } -} - -//-- - -macro_rules! map_integral_type_to_signed_integer { - ($iN:ident, $uN:ident) => { - impl From<$iN> for SignedInteger { - fn from(v: $iN) -> Self { - SignedInteger(SignedIntegerRepr::I128(v.into())) - } - } - - impl From<$uN> for SignedInteger { - fn from(v: $uN) -> Self { - SignedInteger(SignedIntegerRepr::I128(v.into())) - } - } - - impl TryFrom<&SignedInteger> for $iN { - type Error = (); - fn try_from(v: &SignedInteger) -> Result { - i128::try_from(v)?.try_into().map_err(|_| ()) - } - } - - impl TryFrom<&SignedInteger> for $uN { - type Error = (); - fn try_from(v: &SignedInteger) -> Result { - u128::try_from(v)?.try_into().map_err(|_| ()) - } - } - }; -} - -map_integral_type_to_signed_integer!(i8, u8); -map_integral_type_to_signed_integer!(i16, u16); -map_integral_type_to_signed_integer!(i32, u32); -map_integral_type_to_signed_integer!(i64, u64); - -//-- - -impl From for SignedInteger { - fn from(v: i128) -> Self { - SignedInteger(SignedIntegerRepr::I128(v)) - } -} - -impl From for SignedInteger { - fn from(v: u128) -> Self { - if let Ok(w) = v.try_into() { - SignedInteger(SignedIntegerRepr::I128(w)) - } else { - SignedInteger(SignedIntegerRepr::U128(v)) - } - } -} - -impl TryFrom<&SignedInteger> for i128 { - type Error = (); - fn try_from(v: &SignedInteger) -> Result { - match v.repr() { - SignedIntegerRepr::I128(i) => Ok(*i), - SignedIntegerRepr::U128(_) => Err(()), - SignedIntegerRepr::Big(_) => Err(()), - } - } -} - -impl TryFrom<&SignedInteger> for u128 { - type Error = (); - fn try_from(v: &SignedInteger) -> Result { - match v.repr() { - SignedIntegerRepr::I128(i) => i.to_u128().ok_or(()), - SignedIntegerRepr::U128(u) => Ok(*u), - SignedIntegerRepr::Big(_) => Err(()), - } - } -} - -//-- - -impl From for SignedInteger { - fn from(v: BigInt) -> Self { - Self::from(Cow::Owned(v)) - } -} - -impl<'a> From<&'a SignedInteger> for BigInt { - fn from(v: &'a SignedInteger) -> Self { - match v.repr() { - SignedIntegerRepr::I128(i) => BigInt::from(*i), - SignedIntegerRepr::U128(u) => BigInt::from(*u), - SignedIntegerRepr::Big(n) => *n.clone(), - } - } -} - -//-- - -impl<'a> From> for SignedInteger { - fn from(v: Cow<'a, BigInt>) -> Self { - if let Some(w) = v.to_i128() { - SignedInteger(SignedIntegerRepr::I128(w)) - } else if let Some(w) = v.to_u128() { - SignedInteger(SignedIntegerRepr::U128(w)) - } else { - SignedInteger(SignedIntegerRepr::Big(Box::new(v.into_owned()))) - } - } -} - -impl<'a> From<&'a SignedInteger> for Cow<'a, BigInt> { - fn from(v: &'a SignedInteger) -> Self { - match v.repr() { - SignedIntegerRepr::I128(i) => Cow::Owned(BigInt::from(*i)), - SignedIntegerRepr::U128(u) => Cow::Owned(BigInt::from(*u)), - SignedIntegerRepr::Big(n) => Cow::Borrowed(n), - } - } -} - -//-- - -impl From for SignedInteger { - fn from(v: isize) -> Self { - SignedInteger(SignedIntegerRepr::I128(v as i128)) - } -} - -impl From for SignedInteger { - fn from(v: usize) -> Self { - SignedInteger(SignedIntegerRepr::U128(v as u128)) - } -} - -impl TryFrom<&SignedInteger> for isize { - type Error = (); - fn try_from(v: &SignedInteger) -> Result { - i128::try_from(v)?.try_into().map_err(|_| ()) - } -} - -impl TryFrom<&SignedInteger> for usize { - type Error = (); - fn try_from(v: &SignedInteger) -> Result { - u128::try_from(v)?.try_into().map_err(|_| ()) - } -} diff --git a/implementations/rust/preserves/src/value/suspendable.rs b/implementations/rust/preserves/src/value/suspendable.rs deleted file mode 100644 index 4e0d789..0000000 --- a/implementations/rust/preserves/src/value/suspendable.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![doc(hidden)] - -use std::ops::{Deref, DerefMut}; - -pub enum Suspendable { - Active(T), - Suspended, -} - -impl Suspendable { - pub fn new(t: T) -> Self { - Suspendable::Active(t) - } - - #[inline(always)] - pub fn suspend(&mut self) -> Self { - match self { - Suspendable::Active(_) => std::mem::replace(self, Suspendable::Suspended), - Suspendable::Suspended => panic!("Attempt to suspend suspended Suspendable"), - } - } - - #[inline(always)] - pub fn resume(&mut self, other: Self) { - match self { - Suspendable::Suspended => match other { - Suspendable::Active(_) => *self = other, - Suspendable::Suspended => panic!("Attempt to resume from suspended Suspendable"), - }, - Suspendable::Active(_) => panic!("Attempt to resume non-suspended Suspendable"), - } - } - - #[inline(always)] - pub fn take(self) -> T { - match self { - Suspendable::Active(t) => t, - Suspendable::Suspended => panic!("Attempt to take from suspended Suspendable"), - } - } -} - -impl Deref for Suspendable { - type Target = T; - #[inline(always)] - fn deref(&self) -> &Self::Target { - match self { - Suspendable::Suspended => panic!("Suspended Suspendable at deref"), - Suspendable::Active(t) => t, - } - } -} - -impl DerefMut for Suspendable { - #[inline(always)] - fn deref_mut(&mut self) -> &mut Self::Target { - match self { - Suspendable::Suspended => panic!("Empty Suspendable at deref_mut"), - Suspendable::Active(t) => t, - } - } -} diff --git a/implementations/rust/preserves/src/value/text/mod.rs b/implementations/rust/preserves/src/value/text/mod.rs deleted file mode 100644 index b7943fd..0000000 --- a/implementations/rust/preserves/src/value/text/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! Implements the Preserves [human-oriented text -//! syntax](https://preserves.dev/preserves-text.html). -//! -//! The main entry points for reading are functions [iovalue_from_str], -//! [annotated_iovalue_from_str], [from_str], and [annotated_from_str]. -//! -//! The main entry points for writing are [TextWriter::encode_iovalue] and -//! [TextWriter::encode]. -//! -//! # Summary of Text Syntax -#![doc = include_str!("../../../doc/cheatsheet-text-plaintext.md")] - -pub mod reader; -pub mod writer; - -pub use reader::TextReader; -pub use reader::ToplevelWhitespaceMode; -pub use writer::TextWriter; - -use crate::value::reader::BytesBinarySource; - -use std::io; - -use super::{DomainParse, IOValue, IOValueDomainCodec, NestedValue, Reader, ViaCodec}; - -/// Reads a value from the given string using the text syntax, discarding annotations. -pub fn from_str>( - s: &str, - decode_embedded: Dec, -) -> io::Result { - TextReader::new(&mut BytesBinarySource::new(s.as_bytes()), decode_embedded).demand_next(false) -} - -/// Reads an [IOValue] from the given string using the text syntax, discarding annotations. -pub fn iovalue_from_str(s: &str) -> io::Result { - from_str(s, ViaCodec::new(IOValueDomainCodec)) -} - -/// As [from_str], but includes annotations. -pub fn annotated_from_str>( - s: &str, - decode_embedded: Dec, -) -> io::Result { - TextReader::new(&mut BytesBinarySource::new(s.as_bytes()), decode_embedded).demand_next(true) -} - -/// As [iovalue_from_str], but includes annotations. -pub fn annotated_iovalue_from_str(s: &str) -> io::Result { - annotated_from_str(s, ViaCodec::new(IOValueDomainCodec)) -} diff --git a/implementations/rust/preserves/src/value/text/reader.rs b/implementations/rust/preserves/src/value/text/reader.rs deleted file mode 100644 index 2a853b2..0000000 --- a/implementations/rust/preserves/src/value/text/reader.rs +++ /dev/null @@ -1,715 +0,0 @@ -//! Implementation of [Reader] for the text syntax. - -use crate::error::io_syntax_error; -use crate::error::is_eof_io_error; -use crate::error::syntax_error; -use crate::error::Error; -use crate::error::ExpectedKind; -use crate::error::Received; - -use crate::hex; - -use crate::value::boundary as B; -use crate::value::reader::BinarySource; -use crate::value::reader::ReaderResult; -use crate::value::repr::Annotations; -use crate::value::CompoundClass; -use crate::value::DomainParse; -use crate::value::IOValue; -use crate::value::IOValueDomainCodec; -use crate::value::Map; -use crate::value::NestedValue; -use crate::value::Reader; -use crate::value::Record; -use crate::value::Set; -use crate::value::Token; -use crate::value::Value; -use crate::value::ViaCodec; - -use lazy_static::lazy_static; - -use num::bigint::BigInt; - -use std::convert::TryInto; -use std::io; -use std::marker::PhantomData; - -/// The text syntax Preserves reader. -pub struct TextReader<'de, 'src, N: NestedValue, Dec: DomainParse, S: BinarySource<'de>> { - /// Underlying source of (utf8) bytes. - pub source: &'src mut S, - /// Decoder for producing Rust values embedded in the text. - pub dec: Dec, - /// Treatment of whitespace before a toplevel term. - pub toplevel_whitespace_mode: ToplevelWhitespaceMode, - phantom: PhantomData<&'de N>, -} - -/// [TextReader] chooses `Document` mode to treat whitespace preceding end-of-file as a "no -/// more values" non-error situation, or `Value` mode to treat it as an "expected more input" -/// situation. -/// -/// The Preserves syntax for `Value` treats any input at all, even whitespace, as an indicator -/// that a term is to follow. However, when using a TextReader to parse a *series* of `Value`s -/// in a `Document`, whitespace followed by EOF is to be treated as the permitted optional -/// whitespace at the end of a `Document. -pub enum ToplevelWhitespaceMode { - Document, - Value, -} - -fn decode_utf8(bs: Vec) -> io::Result { - Ok(String::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?) -} - -fn append_codepoint(bs: &mut Vec, n: u32) -> io::Result<()> { - let c = char::from_u32(n).ok_or_else(|| io_syntax_error("Bad code point"))?; - let mut buf = [0; 4]; - let _ = c.encode_utf8(&mut buf); - bs.extend(&buf[0..c.len_utf8()]); - Ok(()) -} - -impl<'de, 'src, N: NestedValue, Dec: DomainParse, S: BinarySource<'de>> - TextReader<'de, 'src, N, Dec, S> -{ - /// Construct a new reader from a byte (utf8) source and embedded-value decoder. - pub fn new(source: &'src mut S, dec: Dec) -> Self { - TextReader { - source, - dec, - toplevel_whitespace_mode: ToplevelWhitespaceMode::Document, - phantom: PhantomData, - } - } - - pub fn toplevel_whitespace_mode(mut self, new_mode: ToplevelWhitespaceMode) -> Self { - self.toplevel_whitespace_mode = new_mode; - self - } - - fn peek(&mut self) -> io::Result { - self.source.peek() - } - - fn skip(&mut self) -> io::Result<()> { - self.source.skip() - } - - fn next_byte(&mut self) -> io::Result { - let b = self.source.peek()?; - self.source.skip()?; - Ok(b) - } - - fn skip_whitespace(&mut self) { - self.skip_whitespace_and_maybe_commas(false) - } - - fn skip_whitespace_and_maybe_commas(&mut self, skip_commas: bool) { - // Deliberately swallows errors. - while let Ok(c) = self.peek() { - match c { - b' ' | b'\t' | b'\r' | b'\n' => { - let _ = self.skip(); - () - } - b',' if skip_commas => { - let _ = self.skip(); - () - } - _ => break, - } - } - } - - // TODO: This is a duplicate of fn expected in PackedReader. - fn expected(&mut self, k: ExpectedKind) -> Error { - match Reader::::demand_next(self, true) { - Ok(v) => Error::Expected(k, Received::ReceivedOtherValue(format!("{:?}", v))), - Err(e) => e.into(), - } - } - - fn gather_annotations(&mut self, vs: &mut Vec) -> ReaderResult<()> { - loop { - self.skip_whitespace(); - match self.peek()? { - b'#' => { - let m = self.source.mark()?; - self.skip()?; - match self.next_byte()? { - b' ' | b'\t' => vs.push(N::new(self.comment_line()?)), - b'\n' | b'\r' => vs.push(N::new("")), - _ => { - self.source.restore(&m)?; - return Ok(()); - } - } - } - b'@' => { - self.skip()?; - vs.push(self.demand_next(true)?) - } - _ => return Ok(()), - } - } - } - - fn prepend_annotations_to_next(&mut self, mut annotations: Vec) -> ReaderResult { - let (existing_annotations, v) = Reader::::demand_next(self, true)?.pieces(); - annotations.extend_from_slice(existing_annotations.slice()); - Ok(N::wrap(Annotations::new(Some(annotations)), v)) - } - - fn skip_annotations(&mut self) -> ReaderResult<()> { - loop { - self.skip_whitespace(); - match self.peek()? { - b'#' => { - let m = self.source.mark()?; - self.skip()?; - match self.next_byte()? { - b' ' | b'\t' => { self.comment_line()?; () } - b'\n' | b'\r' => (), - _ => { - self.source.restore(&m)?; - return Ok(()); - } - } - } - b'@' => { - self.skip()?; - self.skip_value()?; - } - _ => return Ok(()), - } - } - } - - /// Retrieve the next [IOValue] in the input stream. - pub fn next_iovalue(&mut self, read_annotations: bool) -> io::Result { - let mut r = TextReader::new(self.source, ViaCodec::new(IOValueDomainCodec)); - let v = r.demand_next(read_annotations)?; - Ok(v) - } - - fn comment_line(&mut self) -> io::Result { - let mut bs = Vec::new(); - loop { - let b = self.peek()?; - self.skip()?; - match b { - b'\r' | b'\n' => return Ok(decode_utf8(bs)?), - _ => bs.push(b), - } - } - } - - fn read_hex_float(&mut self) -> io::Result { - if self.next_byte()? != b'"' { - return Err(io_syntax_error( - "Missing open-double-quote in hex-encoded floating-point number", - )); - } - let bs = self.read_hex_binary()?; - if bs.len() != 8 { - return Err(io_syntax_error( - "Incorrect number of bytes in hex-encoded floating-point number", - )); - } - Ok(Value::from(f64::from_bits(u64::from_be_bytes(bs.try_into().unwrap()))).wrap()) - } - - fn read_stringlike( - &mut self, - mut seed: R, - xform_item: X, - terminator: u8, - hexescape: u8, - hexescaper: H, - ) -> io::Result - where - X: Fn(&mut R, u8) -> io::Result<()>, - H: Fn(&mut R, &mut Self) -> io::Result<()>, - { - loop { - match self.next_byte()? { - c if c == terminator => return Ok(seed), - b'\\' => match self.next_byte()? { - c if c == hexescape => hexescaper(&mut seed, self)?, - c if c == terminator || c == b'\\' || c == b'/' => xform_item(&mut seed, c)?, - b'b' => xform_item(&mut seed, b'\x08')?, - b'f' => xform_item(&mut seed, b'\x0c')?, - b'n' => xform_item(&mut seed, b'\x0a')?, - b'r' => xform_item(&mut seed, b'\x0d')?, - b't' => xform_item(&mut seed, b'\x09')?, - _ => return Err(io_syntax_error("Invalid escape code")), - }, - c => xform_item(&mut seed, c)?, - } - } - } - - fn hexnum(&mut self, count: usize) -> io::Result { - let mut v: u32 = 0; - for _ in 0..count { - let c = self.next_byte()?; - match (c as char).to_digit(16) { - Some(d) => v = v << 4 | d, - None => return Err(io_syntax_error("Bad hex escape")), - } - } - Ok(v) - } - - fn read_string(&mut self, delimiter: u8) -> io::Result { - decode_utf8(self.read_stringlike( - Vec::new(), - |bs, c| Ok(bs.push(c)), - delimiter, - b'u', - |bs, r| { - let n1 = r.hexnum(4)?; - if (0xd800..=0xdbff).contains(&n1) { - let mut ok = true; - ok = ok && r.next_byte()? == b'\\'; - ok = ok && r.next_byte()? == b'u'; - if !ok { - Err(io_syntax_error("Missing second half of surrogate pair")) - } else { - let n2 = r.hexnum(4)?; - if (0xdc00..=0xdfff).contains(&n2) { - let n = ((n1 - 0xd800) << 10) + (n2 - 0xdc00) + 0x10000; - append_codepoint(bs, n) - } else { - Err(io_syntax_error("Bad second half of surrogate pair")) - } - } - } else { - append_codepoint(bs, n1) - } - }, - )?) - } - - fn read_literal_binary(&mut self) -> io::Result { - Ok(N::new( - &self.read_stringlike( - Vec::new(), - |bs, b| Ok(bs.push(b)), - b'"', - b'x', - |bs, r| Ok(bs.push(r.hexnum(2)? as u8)), - )?[..], - )) - } - - fn read_hex_binary(&mut self) -> io::Result> { - let mut s = String::new(); - loop { - self.skip_whitespace(); - let c1 = self.next_byte()? as char; - if c1 == '"' { - return Ok(hex::HexParser::Strict.decode(&s).unwrap()); - } - let c2 = self.next_byte()? as char; - if !(c1.is_digit(16) && c2.is_digit(16)) { - return Err(io_syntax_error("Invalid hex binary")); - } - s.push(c1); - s.push(c2); - } - } - - fn read_base64_binary(&mut self) -> io::Result { - let mut bs = Vec::new(); - loop { - self.skip_whitespace(); - let mut c = self.next_byte()?; - if c == b']' { - let bs = base64::decode_config(&decode_utf8(bs)?, base64::STANDARD_NO_PAD) - .map_err(|_| io_syntax_error("Invalid base64 character"))?; - return Ok(N::new(&bs[..])); - } - if c == b'-' { - c = b'+'; - } - if c == b'_' { - c = b'/'; - } - if c == b'=' { - continue; - } - bs.push(c); - } - } - - fn upto(&mut self, delimiter: u8, read_annotations: bool, skip_commas: bool) -> io::Result> { - let mut vs = Vec::new(); - loop { - self.skip_whitespace_and_maybe_commas(skip_commas); - if self.peek()? == delimiter { - self.skip()?; - return Ok(vs); - } - vs.push(Reader::::demand_next(self, read_annotations)?); - } - } - - fn read_set(&mut self, read_annotations: bool) -> io::Result { - let items = self.upto(b'}', read_annotations, true)?; - let mut s = Set::::new(); - for i in items { - if s.contains(&i) { - return Err(io_syntax_error("Duplicate set element")); - } - s.insert(i); - } - Ok(N::new(s)) - } - - fn read_dictionary(&mut self, read_annotations: bool) -> io::Result { - let mut d = Map::new(); - loop { - self.skip_whitespace_and_maybe_commas(true); - if self.peek()? == b'}' { - self.skip()?; - return Ok(N::new(d)); - } - let k = Reader::::demand_next(self, read_annotations)?; - self.skip_whitespace(); - if self.next_byte()? != b':' { - return Err(io_syntax_error("Missing expected key/value separator")); - } - if d.contains_key(&k) { - return Err(io_syntax_error("Duplicate key")); - } - let v = Reader::::demand_next(self, read_annotations)?; - d.insert(k, v); - } - } - - fn require_delimiter(&mut self, msg: &'static str) -> io::Result<()> { - if self.delimiter_follows()? { - Ok(()) - } else { - Err(io_syntax_error(msg)) - } - } - - fn delimiter_follows(&mut self) -> io::Result { - let c = match self.peek() { - Err(e) if is_eof_io_error(&e) => return Ok(true), - Err(e) => return Err(e)?, - Ok(c) if (c as char).is_whitespace() => return Ok(true), - Ok(c) => c, - }; - Ok(match c { - b'(' | b')' | b'{' | b'}' | b'[' | b']' | b'<' | b'>' | b'"' | b';' | b',' - | b'@' | b'#' | b':' | b'|' | b' ' => true, - _ => false, - }) - } - - fn read_raw_symbol_or_number(&mut self, mut bs: Vec) -> io::Result { - lazy_static! { - static ref NUMBER_RE: regex::Regex = - regex::Regex::new(r"^([-+]?\d+)((\.\d+([eE][-+]?\d+)?)|([eE][-+]?\d+))?$") - .unwrap(); - } - while !self.delimiter_follows()? { - bs.push(self.next_byte()?); - } - let s = decode_utf8(bs)?; - match NUMBER_RE.captures(&s) { - None => Ok(N::symbol(&s)), - Some(m) => match m.get(2) { - None => Ok(N::new(s.parse::().map_err(|_| { - io_syntax_error(&format!("Invalid signed-integer number: {:?}", s))})?)), - Some(_) => Ok(N::new(s.parse::().map_err(|_| { - io_syntax_error(&format!("Invalid double-precision number: {:?}", s))})?)), - }, - } - } -} - -impl<'de, 'src, N: NestedValue, Dec: DomainParse, S: BinarySource<'de>> Reader<'de, N> - for TextReader<'de, 'src, N, Dec, S> -{ - fn next(&mut self, read_annotations: bool) -> io::Result> { - 'restart: loop { - match self.toplevel_whitespace_mode { - ToplevelWhitespaceMode::Document => self.skip_whitespace(), - ToplevelWhitespaceMode::Value => (), - } - match self.peek() { - Err(e) if is_eof_io_error(&e) => return Ok(None), - _ => (), - } - match self.toplevel_whitespace_mode { - ToplevelWhitespaceMode::Document => (), - ToplevelWhitespaceMode::Value => self.skip_whitespace(), - } - return Ok(Some(match self.peek()? { - b'"' => { - self.skip()?; - N::new(self.read_string(b'"')?) - } - b'|' => { - self.skip()?; - N::symbol(&self.read_string(b'|')?) - } - b';' => { - return Err(io_syntax_error( - "Semicolon is reserved syntax" - )); - } - b'@' => { - if read_annotations { - let mut annotations = Vec::new(); - self.gather_annotations(&mut annotations)?; - self.prepend_annotations_to_next(annotations)? - } else { - self.skip_annotations()?; - self.demand_next(read_annotations)? - } - } - b':' => { - return Err(io_syntax_error( - "Unexpected key/value separator between items", - )); - } - b'#' => { - self.skip()?; - match self.next_byte()? { - b' ' | b'\t' => { - if read_annotations { - let mut annotations = vec![N::new(self.comment_line()?)]; - self.gather_annotations(&mut annotations)?; - self.prepend_annotations_to_next(annotations)? - } else { - self.comment_line()?; - continue 'restart; - } - } - b'\n' | b'\r' => { - if read_annotations { - let mut annotations = vec![N::new("")]; - self.gather_annotations(&mut annotations)?; - self.prepend_annotations_to_next(annotations)? - } else { - continue 'restart; - } - } - b'f' => { self.require_delimiter("Delimiter must follow #f")?; N::new(false) } - b't' => { self.require_delimiter("Delimiter must follow #t")?; N::new(true) } - b'{' => self.read_set(read_annotations)?, - b'"' => self.read_literal_binary()?, - b'x' => match self.next_byte()? { - b'"' => N::new(&self.read_hex_binary()?[..]), - b'd' => self.read_hex_float()?, - _ => return Err(io_syntax_error("Invalid #x syntax")), - }, - b'[' => self.read_base64_binary()?, - b'!' => { - let v = self.next_iovalue(read_annotations)?; - Value::Embedded(self.dec.parse_embedded(&v)?).wrap() - } - other => { - return Err(io_syntax_error(&format!("Invalid # syntax: {:?}", other))) - } - } - } - b'<' => { - self.skip()?; - let vs = self.upto(b'>', read_annotations, false)?; - if vs.is_empty() { - return Err(io_syntax_error("Missing record label")); - } - Value::Record(Record(vs)).wrap() - } - b'[' => { - self.skip()?; - N::new(self.upto(b']', read_annotations, true)?) - } - b'{' => { - self.skip()?; - self.read_dictionary(read_annotations)? - } - b'>' => return Err(io_syntax_error("Unexpected >")), - b']' => return Err(io_syntax_error("Unexpected ]")), - b'}' => return Err(io_syntax_error("Unexpected }")), - b',' => return Err(io_syntax_error("Unexpected ,")), - other => { - self.skip()?; - self.read_raw_symbol_or_number(vec![other])? - } - })) - } - } - - fn open_record(&mut self, arity: Option) -> ReaderResult { - self.skip_annotations()?; - if self.peek()? != b'<' { - return Err(self.expected(ExpectedKind::Record(arity))); - } - self.skip()?; - let mut b = B::Type::default(); - Reader::::ensure_more_expected(self, &mut b, &B::Item::RecordLabel)?; - Ok(b) - } - - fn open_sequence_or_set(&mut self) -> ReaderResult { - self.skip_annotations()?; - let mark = Reader::::mark(self)?; - match self.next_byte()? { - b'#' => match self.next_byte()? { - b'{' => return Ok(B::Item::SetValue), - _ => (), - }, - b'[' => return Ok(B::Item::SequenceValue), - _ => (), - } - Reader::::restore(self, &mark)?; - Err(self.expected(ExpectedKind::SequenceOrSet)) - } - - fn open_sequence(&mut self) -> ReaderResult<()> { - self.skip_annotations()?; - if self.peek()? != b'[' { - return Err(self.expected(ExpectedKind::Sequence)); - } - self.skip()?; - Ok(()) - } - - fn open_set(&mut self) -> ReaderResult<()> { - self.skip_annotations()?; - let mark = Reader::::mark(self)?; - match self.next_byte()? { - b'#' => match self.next_byte()? { - b'{' => return Ok(()), - _ => (), - }, - _ => (), - } - Reader::::restore(self, &mark)?; - Err(self.expected(ExpectedKind::Set)) - } - - fn open_dictionary(&mut self) -> ReaderResult<()> { - self.skip_annotations()?; - if self.peek()? != b'{' { - return Err(self.expected(ExpectedKind::Dictionary)); - } - self.skip()?; - Ok(()) - } - - #[inline] - fn boundary(&mut self, b: &B::Type) -> ReaderResult<()> { - match b { - B::Type { - closing: Some(B::Item::DictionaryKey), - opening: Some(B::Item::DictionaryValue), - } => { - self.skip_whitespace(); - if self.next_byte()? != b':' { - return Err(syntax_error("Missing expected key/value separator")); - } - } - B::Type { closing: Some(B::Item::DictionaryValue), opening: None } | - B::Type { closing: None, opening: Some(B::Item::DictionaryKey) } | - B::Type { closing: Some(B::Item::SetValue), opening: _ } | - B::Type { closing: _, opening: Some(B::Item::SetValue) } | - B::Type { closing: Some(B::Item::SequenceValue), opening: _ } | - B::Type { closing: _, opening: Some(B::Item::SequenceValue) } | - B::Type { - closing: Some(B::Item::DictionaryValue), - opening: Some(B::Item::DictionaryKey), - } => { - self.skip_whitespace_and_maybe_commas(true); - } - _ => (), - } - Ok(()) - } - - fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult { - self.skip_whitespace(); - match self.peek()? { - b'>' | b']' | b'}' => { - self.skip()?; - Ok(true) - } - _ => { - b.shift(Some(i.clone())); - Reader::::boundary(self, b)?; - Ok(false) - } - } - } - - fn open_embedded(&mut self) -> ReaderResult<()> { - self.skip_annotations()?; - let mark = Reader::::mark(self)?; - match self.next_byte()? { - b'#' => match self.next_byte()? { - b'!' => return Ok(()), - _ => (), - }, - _ => (), - } - Reader::::restore(self, &mark)?; - Err(self.expected(ExpectedKind::Embedded)) - } - - fn close_embedded(&mut self) -> ReaderResult<()> { - 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> { - self.skip_annotations()?; - let mark = Reader::::mark(self)?; - Ok(match self.next_byte()? { - b'<' => Token::Compound(CompoundClass::Record), - b'[' => Token::Compound(CompoundClass::Sequence), - b'{' => Token::Compound(CompoundClass::Dictionary), - b'>' => Token::End, - b']' => Token::End, - b'}' => Token::End, - b'#' => match self.next_byte()? { - b'!' => { - let v = self.next_iovalue(read_embedded_annotations)?; - Token::Embedded(self.dec.parse_embedded(&v)?) - } - b'{' => Token::Compound(CompoundClass::Set), - _ => { - Reader::::restore(self, &mark)?; - Token::Atom(self.demand_next(false)?) - } - }, - _ => { - Reader::::restore(self, &mark)?; - Token::Atom(self.demand_next(false)?) - } - }) - } - - fn next_annotations_and_token(&mut self) -> io::Result<(Vec, Token)> { - let mut annotations = Vec::new(); - self.gather_annotations(&mut annotations)?; - Ok((annotations, self.next_token(true)?)) - } -} diff --git a/implementations/rust/preserves/src/value/text/writer.rs b/implementations/rust/preserves/src/value/text/writer.rs deleted file mode 100644 index 69051e5..0000000 --- a/implementations/rust/preserves/src/value/text/writer.rs +++ /dev/null @@ -1,379 +0,0 @@ -//! Implementation of [Writer] for the text syntax. - -use crate::hex::HexFormatter; -use crate::value::suspendable::Suspendable; -use crate::value::writer::CompoundWriter; -use crate::value::DomainEncode; -use crate::value::IOValue; -use crate::value::IOValueDomainCodec; -use crate::value::NestedValue; -use crate::value::Writer; - -use lazy_static::lazy_static; - -use num::bigint::BigInt; - -use std::io; - -use super::super::boundary as B; - -/// Specifies a comma style for printing using [TextWriter]. -#[derive(Clone, Copy, Debug)] -pub enum CommaStyle { - /// No commas will be printed. (Preserves text syntax treats commas as whitespace (!).) - None, - /// Commas will be used to separate subterms. - Separating, - /// Commas will be used to terminate subterms. - Terminating, -} - -/// The (optionally pretty-printing) text syntax Preserves writer. -pub struct TextWriter { - w: Suspendable, - /// Selects a comma style to use when printing. - pub comma_style: CommaStyle, - /// Specifies indentation to use when pretty-printing; 0 disables pretty-printing. - pub indentation: usize, - /// An aid to use of printed terms in shell scripts: set `true` to escape spaces embedded - /// in strings and symbols. - pub escape_spaces: bool, - indent: String, -} - -impl std::default::Default for CommaStyle { - fn default() -> Self { - CommaStyle::Separating - } -} - -impl TextWriter<&mut Vec> { - /// Writes `v` to `f` using text syntax. Selects indentation mode based on - /// [`f.alternate()`][std::fmt::Formatter::alternate]. - pub fn fmt_value>( - f: &mut std::fmt::Formatter<'_>, - enc: &mut Enc, - v: &crate::value::Value, - ) -> io::Result<()> { - let mut buf: Vec = Vec::new(); - let mut w = TextWriter::new(&mut buf); - if f.alternate() { - w.indentation = 4 - } - w.write_value(enc, v)?; - f.write_str(std::str::from_utf8(&buf).expect("valid UTF-8 from TextWriter")) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "could not append to Formatter")) - } - - /// Encode `v` to a [String]. - pub fn encode>( - enc: &mut Enc, - v: &N, - ) -> io::Result { - let mut buf: Vec = Vec::new(); - TextWriter::new(&mut buf).write(enc, v)?; - Ok(String::from_utf8(buf).expect("valid UTF-8 from TextWriter")) - } - - /// Encode `v` to a [String]. - pub fn encode_iovalue(v: &IOValue) -> io::Result { - Self::encode(&mut IOValueDomainCodec, v) - } -} - -impl TextWriter { - /// Construct a writer from the given byte sink `w`. - pub fn new(w: W) -> Self { - TextWriter { - w: Suspendable::new(w), - comma_style: CommaStyle::default(), - indentation: 0, - escape_spaces: false, - indent: "\n".to_owned(), - } - } - - /// Update selected comma-printing style. - pub fn set_comma_style(mut self, v: CommaStyle) -> Self { - self.comma_style = v; - self - } - - /// Update selected space-escaping style. - pub fn set_escape_spaces(mut self, v: bool) -> Self { - self.escape_spaces = v; - self - } - - #[doc(hidden)] - pub fn suspend(&mut self) -> Self { - TextWriter { - w: self.w.suspend(), - indent: self.indent.clone(), - ..*self - } - } - - #[doc(hidden)] - pub fn resume(&mut self, other: Self) { - self.w.resume(other.w) - } - - #[doc(hidden)] - pub fn write_stringlike_char_fallback(&mut self, c: char, f: F) -> io::Result<()> - where - F: FnOnce(&mut W, char) -> io::Result<()>, - { - match c { - '\\' => write!(self.w, "\\\\"), - '\x08' => write!(self.w, "\\b"), - '\x0c' => write!(self.w, "\\f"), - '\x0a' => write!(self.w, "\\n"), - '\x0d' => write!(self.w, "\\r"), - '\x09' => write!(self.w, "\\t"), - _ => f(&mut self.w, c), - } - } - - #[doc(hidden)] - pub fn write_stringlike_char(&mut self, c: char) -> io::Result<()> { - self.write_stringlike_char_fallback(c, |w, c| write!(w, "{}", c)) - } - - #[doc(hidden)] - pub fn add_indent(&mut self) { - for _ in 0..self.indentation { - self.indent.push(' ') - } - } - - #[doc(hidden)] - pub fn del_indent(&mut self) { - if self.indentation > 0 { - self.indent.truncate(self.indent.len() - self.indentation) - } - } - - #[doc(hidden)] - pub fn indent(&mut self) -> io::Result<()> { - if self.indentation > 0 { - write!(self.w, "{}", &self.indent) - } else { - Ok(()) - } - } - - #[doc(hidden)] - pub fn indent_sp(&mut self) -> io::Result<()> { - if self.indentation > 0 { - write!(self.w, "{}", &self.indent) - } else { - write!(self.w, " ") - } - } - - /// Borrow the underlying byte sink. - pub fn borrow_write(&mut self) -> &mut W { - &mut self.w - } -} - -impl CompoundWriter for TextWriter { - #[inline] - fn boundary(&mut self, b: &B::Type) -> io::Result<()> { - match (b.closing.as_ref(), b.opening.as_ref()) { - (None, Some(B::Item::RecordLabel)) - | (Some(B::Item::RecordLabel), None) - | (Some(B::Item::RecordField), None) => return Ok(()), - (_, Some(B::Item::RecordField)) => return write!(self.w, " "), - - (Some(B::Item::DictionaryKey), Some(B::Item::DictionaryValue)) => { - return write!(self.w, ": ") - } - - (None, Some(B::Item::Annotation)) => return write!(self.w, "@"), - (Some(_), Some(B::Item::Annotation)) => return write!(self.w, " @"), - (Some(B::Item::Annotation), Some(B::Item::AnnotatedValue)) => { - return write!(self.w, " ") - } - (Some(B::Item::AnnotatedValue), None) => return Ok(()), - - _ => (), - } - - match (b.closing.as_ref(), b.opening.as_ref()) { - (None, None) => (), - (None, Some(_)) => { - self.add_indent(); - self.indent()? - } - (Some(_), Some(_)) => { - match self.comma_style { - CommaStyle::Separating | CommaStyle::Terminating => write!(self.w, ",")?, - CommaStyle::None => (), - } - self.indent_sp()? - } - (Some(_), None) => { - match self.comma_style { - CommaStyle::Terminating => write!(self.w, ",")?, - CommaStyle::Separating | CommaStyle::None => (), - } - self.del_indent(); - self.indent()? - } - } - - Ok(()) - } -} - -macro_rules! simple_writer_method { - ($n:ident, $argty:ty) => { - fn $n(&mut self, v: $argty) -> io::Result<()> { - write!(self.w, "{}", v) - } - }; -} - -impl Writer for TextWriter { - type AnnWriter = Self; - type RecWriter = Self; - type SeqWriter = Self; - type SetWriter = Self; - type DictWriter = Self; - type EmbeddedWriter = Self; - - fn start_annotations(&mut self) -> io::Result { - Ok(self.suspend()) - } - - fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()> { - self.resume(ann); - Ok(()) - } - - fn write_bool(&mut self, v: bool) -> io::Result<()> { - write!(self.w, "{}", if v { "#t" } else { "#f" }) - } - - fn write_f64(&mut self, v: f64) -> io::Result<()> { - if v.is_nan() || v.is_infinite() { - write!( - self.w, - "#xd\"{}\"", - HexFormatter::Packed.encode(&u64::to_be_bytes(f64::to_bits(v))) - ) - } else { - dtoa::write(&mut *self.w, v)?; - Ok(()) - } - } - - simple_writer_method!(write_i8, i8); - simple_writer_method!(write_u8, u8); - simple_writer_method!(write_i16, i16); - simple_writer_method!(write_u16, u16); - simple_writer_method!(write_i32, i32); - simple_writer_method!(write_u32, u32); - simple_writer_method!(write_i64, i64); - simple_writer_method!(write_u64, u64); - simple_writer_method!(write_i128, i128); - simple_writer_method!(write_u128, u128); - simple_writer_method!(write_int, &BigInt); - - fn write_string(&mut self, v: &str) -> io::Result<()> { - write!(self.w, "\"")?; - for c in v.chars() { - match c { - '"' => write!(self.w, "\\\"")?, - ' ' if self.escape_spaces => write!(self.w, "\\u0020")?, - _ => self.write_stringlike_char(c)?, - } - } - write!(self.w, "\"") - } - - fn write_bytes(&mut self, v: &[u8]) -> io::Result<()> { - write!( - self.w, - "#[{}]", - base64::encode_config(v, base64::URL_SAFE_NO_PAD) - ) - } - - fn write_symbol(&mut self, v: &str) -> io::Result<()> { - lazy_static! { - // FIXME: This regular expression is conservatively correct, but Anglo-chauvinistic. - static ref RE: regex::Regex = - regex::Regex::new("^[-a-zA-Z0-9~!$%^&*?_=+/.]+$").unwrap(); - } - if RE.is_match(v) { - write!(self.w, "{}", v) - } else { - write!(self.w, "|")?; - for c in v.chars() { - match c { - '|' => write!(self.w, "\\|")?, - ' ' if self.escape_spaces => write!(self.w, "\\u0020")?, - _ => self.write_stringlike_char(c)?, - } - } - write!(self.w, "|") - } - } - - fn start_record(&mut self, _field_count: Option) -> io::Result { - write!(self.w, "<")?; - Ok(self.suspend()) - } - - fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> { - self.resume(rec); - write!(self.w, ">") - } - - fn start_sequence(&mut self, _item_count: Option) -> io::Result { - write!(self.w, "[")?; - Ok(self.suspend()) - } - - fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> { - self.resume(seq); - write!(self.w, "]") - } - - fn start_set(&mut self, _item_count: Option) -> io::Result { - write!(self.w, "#{{")?; - Ok(self.suspend()) - } - - fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> { - self.resume(set); - write!(self.w, "}}") - } - - fn start_dictionary(&mut self, _entry_count: Option) -> io::Result { - write!(self.w, "{{")?; - Ok(self.suspend()) - } - - fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> { - self.resume(dict); - write!(self.w, "}}") - } - - fn start_embedded(&mut self) -> io::Result { - write!(self.w, "#!")?; - Ok(self.suspend()) - } - - fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()> { - self.resume(ptr); - Ok(()) - } - - fn flush(&mut self) -> io::Result<()> { - self.w.flush() - } -} diff --git a/implementations/rust/preserves/src/value/writer.rs b/implementations/rust/preserves/src/value/writer.rs deleted file mode 100644 index 660171e..0000000 --- a/implementations/rust/preserves/src/value/writer.rs +++ /dev/null @@ -1,232 +0,0 @@ -//! Generic [Writer] trait for unparsing Preserves [Value]s, implemented by code that provides -//! each specific transfer syntax. - -use super::boundary as B; -use super::repr::{Double, NestedValue, Value}; -use super::signed_integer::SignedIntegerRepr; -use super::DomainEncode; -use num::bigint::BigInt; -use std::io; - -#[doc(hidden)] -/// Utility trait for tracking unparser state during production of compound `Value`s. -pub trait CompoundWriter: Writer { - fn boundary(&mut self, b: &B::Type) -> io::Result<()>; -} - -/// Generic unparser for Preserves. -pub trait Writer: Sized { - // Hiding these from the documentation for the moment because I don't want to have to - // document the whole Boundary thing. - #[doc(hidden)] - type AnnWriter: CompoundWriter; - #[doc(hidden)] - type RecWriter: CompoundWriter; - #[doc(hidden)] - type SeqWriter: CompoundWriter; - #[doc(hidden)] - type SetWriter: CompoundWriter; - #[doc(hidden)] - type DictWriter: CompoundWriter; - #[doc(hidden)] - type EmbeddedWriter: Writer; - - #[doc(hidden)] - fn start_annotations(&mut self) -> io::Result; - #[doc(hidden)] - fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()>; - - #[doc(hidden)] - fn write_bool(&mut self, v: bool) -> io::Result<()>; - - #[doc(hidden)] - fn write_f64(&mut self, v: f64) -> io::Result<()>; - - #[doc(hidden)] - fn write_i8(&mut self, v: i8) -> io::Result<()>; - #[doc(hidden)] - fn write_u8(&mut self, v: u8) -> io::Result<()>; - #[doc(hidden)] - fn write_i16(&mut self, v: i16) -> io::Result<()>; - #[doc(hidden)] - fn write_u16(&mut self, v: u16) -> io::Result<()>; - #[doc(hidden)] - fn write_i32(&mut self, v: i32) -> io::Result<()>; - #[doc(hidden)] - fn write_u32(&mut self, v: u32) -> io::Result<()>; - #[doc(hidden)] - fn write_i64(&mut self, v: i64) -> io::Result<()>; - #[doc(hidden)] - fn write_u64(&mut self, v: u64) -> io::Result<()>; - #[doc(hidden)] - fn write_i128(&mut self, v: i128) -> io::Result<()>; - #[doc(hidden)] - fn write_u128(&mut self, v: u128) -> io::Result<()>; - #[doc(hidden)] - fn write_int(&mut self, v: &BigInt) -> io::Result<()>; - - #[doc(hidden)] - fn write_string(&mut self, v: &str) -> io::Result<()>; - #[doc(hidden)] - fn write_bytes(&mut self, v: &[u8]) -> io::Result<()>; - #[doc(hidden)] - fn write_symbol(&mut self, v: &str) -> io::Result<()>; - - #[doc(hidden)] - fn start_record(&mut self, field_count: Option) -> io::Result; - #[doc(hidden)] - fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()>; - - #[doc(hidden)] - fn start_sequence(&mut self, item_count: Option) -> io::Result; - #[doc(hidden)] - fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()>; - - #[doc(hidden)] - fn start_set(&mut self, item_count: Option) -> io::Result; - #[doc(hidden)] - fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()>; - - #[doc(hidden)] - fn start_dictionary(&mut self, entry_count: Option) -> io::Result; - #[doc(hidden)] - fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()>; - - #[doc(hidden)] - fn start_embedded(&mut self) -> io::Result; - #[doc(hidden)] - fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()>; - - /// Flushes any buffered output. - fn flush(&mut self) -> io::Result<()>; - - //--------------------------------------------------------------------------- - - /// Writes [NestedValue] `v` to the output of this [Writer]. - fn write>( - &mut self, - enc: &mut Enc, - v: &N, - ) -> io::Result<()> { - match v.annotations().maybe_slice() { - None => { - self.write_value(enc, v.value())?; - } - Some(anns) => { - let mut a = self.start_annotations()?; - let mut b = B::Type::default(); - for ann in anns { - b.shift(Some(B::Item::Annotation)); - a.boundary(&b)?; - a.write(enc, ann)?; - } - b.shift(Some(B::Item::AnnotatedValue)); - a.boundary(&b)?; - a.write_value(enc, v.value())?; - b.shift(None); - a.boundary(&b)?; - self.end_annotations(a)?; - } - } - Ok(()) - } - - /// Writes [Value] `v` to the output of this [Writer]. - fn write_value>( - &mut self, - enc: &mut Enc, - v: &Value, - ) -> io::Result<()> { - match v { - Value::Boolean(b) => self.write_bool(*b), - Value::Double(Double(d)) => self.write_f64(*d), - Value::SignedInteger(n) => match n.repr() { - SignedIntegerRepr::I128(i) => self.write_i128(*i), - SignedIntegerRepr::U128(u) => self.write_u128(*u), - SignedIntegerRepr::Big(n) => self.write_int(n), - }, - Value::String(s) => self.write_string(s), - Value::ByteString(bs) => self.write_bytes(bs), - Value::Symbol(s) => self.write_symbol(s), - Value::Record(r) => { - let mut c = self.start_record(Some(r.arity()))?; - let mut b = B::start(B::Item::RecordLabel); - c.boundary(&b)?; - c.write(enc, r.label())?; - for f in r.fields() { - b.shift(Some(B::Item::RecordField)); - c.boundary(&b)?; - c.write(enc, f)?; - } - b.shift(None); - c.boundary(&b)?; - self.end_record(c) - } - Value::Sequence(vs) => { - let mut c = self.start_sequence(Some(vs.len()))?; - let mut b = B::Type::default(); - for v in vs { - b.shift(Some(B::Item::SequenceValue)); - c.boundary(&b)?; - c.write(enc, v)?; - } - b.shift(None); - c.boundary(&b)?; - self.end_sequence(c) - } - Value::Set(vs) => { - let mut c = self.start_set(Some(vs.len()))?; - let mut b = B::Type::default(); - for v in vs { - b.shift(Some(B::Item::SetValue)); - c.boundary(&b)?; - c.write(enc, v)?; - } - b.shift(None); - c.boundary(&b)?; - self.end_set(c) - } - Value::Dictionary(vs) => { - let mut c = self.start_dictionary(Some(vs.len()))?; - let mut b = B::Type::default(); - for (k, v) in vs { - b.shift(Some(B::Item::DictionaryKey)); - c.boundary(&b)?; - c.write(enc, k)?; - b.shift(Some(B::Item::DictionaryValue)); - c.boundary(&b)?; - c.write(enc, v)?; - } - b.shift(None); - c.boundary(&b)?; - self.end_dictionary(c) - } - Value::Embedded(d) => { - let mut c = self.start_embedded()?; - enc.encode_embedded(&mut c, d)?; - self.end_embedded(c) - } - } - } -} - -/// Writes a [varint](https://protobuf.dev/programming-guides/encoding/#varints) to `w`. -/// Returns the number of bytes written. -/// -/// ```text -/// varint(n) = [n] if n < 128 -/// [(n & 127) | 128] ++ varint(n >> 7) if n ≥ 128 -/// ``` -pub fn varint(w: &mut W, mut v: u64) -> io::Result { - let mut byte_count = 0; - loop { - byte_count += 1; - if v < 128 { - w.write_all(&[v as u8])?; - return Ok(byte_count); - } else { - w.write_all(&[((v & 0x7f) + 128) as u8])?; - v >>= 7; - } - } -} diff --git a/implementations/rust/preserves/tests/samples/mod.rs b/implementations/rust/preserves/tests/samples/mod.rs deleted file mode 100644 index d127194..0000000 --- a/implementations/rust/preserves/tests/samples/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -use preserves::symbol::Symbol; -use preserves::value::{IOValue, Map}; - -#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct TestCases { - pub tests: Map, -} - -#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub enum TestCase { - Test(#[serde(with = "serde_bytes")] Vec, IOValue), - NondeterministicTest(#[serde(with = "serde_bytes")] Vec, IOValue), - ParseError(String), - ParseShort(String), - ParseEOF(String), - DecodeError(#[serde(with = "serde_bytes")] Vec), - DecodeShort(#[serde(with = "serde_bytes")] Vec), - DecodeEOF(#[serde(with = "serde_bytes")] Vec), -} diff --git a/implementations/rust/preserves/tests/samples_tests.rs b/implementations/rust/preserves/tests/samples_tests.rs deleted file mode 100644 index 7df7212..0000000 --- a/implementations/rust/preserves/tests/samples_tests.rs +++ /dev/null @@ -1,214 +0,0 @@ -use preserves::error::{is_eof_io_error, is_syntax_io_error}; -use preserves::symbol::Symbol; -use preserves::value::de::from_value as deserialize_from_value; -use preserves::value::BinarySource; -use preserves::value::BytesBinarySource; -use preserves::value::IOBinarySource; -use preserves::value::IOValue; -use preserves::value::PackedWriter; -use preserves::value::Reader; -use preserves::value::ToplevelWhitespaceMode; -use std::io; -use std::iter::Iterator; - -mod samples; -use samples::*; - -fn decode_all(bytes: &'_ [u8]) -> io::Result> { - BytesBinarySource::new(bytes) - .packed_iovalues() - .configured(true) - .collect() -} - -fn parse_all(text: &str) -> io::Result> { - BytesBinarySource::new(text.as_bytes()) - .text_iovalues() - .configured(true) - .collect() -} - -#[test] -fn compare_text_with_packed() -> io::Result<()> { - use io::prelude::*; - let from_text = { - let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap(); - let mut contents = String::new(); - fh.read_to_string(&mut contents)?; - BytesBinarySource::new(contents.as_bytes()) - .text_iovalues() - .demand_next(true)? - }; - let from_packed = { - let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); - IOBinarySource::new(&mut fh) - .packed_iovalues() - .demand_next(true)? - }; - assert_eq!(from_text, from_packed); - Ok(()) -} - -#[test] -fn compare_deserialize_text_with_packed() -> io::Result<()> { - use io::prelude::*; - let from_text = { - let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap(); - let mut contents = String::new(); - fh.read_to_string(&mut contents)?; - let tests: TestCases = preserves::de::from_text(&contents)?; - tests - }; - let from_packed = { - let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); - let tests: TestCases = preserves::de::from_read(&mut fh)?; - tests - }; - assert_eq!(from_text, from_packed); - Ok(()) -} - -#[test] -fn read_write_read_text() -> io::Result<()> { - use io::prelude::*; - let from_text = { - let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap(); - let mut contents = String::new(); - fh.read_to_string(&mut contents)?; - preserves::value::text::annotated_iovalue_from_str(&contents)? - }; - let roundtripped = { - let mut bs = Vec::new(); - let mut w = preserves::value::TextWriter::new(&mut bs); - preserves::ser::to_writer(&mut w, &from_text)?; - let s = String::from_utf8(bs).unwrap(); - preserves::value::text::annotated_iovalue_from_str(&s)? - }; - let roundtripped_indented = { - let mut bs = Vec::new(); - let mut w = preserves::value::TextWriter::new(&mut bs); - w.indentation = 4; - preserves::ser::to_writer(&mut w, &from_text)?; - let s = String::from_utf8(bs).unwrap(); - preserves::value::text::annotated_iovalue_from_str(&s)? - }; - assert_eq!(from_text, roundtripped); - assert_eq!(from_text, roundtripped_indented); - Ok(()) -} - -#[test] -fn deserialize_serialize_deserialize_text() -> io::Result<()> { - use io::prelude::*; - let from_text = { - let mut fh = std::fs::File::open("../../../tests/samples.pr").unwrap(); - let mut contents = String::new(); - fh.read_to_string(&mut contents)?; - let tests: TestCases = preserves::de::from_text(&contents)?; - tests - }; - let roundtripped = { - let mut bs = Vec::new(); - let mut w = preserves::value::TextWriter::new(&mut bs); - preserves::ser::to_writer(&mut w, &from_text)?; - let s = String::from_utf8(bs).unwrap(); - preserves::de::from_text(&s)? - }; - assert_eq!(from_text, roundtripped); - Ok(()) -} - -#[test] -fn run() -> io::Result<()> { - let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); - let mut src = IOBinarySource::new(&mut fh); - let mut d = src.packed_iovalues().configured(true); - let tests: TestCases = deserialize_from_value(&d.next().unwrap().unwrap()).unwrap(); - - for (Symbol(name), case) in tests.tests { - println!("{:?} ==> {:?}", name, case); - match case { - TestCase::Test(bin, val) => { - assert_eq!( - &decode_all(&PackedWriter::encode_iovalue(&val)?[..])?, - &[val.clone()] - ); - assert_eq!(&decode_all(&bin[..])?, &[val.clone()]); - assert_eq!(&PackedWriter::encode_iovalue(&val)?, &bin); - } - TestCase::NondeterministicTest(bin, val) => { - assert_eq!(&PackedWriter::encode_iovalue(&val)?, &bin); - assert_eq!( - &decode_all(&PackedWriter::encode_iovalue(&val)?[..])?, - &[val.clone()] - ); - assert_eq!(&decode_all(&bin[..])?, &[val.clone()]); - } - TestCase::ParseError(text) => { - match parse_all(&text) { - Ok(_) => panic!("Unexpected success"), - Err(e) => { - if is_syntax_io_error(&e) { - // all is OK - } else { - panic!("Unexpected error {:?}", e) - } - } - } - } - TestCase::ParseShort(text) => { - assert!(if let Err(e) = BytesBinarySource::new(text.as_bytes()) - .text_iovalues() - .toplevel_whitespace_mode(ToplevelWhitespaceMode::Value) - .configured(true) - .next() - .unwrap() - { - is_eof_io_error(&e) - } else { - false - }) - } - TestCase::ParseEOF(text) => { - assert!(BytesBinarySource::new(text.as_bytes()) - .text_iovalues() - .toplevel_whitespace_mode(ToplevelWhitespaceMode::Value) - .configured(true) - .next() - .is_none()); - } - TestCase::DecodeError(bin) => { - match decode_all(&bin[..]) { - Ok(_) => panic!("Unexpected success"), - Err(e) => { - if is_syntax_io_error(&e) { - // all is OK - } else { - panic!("Unexpected error {:?}", e) - } - } - } - } - TestCase::DecodeShort(bin) => { - assert!(if let Err(e) = BytesBinarySource::new(&bin) - .packed_iovalues() - .configured(true) - .next() - .unwrap() - { - is_eof_io_error(&e) - } else { - false - }) - } - TestCase::DecodeEOF(bin) => { - assert!(BytesBinarySource::new(&bin) - .packed_iovalues() - .configured(true) - .next() - .is_none()); - } - } - } - Ok(()) -} diff --git a/implementations/rust/release.toml b/implementations/rust/release.toml deleted file mode 100644 index be7f5c7..0000000 --- a/implementations/rust/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -consolidate-commits=true -consolidate-pushes=true -tag-prefix="rust-{{crate_name}}" -tag-name="{{prefix}}@{{version}}" -dev-version-ext="dev.0" diff --git a/preserves-schema.md b/preserves-schema.md index c751ac2..8452ec5 100644 --- a/preserves-schema.md +++ b/preserves-schema.md @@ -31,7 +31,7 @@ object-oriented languages like Java, [Python][python-impl] and [nim-impl]: https://git.syndicate-lang.org/ehmry/preserves-nim [python-impl]: https://gitlab.com/preserves/preserves/-/blob/main/implementations/python/preserves/schema.py [racket-impl]: https://gitlab.com/preserves/preserves/-/tree/main/implementations/racket/preserves/preserves-schema -[rust-impl]: https://gitlab.com/preserves/preserves/-/tree/main/implementations/rust/preserves-schema +[rust-impl]: https://gitlab.com/preserves/preserves-rs/-/tree/main/preserves-schema [smalltalk-impl]: https://squeaksource.com/Preserves.html [ts-impl]: https://gitlab.com/preserves/preserves/-/tree/main/implementations/javascript/packages/schema