2 releases

new 0.0.2 Dec 13, 2024
0.0.1 Dec 8, 2024

#4 in #composite

Download history 133/week @ 2024-12-05

133 downloads per month
Used in 2 crates

MIT/Apache

185KB
4K SLoC

Work in progress, not ready for general use

crates.io docs.rs

Compris

A Rust library to access, change, read, and write CPS (Composite Primitive Schema) data in several textual and binary representation formats.

What's CPS? It's that schema that comprises primitive data types (numbers, booleans, strings, etc.) as well as list and map collection types. The collections allow for nested structure, hence it is a composite schema. This concept is very widely used but has remarkably been unnamed... until now. You're welcome.

CPS is sometimes glossed it as "JSON", but that's misleading and ultimately unhelpful because JSON is merely one representation format for the data, and is actually comparitively quite limited (e.g. implementations do not often preserve the distinction between integers and floats). So instead of saying "let's just store it as JSON", say "let's just store it as CPS", and use Compris to handle the representation. It will allow you and your users to select from several formats at runtime.

Compris is pronounced "com-PREE". It comes from CompositePrimitiveSchema, or ComPriS for short.

See here for a full descripton of CPS.

Get started with the API documentation and the examples.

J'ai compris!

Supported Representation Formats

  • YAML
  • JSON, including an "XJSON" convention for JSON to support all CPS types
  • XML via a conventional schema (work in progress)
  • CBOR
  • MessagePack

Compris can read any of these formats into its "normal" value types, which provide many utility functions for convenient access and transformation of the nested data.

The types also include file location information (row and column) for debugging textual format sources (YAML, JSON, and XML).

All formats are enabled by default but can be turned on selectively using default-features = false.

Need more formats? We accept contributions and suggestions!

Traversal

Included are ergonomic facilities for accessing nested values by path.

Example.

Serialization

Compris's normal value types can be serialized via serde (optional serde feature).

But we also allow you to attach "serialization modes" that allow some control over seralization behavior. For example, FloatSerializationMode::AsIntegerIfFractionless will try to convert floats to integers when possible. This would happen only during serialization, on-the-fly, and does not modify your in-memory data.

We additionally provide serializers for all supported representation formats behind a common API so that they can be selected at runtime. For the textual formats, we support pretty printing for human readability, including colorization for terminals. For the binary formats, we support Base64 encoding.

Actually, this common serialization API can be used with any Rust type that supports serde serialization, not just our normal types. It is thus useful if your program needs to serialize to a range of different formats and you would rather use a single crate with a single API.

Example.

Deserialization

As with serialization, we provide a common API to deserialize from all supported representation formats (optional serde feature).

However, there is a twist, as this is done in two phases. Internally, we first read the format into Compris's normal value types before deserializing. This enables our full feature set, though it can be considered inefficient if you do not need these values.

But there is additional utility here. Often you will be working with Compris's normal values types, not the raw formats. Do you need to populate your own structs and enums from them? Instead of doing it manually, you can "deserialize" directly from there. No representation format is involved and no parsing is done. This feature merely uses serde's deserialization mechanism to efficiently handle the data placement.

Example.

CLI Tool

Also included in this repository is a CLI tool for querying and converting between all supported CPS format. It also supports reading CPS from a wide variety of URL types, via read-url.

To install:

cargo install compris-cli

Example of converting YAML in stdin to XJSON:

cat my_text.yaml | compris --input-format=yaml --format=xjson

References

Libraries implementing this concept for other languages:

License

Like much of the Rust ecosystem, licensed under your choice of either of

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~2.3–4MB
~76K SLoC