Skip to main content

deser_transcode/
lib.rs

1//! Converts values from one data format to another.
2//!
3//! Every [`Deserializer`] can be transcoded into every [`Serializer`],
4//! without types in between and without code that is specific to the
5//! formats:
6//!
7//! ```rust
8//! let mut de = deser_json::Deserializer::from_str(r#"{"name": "deser", "tags": ["a", "b"]}"#);
9//! let mut ser = deser_yaml::Serializer::new();
10//! deser_transcode::transcode(&mut de, &mut ser).unwrap();
11//! assert_eq!(ser.finish(), "name: deser\ntags:\n  - a\n  - b\n");
12//! ```
13//!
14//! # How it Works
15//!
16//! A deserializer parses a value and pushes its events into a
17//! [`DeserializeDriver`], a serializer receives the events of a value
18//! from a [`SerializeDriver`].  Both are in control of their loop, so a
19//! value is recorded into a [`RecordBuf`] and then serialized from it.
20//! Only one value is held at a time, and strings which the deserializer
21//! lends from the input (like the strings without escape sequences in
22//! JSON) are not copied.  Recording also makes the length of every map and
23//! sequence known before it's serialized, even if the input format did not
24//! say, so formats that write lengths upfront (such as CBOR and
25//! MessagePack) do not have to fix them up afterwards.
26//!
27//! The events are passed on as the deserializer emitted them, together
28//! with the data attached to them (such as CBOR tags).  Each serializer
29//! then does with them what it does with any value, there are no rules
30//! specific to transcoding:
31//!
32//! * values whose type the input format infers from their text (like
33//!   `true` or `1.0` in YAML) are written as the type they were inferred
34//!   as, text that is text in the input format (like the values of query
35//!   strings) stays text.
36//! * keys that are not strings are written the way the target format
37//!   writes such keys (JSON writes `1` as `"1"`), keys that the target
38//!   format cannot express (such as sequences in JSON) are an error.
39//! * values that the target format cannot express use its fallback (bytes
40//!   are base64 in text formats, TOML skips map entries that are null) or
41//!   are an error (TOML documents must be tables).
42//! * duplicate keys are passed on, it's up to the target format what it
43//!   does with them.
44//!
45//! # Streams
46//!
47//! Every call transcodes a single value.  What follows the value in the
48//! input depends on the configuration of the deserializer, for a stream of
49//! values (like JSON Lines or YAML documents) transcode until the
50//! deserializer is at its end.  A [`Transcoder`] reuses its buffer for all
51//! values:
52//!
53//! ```rust
54//! use deser_json::{DeserializerConfig, Trailing};
55//! use deser_transcode::Transcoder;
56//!
57//! let config = DeserializerConfig::new().trailing(Trailing::Newline);
58//! let mut de = deser_json::Deserializer::from_str_with_config(
59//!     "{\"a\": 1}\n{\"a\": 2}\n",
60//!     &config,
61//! );
62//! let mut ser = deser_yaml::Serializer::new();
63//! let mut transcoder = Transcoder::new();
64//! while !de.is_end() {
65//!     transcoder.transcode(&mut de, &mut ser).unwrap();
66//! }
67//! assert_eq!(ser.finish(), "a: 1\n---\na: 2\n");
68//! ```
69//!
70//! Readers and writers of `deser::io` are deserializers and serializers
71//! too, so values can be transcoded from one stream to another (for
72//! instance from a file to standard output) without holding more than one
73//! value in memory:
74//!
75//! ```rust
76//! use deser_json::{DeserializerConfig, Trailing};
77//! use deser_transcode::Transcoder;
78//!
79//! let config = DeserializerConfig::new().trailing(Trailing::Newline);
80//! let input = &b"{\"a\": 1}\n{\"a\": 2}\n"[..];
81//! let mut de = config.reader(input);
82//! let mut ser = deser_yaml::SerializerConfig::new().writer(Vec::new());
83//! let mut transcoder = Transcoder::new();
84//! while !de.is_end().unwrap() {
85//!     transcoder.transcode(&mut de, &mut ser).unwrap();
86//! }
87//! assert_eq!(ser.into_inner(), b"a: 1\n---\na: 2\n");
88//! ```
89//!
90//! Values that are read from streams cannot borrow from the input, strings
91//! are copied into the buffer of the transcoder.
92//!
93//! # Layers
94//!
95//! Layers can be added to both sides (see [`transcode_with`]), for
96//! instance to limit what is accepted from the input.  Errors of the
97//! deserializer carry the location in the input as usual.
98#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
99#![no_std]
100
101use deser_core::de::{DeserializeDriver, Deserializer, RecordBuf};
102use deser_core::ser::{SerializeDriver, Serializer};
103use deser_core::{Error, ErrorKind};
104
105/// Transcodes a value from a deserializer into a serializer.
106///
107/// This reads the next value of the deserializer and serializes it.  To
108/// transcode many values, [`Transcoder`] reuses the buffer.
109pub fn transcode<'de, D, S>(de: &mut D, ser: &mut S) -> Result<(), Error>
110where
111    D: Deserializer<'de> + ?Sized,
112    S: Serializer + ?Sized,
113{
114    Transcoder::new().transcode(de, ser)
115}
116
117/// Transcodes a value with configured drivers.
118///
119/// The callbacks are invoked with the drivers before the value is
120/// deserialized and serialized, for instance to add layers:
121///
122/// ```rust
123/// use deser::de::Limits;
124///
125/// let mut de = deser_json::Deserializer::from_str("[[[1]]]");
126/// let mut ser = deser_yaml::Serializer::new();
127/// let err = deser_transcode::transcode_with(
128///     &mut de,
129///     &mut ser,
130///     |driver| driver.push_layer(Limits::new().max_depth(2)),
131///     |_driver| {},
132/// )
133/// .unwrap_err();
134/// assert_eq!(
135///     err.to_string(),
136///     "Unexpected: recursion limit exceeded at line 1 column 3"
137/// );
138/// ```
139pub fn transcode_with<'de, D, S, DF, SF>(
140    de: &mut D,
141    ser: &mut S,
142    de_setup: DF,
143    ser_setup: SF,
144) -> Result<(), Error>
145where
146    D: Deserializer<'de> + ?Sized,
147    S: Serializer + ?Sized,
148    DF: FnOnce(&mut DeserializeDriver<'_, 'de>),
149    SF: FnOnce(&mut SerializeDriver<'_>),
150{
151    Transcoder::new().transcode_with(de, ser, de_setup, ser_setup)
152}
153
154/// Transcodes values and reuses its buffer.
155///
156/// This is useful to transcode many values, see [`transcode`] and
157/// [`transcode_with`] for what it does.  The transcoder can be used for all
158/// values of an input, the buffer it holds borrows from it.
159#[derive(Debug, Default)]
160pub struct Transcoder<'de> {
161    buf: RecordBuf<'de>,
162}
163
164impl<'de> Transcoder<'de> {
165    /// Creates a new transcoder.
166    pub fn new() -> Transcoder<'de> {
167        Transcoder::default()
168    }
169
170    /// Transcodes a value from a deserializer into a serializer.
171    pub fn transcode<D, S>(&mut self, de: &mut D, ser: &mut S) -> Result<(), Error>
172    where
173        D: Deserializer<'de> + ?Sized,
174        S: Serializer + ?Sized,
175    {
176        self.transcode_with(de, ser, |_| {}, |_| {})
177    }
178
179    /// Transcodes a value with configured drivers.
180    ///
181    /// See [`transcode_with`].
182    pub fn transcode_with<D, S, DF, SF>(
183        &mut self,
184        de: &mut D,
185        ser: &mut S,
186        de_setup: DF,
187        ser_setup: SF,
188    ) -> Result<(), Error>
189    where
190        D: Deserializer<'de> + ?Sized,
191        S: Serializer + ?Sized,
192        DF: FnOnce(&mut DeserializeDriver<'_, 'de>),
193        SF: FnOnce(&mut SerializeDriver<'_>),
194    {
195        let mut de_setup = Some(de_setup);
196        self.record(de, &mut |driver| {
197            if let Some(setup) = de_setup.take() {
198                setup(driver);
199            }
200        })?;
201        let mut ser_setup = Some(ser_setup);
202        self.replay(ser, &mut |driver| {
203            if let Some(setup) = ser_setup.take() {
204                setup(driver);
205            }
206        })
207    }
208
209    /// Records the next value of the deserializer.
210    ///
211    /// This is not generic over the setup so that it exists once per
212    /// deserializer.
213    fn record<D>(
214        &mut self,
215        de: &mut D,
216        setup: &mut dyn FnMut(&mut DeserializeDriver<'_, 'de>),
217    ) -> Result<(), Error>
218    where
219        D: Deserializer<'de> + ?Sized,
220    {
221        {
222            let mut driver = DeserializeDriver::from_fn(|state| self.buf.recorder(state));
223            setup(&mut driver);
224            de.drive(&mut driver)?;
225        }
226        if self.buf.is_empty() {
227            return Err(Error::new(ErrorKind::EndOfFile, "empty input"));
228        }
229        Ok(())
230    }
231
232    /// Serializes the recorded value.
233    fn replay<S>(
234        &mut self,
235        ser: &mut S,
236        setup: &mut dyn FnMut(&mut SerializeDriver<'_>),
237    ) -> Result<(), Error>
238    where
239        S: Serializer + ?Sized,
240    {
241        let mut driver = SerializeDriver::new(&self.buf);
242        setup(&mut driver);
243        ser.drive(&mut driver)
244    }
245}