[][src]Crate sval

A small, no-std, object-safe, serialization-only framework.

The sval API is built around two key traits:

  • Value is a trait for data with a streamable structure. It's like serde::Serialize.
  • Stream is a trait for receiving the structure of a value. It's like serde::Serializer.

Getting started

Add sval to your Cargo.toml:

[dependencies.sval]
version = "1.0.0-alpha.5"

Supported formats

  • JSON, the ubiquitous JavaScript Object Notation used by many HTTP APIs.

Streaming values

The structure of a Value can be streamed to a Stream.

in a single call

For simple use-cases, use the stream function to stream the structure of a value:

sval::stream(MyStream, 42)?;

where 42 is a Value and MyStream is a Stream.

over multiple calls

More involved use-cases may want to build up structure over time. Use a stream::OwnedStream to hang on to a stream and pass it values over time.

The following example wraps up a stream in an API that lets callers treat it like a map:

// Create a `Map` stream that wraps up another one
let mut stream = Map::new(my_stream)?;

// Stream it some entries
stream.entry("a", 42)?;
stream.entry("b", 17)?;

// Eventually we end the wrapper and return the original stream
let my_stream = stream.end()?;
}

An implementation of Map could then look like this:

use sval::{
    value::Value,
    stream::{self, OwnedStream},
};

struct Map {
    // Using `OwnedStream<MyStream>` instead of just `MyStream`
    // gives us better ergonomics and validation
    stream: OwnedStream<MyStream>,
}

impl Map {
    fn new(stream: MyStream) -> Result<Self, sval::Error> {
        let mut stream = OwnedStream::new(stream);
        stream.map_begin(None)?;

        Ok(Map {
            stream,
        })
    }

    fn entry(&mut self, k: impl Value, v: impl Value) -> Result<(), sval::Error> {
        self.stream.map_key(k)?;
        self.stream.map_value(v)?;

        Ok(())
    }

    fn end(mut self) -> Result<MyStream, sval::Error> {
        self.stream.map_end()?;

        Ok(self.stream.into_inner())
    }
}

serde integration

Use the serde Cargo feature to enable integration with serde:

[dependencies.sval]
features = ["serde"]

When serde is available, the Value trait can also be derived based on an existing Serialize implementation:

#[macro_use]
extern crate sval;

#[derive(Serialize, Value)]
#[sval(derive_from = "serde")]
pub enum Data {
    Variant(i32, String),
}

std::fmt integration

Use the fmt Cargo feature to enable extended integration with std::fmt:

[dependencies.sval]
features = ["fmt"]

When fmt is available, arbitrary Values can be treated like std::fmt::Debug:

fn with_value(value: impl Value) {
    dbg!(sval::fmt::to_debug(&value));

    // Do something with the value
}

Modules

fmt

Integration between sval and std::fmt.

serde

Integration between sval and serde.

stream

A stream for datastructures.

test

Helpers for testing value implementations.

value

A streamable value.

Structs

Error

An error encountered while visiting a value.

Functions

stream

Stream the structure of a Value using the given Stream.

Derive Macros

Value