Crate preserves_schema

source ·
Expand description
cargo add preserves preserves-schema

This crate (preserves-schema on 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.


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.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.1 See the preserves-schemac documentation.

§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 (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.prb

Representative excerpts from one of the generated files, ./rs/chat/

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 {
    Away {
        since: std::boxed::Box<TimeStamp>
pub struct TimeStamp(pub std::string::String);

  1. 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 convert

    The result:

    <bundle {
      ]: <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 [
              <lit here>
              <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



  • Implementation of the Schema-to-Rust compiler; this is the core of the preserves-schema-rs program.
  • Auto-generated Preserves Schema Metaschema types, parsers, and unparsers.
  • The runtime support library for compiled Schemas.
  • A library for emitting pretty-formatted structured source code.