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
trueor1.0in 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
1as"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.