Skip to main content

Crate deser_transcode

Crate deser_transcode 

Source
Expand description

Converts values from one data format to another.

Every Deserializer can be transcoded into every Serializer, without types in between and without code that is specific to the formats:

let mut de = deser_json::Deserializer::from_str(r#"{"name": "deser", "tags": ["a", "b"]}"#);
let mut ser = deser_yaml::Serializer::new();
deser_transcode::transcode(&mut de, &mut ser).unwrap();
assert_eq!(ser.finish(), "name: deser\ntags:\n  - a\n  - b\n");

§How it Works

A deserializer parses a value and pushes its events into a DeserializeDriver, a serializer receives the events of a value from a SerializeDriver. Both are in control of their loop, so a value is recorded into a RecordBuf and then serialized from it. Only one value is held at a time, and strings which the deserializer lends from the input (like the strings without escape sequences in JSON) are not copied. Recording also makes the length of every map and sequence known before it’s serialized, even if the input format did not say, so formats that write lengths upfront (such as CBOR and MessagePack) do not have to fix them up afterwards.

The events are passed on as the deserializer emitted them, together with the data attached to them (such as CBOR tags). Each serializer then does with them what it does with any value, there are no rules specific to transcoding:

  • values whose type the input format infers from their text (like true or 1.0 in YAML) are written as the type they were inferred as, text that is text in the input format (like the values of query strings) stays text.
  • keys that are not strings are written the way the target format writes such keys (JSON writes 1 as "1"), keys that the target format cannot express (such as sequences in JSON) are an error.
  • values that the target format cannot express use its fallback (bytes are base64 in text formats, TOML skips map entries that are null) or are an error (TOML documents must be tables).
  • duplicate keys are passed on, it’s up to the target format what it does with them.

§Streams

Every call transcodes a single value. What follows the value in the input depends on the configuration of the deserializer, for a stream of values (like JSON Lines or YAML documents) transcode until the deserializer is at its end. A Transcoder reuses its buffer for all values:

use deser_json::{DeserializerConfig, Trailing};
use deser_transcode::Transcoder;

let config = DeserializerConfig::new().trailing(Trailing::Newline);
let mut de = deser_json::Deserializer::from_str_with_config(
    "{\"a\": 1}\n{\"a\": 2}\n",
    &config,
);
let mut ser = deser_yaml::Serializer::new();
let mut transcoder = Transcoder::new();
while !de.is_end() {
    transcoder.transcode(&mut de, &mut ser).unwrap();
}
assert_eq!(ser.finish(), "a: 1\n---\na: 2\n");

Readers and writers of deser::io are deserializers and serializers too, so values can be transcoded from one stream to another (for instance from a file to standard output) without holding more than one value in memory:

use deser_json::{DeserializerConfig, Trailing};
use deser_transcode::Transcoder;

let config = DeserializerConfig::new().trailing(Trailing::Newline);
let input = &b"{\"a\": 1}\n{\"a\": 2}\n"[..];
let mut de = config.reader(input);
let mut ser = deser_yaml::SerializerConfig::new().writer(Vec::new());
let mut transcoder = Transcoder::new();
while !de.is_end().unwrap() {
    transcoder.transcode(&mut de, &mut ser).unwrap();
}
assert_eq!(ser.into_inner(), b"a: 1\n---\na: 2\n");

Values that are read from streams cannot borrow from the input, strings are copied into the buffer of the transcoder.

§Layers

Layers can be added to both sides (see transcode_with), for instance to limit what is accepted from the input. Errors of the deserializer carry the location in the input as usual.

Structs§

Transcoder
Transcodes values and reuses its buffer.

Functions§

transcode
Transcodes a value from a deserializer into a serializer.
transcode_with
Transcodes a value with configured drivers.