Expand description
cargo add preserves preserves-schemaThis crate (preserves-schema on crates.io) is an
implementation of Preserves Schema for Rust.
§What is Preserves Schema?
A Preserves schema connects Preserves Values 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
Values to instances of the produced type; and -
a total serialization function from instances of the type to
Values.
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.
§Example
Preserves schemas are written in a syntax that (ab)uses Preserves text syntax as a kind of S-expression. Schema source code looks like this:
version 1 .
Present = <Present @username string> .
Says = <Says @who string @what string> .
UserStatus = <Status @username string @status Status> .
Status = =here / <away @since TimeStamp> .
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. To compile schema source code to metaschema instances, use preserves-schemac:
yarn global add @preserves/schema
preserves-schemac .:simpleChatProtocol.prs > simpleChatProtocol.prbBinary-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.1 See the preserves-schemac documentation.
Converting the simpleChatProtocol.prb file to Preserves text syntax lets us read the
metaschema instance corresponding to the source code:
cat simpleChatProtocol.prb | preserves-tool convertThe result:
<bundle {
[
simpleChatProtocol
]: <schema {
definitions: {
Present: <rec <lit Present> <tuple [
<named username <atom String>>
]>>
Says: <rec <lit Says> <tuple [
<named who <atom String>>
<named what <atom String>>
]>>
Status: <or [
[
"here"
<lit here>
]
[
"away"
<rec <lit away> <tuple [
<named since <ref [] TimeStamp>>
]>>
]
]>
TimeStamp: <atom String>
UserStatus: <rec <lit Status> <tuple [
<named username <atom String>>
<named status <ref [] Status>>
]>>
}
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), 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:
preserves-schema-rs --output-dir rs/chat --prefix chat simpleChatProtocol.prbRepresentative excerpts from one of the generated files, ./rs/chat/simple_chat_protocol.rs:
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<TimeStamp>
}
}
pub struct TimeStamp(pub std::string::String);Re-exports§
pub use support::Codec;pub use support::Deserialize;pub use support::ParseError;
Modules§
- compiler
- Implementation of the Schema-to-Rust compiler; this is the core of the preserves-schema-rs program.
- gen
- Auto-generated Preserves Schema Metaschema types, parsers, and unparsers.
- support
- The runtime support library for compiled Schemas.
- syntax
- A library for emitting pretty-formatted structured source code.
Macros§
- anglebrackets
anglebrackets!(a,b,…,z)⟶<a,b,…,z>- block
block!(a,b,…,z)⟶{ab…z}- braces
braces!(a,b,…,z)⟶{a,b,…,z}- brackets
brackets!(a,b,…,z)⟶[a,b,…,z]- codeblock
- As
block!, but always vertical. See constructors::codeblock. - commas
commas!(a,b,…,z)⟶ a,b,…,z- define_
language - name
name!(a,b,…,z)⟶ a::b::…::z- parens
parens!(a,b,…,z)⟶(a,b,…,z)- semiblock
semiblock!(a,b,…,z)⟶{a;b;…;z}- seq
seq!(a,b,…,z)⟶ ab…z