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::builder().trailing(Trailing::Newline).build();
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::builder().trailing(Trailing::Newline).build();
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 or to give
121/// them a context:
122///
123/// ```rust
124/// use deser::Context;
125/// use deser::de::Limits;
126///
127/// let limits = Context::with(Limits::builder().max_depth(2).build());
128/// let mut de = deser_json::Deserializer::from_str("[[[1]]]");
129/// let mut ser = deser_yaml::Serializer::new();
130/// let err = deser_transcode::transcode_with(
131/// &mut de,
132/// &mut ser,
133/// |driver| driver.set_context(limits.clone()),
134/// |_driver| {},
135/// )
136/// .unwrap_err();
137/// assert_eq!(
138/// err.to_string(),
139/// "LimitExceeded: recursion limit exceeded at line 1 column 3"
140/// );
141/// ```
142pub fn transcode_with<'de, D, S, DF, SF>(
143 de: &mut D,
144 ser: &mut S,
145 de_setup: DF,
146 ser_setup: SF,
147) -> Result<(), Error>
148where
149 D: Deserializer<'de> + ?Sized,
150 S: Serializer + ?Sized,
151 DF: FnOnce(&mut DeserializeDriver<'_, 'de>),
152 SF: FnOnce(&mut SerializeDriver<'_>),
153{
154 Transcoder::new().transcode_with(de, ser, de_setup, ser_setup)
155}
156
157/// Transcodes values and reuses its buffer.
158///
159/// This is useful to transcode many values, see [`transcode`] and
160/// [`transcode_with`] for what it does. The transcoder can be used for all
161/// values of an input, the buffer it holds borrows from it.
162#[derive(Debug, Default)]
163pub struct Transcoder<'de> {
164 buf: RecordBuf<'de>,
165}
166
167impl<'de> Transcoder<'de> {
168 /// Creates a new transcoder.
169 pub fn new() -> Transcoder<'de> {
170 Transcoder::default()
171 }
172
173 /// Transcodes a value from a deserializer into a serializer.
174 pub fn transcode<D, S>(&mut self, de: &mut D, ser: &mut S) -> Result<(), Error>
175 where
176 D: Deserializer<'de> + ?Sized,
177 S: Serializer + ?Sized,
178 {
179 self.transcode_with(de, ser, |_| {}, |_| {})
180 }
181
182 /// Transcodes a value with configured drivers.
183 ///
184 /// See [`transcode_with`].
185 pub fn transcode_with<D, S, DF, SF>(
186 &mut self,
187 de: &mut D,
188 ser: &mut S,
189 de_setup: DF,
190 ser_setup: SF,
191 ) -> Result<(), Error>
192 where
193 D: Deserializer<'de> + ?Sized,
194 S: Serializer + ?Sized,
195 DF: FnOnce(&mut DeserializeDriver<'_, 'de>),
196 SF: FnOnce(&mut SerializeDriver<'_>),
197 {
198 let mut de_setup = Some(de_setup);
199 self.record(de, &mut |driver| {
200 if let Some(setup) = de_setup.take() {
201 setup(driver);
202 }
203 })?;
204 let mut ser_setup = Some(ser_setup);
205 self.replay(ser, &mut |driver| {
206 if let Some(setup) = ser_setup.take() {
207 setup(driver);
208 }
209 })
210 }
211
212 /// Records the next value of the deserializer.
213 ///
214 /// This is not generic over the setup so that it exists once per
215 /// deserializer.
216 fn record<D>(
217 &mut self,
218 de: &mut D,
219 setup: &mut dyn FnMut(&mut DeserializeDriver<'_, 'de>),
220 ) -> Result<(), Error>
221 where
222 D: Deserializer<'de> + ?Sized,
223 {
224 {
225 let mut driver = DeserializeDriver::from_fn(|state| self.buf.recorder(state));
226 setup(&mut driver);
227 de.drive(&mut driver)?;
228 }
229 if self.buf.is_empty() {
230 return Err(Error::new(ErrorKind::EndOfFile, "empty input"));
231 }
232 Ok(())
233 }
234
235 /// Serializes the recorded value.
236 fn replay<S>(
237 &mut self,
238 ser: &mut S,
239 setup: &mut dyn FnMut(&mut SerializeDriver<'_>),
240 ) -> Result<(), Error>
241 where
242 S: Serializer + ?Sized,
243 {
244 let mut driver = SerializeDriver::new(&self.buf);
245 setup(&mut driver);
246 ser.drive(&mut driver)
247 }
248}