Skip to main content

typesafe_sdk/
codec.rs

1//! JSON encoding and decoding for the whole crate.
2//!
3//! [`backend`] selects serde_json by default, or sonic-rs with the `sonic`
4//! feature. No backend type appears in a public signature.
5//!
6//! Four things here are not what a plain serde wrapper would do:
7//!
8//! * **The encode buffer is retained per thread.** sonic-rs reserves
9//!   `len * 6 + 35` bytes before every string write, so a buffer sized to the
10//!   final body re-allocates on every call. [`encode_body`] writes into a
11//!   scratch buffer this thread keeps between calls and copies the finished
12//!   bytes into an exactly sized one with either backend.
13//! * **Decoding runs a depth pre-scan first.** sonic-rs has no recursion limit
14//!   on these paths and aborts if it exhausts the stack; serde_json stops at
15//!   128 levels. A counter inside a `serde` visitor cannot prevent a parser's
16//!   own stack overflow, so both backends use the same 16-level guard on the
17//!   raw bytes. See [`check_depth`].
18//! * **Decode errors are rebuilt rather than forwarded.** sonic-rs's
19//!   `Display` embeds a multi-line excerpt of the input, and `serde`'s
20//!   type-mismatch messages quote the offending value; a `state` may carry
21//!   personal data, so [`DecodeError`] keeps only a kind, a position and a
22//!   field path.
23//! * **Raw JSON has a path for this codec and a path for every other one.**
24//!   Splicing text in unchanged, and capturing it on the way back, are both
25//!   protocols private to this codec. [`RawJson`] is public and users will
26//!   hand it to a codec of their own, so it also knows how to write itself out
27//!   as ordinary data and to read ordinary data back. See [`serialize_raw`]
28//!   and [`deserialize_raw`].
29
30pub(crate) mod backend;
31
32use std::{
33    borrow::Cow,
34    cell::{Cell, RefCell},
35    fmt,
36    marker::PhantomData,
37};
38
39use bytes::Bytes;
40use serde::{
41    Deserialize, Deserializer, Serialize, Serializer, de,
42    de::{DeserializeSeed, IgnoredAny},
43    ser,
44    ser::{SerializeMap, SerializeSeq, SerializeStruct},
45};
46use thiserror::Error;
47
48use self::backend::SPLICE_TOKEN;
49use crate::text::{Backslash, SafeText};
50
51/// The deepest JSON nesting this crate will parse.
52///
53/// Anything deeper is rejected before a byte reaches the parser. The limit is
54/// far below what any documented API response needs. sonic-rs aborts on deep
55/// input, while serde_json has a 128-level limit; the shared guard keeps the
56/// SDK's bound independent of the chosen backend.
57pub(crate) const MAX_JSON_DEPTH: usize = 16;
58
59// ------------------------------------------------------------------ errors
60
61/// The reason a JSON document could not be decoded.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
63#[non_exhaustive]
64pub enum DecodeErrorKind {
65    /// The document is nested deeper than the 16 levels this crate parses, and
66    /// was rejected without being parsed.
67    TooDeep,
68    /// The bytes are not syntactically valid JSON, or they end early.
69    Syntax,
70    /// The document parses, but its shape does not match the expected type: a
71    /// field is missing, or a value has the wrong type.
72    Data,
73}
74
75/// A JSON document could not be decoded into the expected type.
76///
77/// The error deliberately carries no part of the input. A decoded document may
78/// contain application state and therefore personal data, and both the codec's
79/// own error text and `serde`'s type-mismatch messages quote the input. What
80/// is kept is the kind, the position and the field path, which are derived
81/// from the expected type rather than from the values.
82#[derive(Debug, Clone, PartialEq, Eq, Error)]
83#[error("{detail}")]
84#[non_exhaustive]
85pub struct DecodeError {
86    detail: Detail,
87}
88
89/// The rendered forms of [`DecodeError`], kept private so that the public type
90/// can gain fields without breaking callers.
91#[derive(Debug, Clone, PartialEq, Eq, Error)]
92enum Detail {
93    #[error("JSON input is nested deeper than the maximum of {}", MAX_JSON_DEPTH)]
94    TooDeep,
95    #[error("invalid JSON syntax at line {line} column {column}")]
96    Syntax { line: usize, column: usize },
97    #[error("unexpected JSON value at `{path}`, line {line} column {column}")]
98    Data { path: Box<str>, line: usize, column: usize },
99    /// The document does not have the shape the type expects, and the codec
100    /// could say neither where nor why. Rendering an empty path as ``at ` ` ``
101    /// would say less than saying nothing.
102    #[error("the JSON document does not have the expected shape")]
103    Opaque,
104}
105
106impl DecodeError {
107    /// Which of the three failure classes this is.
108    #[must_use]
109    pub fn kind(&self) -> DecodeErrorKind {
110        match self.detail {
111            Detail::TooDeep => DecodeErrorKind::TooDeep,
112            Detail::Syntax { .. } => DecodeErrorKind::Syntax,
113            Detail::Data { .. } | Detail::Opaque => DecodeErrorKind::Data,
114        }
115    }
116
117    /// The one-based line the parser stopped at, or 0 when the document was
118    /// rejected before it was parsed.
119    #[must_use]
120    pub fn line(&self) -> usize {
121        match self.detail {
122            Detail::TooDeep | Detail::Opaque => 0,
123            Detail::Syntax { line, .. } | Detail::Data { line, .. } => line,
124        }
125    }
126
127    /// The byte column the parser stopped at, usually one-based.
128    ///
129    /// It is 0 when no position is available, or when the selected parser
130    /// reports a failure before the first byte of an empty document.
131    #[must_use]
132    pub fn column(&self) -> usize {
133        match self.detail {
134            Detail::TooDeep | Detail::Opaque => 0,
135            Detail::Syntax { column, .. } | Detail::Data { column, .. } => column,
136        }
137    }
138
139    /// The path of the offending field, with dotted names and bracketed
140    /// indices, for example `answers.tone.confidence` or `models[1].name`.
141    ///
142    /// The path of the document root is `.`, and it is empty when the failure
143    /// carries no path at all.
144    ///
145    /// A name in the path may be an object key the input chose, so it is
146    /// rendered safe to print: a control character or a format character that
147    /// reorders or hides text is written as a Rust escape (`\n`, `\u{1b}`,
148    /// `\u{202e}`), a backslash is written `\\` so that an escape cannot be
149    /// mistaken for text, and other printable text, non-ASCII included, is kept
150    /// as it is.
151    /// Each name is cut at 128 characters and the whole path at 320, counted
152    /// after escaping, and a cut is marked with U+2026.
153    #[must_use]
154    pub fn path(&self) -> &str {
155        match &self.detail {
156            Detail::TooDeep | Detail::Syntax { .. } | Detail::Opaque => "",
157            Detail::Data { path, .. } => path,
158        }
159    }
160
161    fn too_deep() -> Self {
162        Self { detail: Detail::TooDeep }
163    }
164}
165
166/// A value could not be encoded as JSON.
167///
168/// The message comes from the codec's serializer, which reports the failing
169/// step - a map key that is not a string, a boolean or a number, or an error
170/// returned by the value's own [`Serialize`] implementation - and never quotes
171/// the value.
172#[derive(Debug, Clone, PartialEq, Eq, Error)]
173#[error("the value could not be encoded as JSON: {message}")]
174#[non_exhaustive]
175pub struct EncodeError {
176    message: Box<str>,
177}
178
179impl EncodeError {
180    /// The serializer's description of what went wrong.
181    #[must_use]
182    pub fn message(&self) -> &str {
183        &self.message
184    }
185
186    /// Serialization errors carry no position and no input excerpt, so the
187    /// codec's `Display` is safe to keep here. Decode errors are not, which is
188    /// why [`DecodeError`] is rebuilt from parts instead.
189    fn from_codec(error: backend::Error) -> Self {
190        Self { message: error.to_string().into_boxed_str() }
191    }
192}
193
194// ---------------------------------------------------------------- encoding
195
196thread_local! {
197    /// The buffer [`encode_body`] writes into, kept between calls.
198    ///
199    /// It is an `Option` because the buffer is taken out for the duration of a
200    /// call rather than borrowed: the closure runs arbitrary `Serialize`
201    /// implementations, and one of them encoding a body of its own would panic
202    /// on a `RefCell` borrow held across it.
203    static SCRATCH: RefCell<Option<Vec<u8>>> = const { RefCell::new(None) };
204    /// The recent body size this thread encodes, decayed by a sixteenth per
205    /// call so that a single large outlier stops pinning the buffer.
206    static SCRATCH_HINT: Cell<usize> = const { Cell::new(0) };
207}
208
209/// The most encode scratch a thread keeps between calls: 8 MiB.
210///
211/// With sonic-rs, the codec reserves six times a string's length before
212/// writing it, so the scratch a large string state leaves behind is six times
213/// the state; serde_json grows the buffer as it writes. Either backend would
214/// keep an outlier until later calls on the same thread decayed it away -
215/// never, on a thread that goes idle. A scratch over this size is
216/// dropped after its call instead, and a state that large grows it afresh on
217/// every call, as a first call does. The scratch of a 1 MB state, the largest
218/// one a call is budgeted for, stays under the ceiling, so its calls keep
219/// reusing it.
220const MAX_RETAINED_SCRATCH: usize = 8 * 1024 * 1024;
221
222/// Appends the JSON form of `value` to `buf`.
223///
224/// The buffer is not cleared, which is what lets a request body be spliced out
225/// of literal fragments and encoded values in one pass.
226///
227/// # Errors
228///
229/// Returns [`EncodeError`] when the value cannot be represented as JSON: a
230/// map whose keys are neither strings, booleans nor numbers, or a non-finite
231/// float key, or a [`Serialize`] implementation that returns an error of its
232/// own. A non-finite float value is not one of these - both backends write it
233/// as `null`. The buffer may then hold a partial encoding of
234/// that value, so a caller that reuses it has to truncate it.
235pub(crate) fn encode_into<T>(buf: &mut Vec<u8>, value: &T) -> Result<(), EncodeError>
236where
237    T: Serialize + ?Sized,
238{
239    // The mark is what tells `RawJson` that the serializer about to run is
240    // this crate's own, and so that raw text may be spliced in verbatim.
241    let _inside = EncoderMark::enter();
242    backend::to_writer(&mut *buf, value).map_err(EncodeError::from_codec)
243}
244
245/// Appends `text` to `buf` as a JSON string literal, quoted and escaped.
246pub(crate) fn write_json_string(buf: &mut Vec<u8>, text: &str) {
247    encode_into(buf, text).expect("invariant: encoding a string into a Vec cannot fail");
248}
249
250/// Builds one request body and hands it over as exactly sized [`Bytes`].
251///
252/// `fill` writes the whole body into a buffer this thread keeps between calls,
253/// so a repeated call of the same shape allocates once: the copy into the
254/// returned buffer. A buffer that grew past [`MAX_RETAINED_SCRATCH`] is not
255/// kept. That buffer has `len == capacity`, which makes
256/// `Bytes::from` a move rather than a copy and defers the shared-header
257/// allocation to the first `clone`.
258///
259/// The scratch buffer is taken out of the thread-local for the duration of the
260/// call. A `Serialize` implementation that calls this function again therefore
261/// gets a buffer of its own instead of corrupting the outer one, and a panic
262/// inside `fill` drops the buffer rather than leaving a damaged one behind.
263///
264/// # Errors
265///
266/// Returns whatever `fill` returns.
267pub(crate) fn encode_body<F>(fill: F) -> Result<Bytes, EncodeError>
268where
269    F: FnOnce(&mut Vec<u8>) -> Result<(), EncodeError>,
270{
271    let mut scratch = SCRATCH.with(|cell| cell.borrow_mut().take()).unwrap_or_default();
272    scratch.clear();
273
274    // `to_vec` allocates exactly `len` bytes, so the body buffer is full and
275    // `Bytes::from` takes it over without copying again.
276    let body = fill(&mut scratch).map(|()| Bytes::from(scratch.as_slice().to_vec()));
277
278    let hint = SCRATCH_HINT.get();
279    let decayed = scratch.len().max(hint - hint / 16);
280    SCRATCH_HINT.set(decayed);
281    if scratch.capacity() > MAX_RETAINED_SCRATCH {
282        // Not shrunk to the hint either: a hint this large is the body that
283        // just passed the ceiling, and keeping it would hold the memory the
284        // ceiling exists to release.
285        scratch = Vec::new();
286    } else if scratch.capacity() > decayed.saturating_mul(8) {
287        // The shrink goes all the way down to the hint rather than to the
288        // bound: stopping at the bound leaves the capacity exactly where the
289        // still-decaying hint lowers it again, so every following call
290        // re-allocates the whole buffer.
291        scratch.shrink_to(decayed);
292    }
293    SCRATCH.with(|cell| cell.replace(Some(scratch)));
294
295    body
296}
297
298/// Bytes the encode scratch of this thread is holding on to.
299#[cfg(any(test, feature = "internals"))]
300pub(crate) fn scratch_capacity() -> usize {
301    SCRATCH.with(|cell| cell.borrow().as_ref().map_or(0, Vec::capacity))
302}
303
304/// The decayed size hint this thread carries.
305#[cfg(any(test, feature = "internals"))]
306pub(crate) fn scratch_hint() -> usize {
307    SCRATCH_HINT.get()
308}
309
310/// Drops this thread's encode scratch and its size hint, so that the next call
311/// starts from the state of a fresh thread.
312#[cfg(any(test, feature = "internals"))]
313pub(crate) fn reset_scratch() {
314    SCRATCH.with(|cell| cell.replace(None));
315    SCRATCH_HINT.set(0);
316}
317
318// ---------------------------------------------------------------- decoding
319
320/// Rejects JSON nested deeper than [`MAX_JSON_DEPTH`].
321///
322/// This runs over the raw bytes, before any of them reach the parser, and it
323/// only counts brackets outside string literals. It does not validate the
324/// document: unbalanced or misplaced brackets are the parser's business.
325///
326/// # Errors
327///
328/// Returns a [`DecodeErrorKind::TooDeep`] error at the first bracket that
329/// crosses the limit.
330pub(crate) fn check_depth(json: &[u8]) -> Result<(), DecodeError> {
331    let mut depth = 0usize;
332    let mut in_string = false;
333    let mut escaped = false;
334
335    for &byte in json {
336        if in_string {
337            if escaped {
338                // Every escape sequence this matters for is one byte long
339                // (`\"` and `\\`); the four hex digits of `\uXXXX` contain no
340                // quote or backslash, so skipping one byte is enough.
341                escaped = false;
342            } else if byte == b'\\' {
343                escaped = true;
344            } else if byte == b'"' {
345                in_string = false;
346            }
347            continue;
348        }
349
350        match byte {
351            b'"' => in_string = true,
352            b'[' | b'{' => {
353                depth += 1;
354                if depth > MAX_JSON_DEPTH {
355                    return Err(DecodeError::too_deep());
356                }
357            }
358            b']' | b'}' => depth = depth.saturating_sub(1),
359            _ => {}
360        }
361    }
362
363    Ok(())
364}
365
366/// Checks that `bytes` are UTF-8, and hands them back as text.
367///
368/// Every decode starts here, before the depth pre-scan and either parser.
369/// sonic-rs can hand a string's bytes on as text before checking the complete
370/// document's UTF-8; serde_json validates strings itself. Giving both the
371/// already-checked text also keeps rejection positions independent of the
372/// selected backend.
373///
374/// # Errors
375///
376/// Returns a [`DecodeErrorKind::Syntax`] error at the first byte that is not
377/// part of a UTF-8 character: JSON text is UTF-8 (RFC 8259, section 8.1), so a
378/// document holding such a byte is not JSON. The position counts bytes, as the
379/// codec's own positions do.
380fn as_text(bytes: &[u8]) -> Result<&str, DecodeError> {
381    std::str::from_utf8(bytes).map_err(|failure| {
382        let before = &bytes[..failure.valid_up_to()];
383        let line = 1 + before.iter().filter(|&&byte| byte == b'\n').count();
384        let line_start = before.iter().rposition(|&byte| byte == b'\n').map_or(0, |at| at + 1);
385        let column = 1 + before.len() - line_start;
386        DecodeError { detail: Detail::Syntax { line, column } }
387    })
388}
389
390/// Decodes `bytes` into `T`.
391///
392/// The successful path is a single pass and pays nothing for error reporting.
393/// A failure is decoded a second time through a path-tracking wrapper, which
394/// is what turns a bare position into `answers.tone.confidence`.
395///
396/// # Errors
397///
398/// Returns [`DecodeError`] when the input is not UTF-8, is nested too deeply,
399/// is not valid JSON, or does not have the shape `T` expects.
400pub(crate) fn decode<'de, T>(bytes: &'de [u8]) -> Result<T, DecodeError>
401where
402    T: Deserialize<'de>,
403{
404    let text = as_text(bytes)?;
405    check_depth(bytes)?;
406    let _inside = DecoderMark::enter();
407    // `PhantomData<T>` is serde's own seed for "decode a `T`", which is what
408    // lets the failure pass below serve this function and `decode_seed` alike.
409    backend::from_str::<T>(text).map_err(|_| describe_failure(text, PhantomData::<T>))
410}
411
412/// Decodes `bytes` through `seed`, a decoder that carries state of its own -
413/// how many answers to make room for, for instance - which a type's
414/// `Deserialize` cannot receive.
415///
416/// Everything else is [`decode`]: the same UTF-8 check and depth pre-scan,
417/// one pass on success that accepts exactly what `decode` accepts, and on
418/// failure the same second, path-tracking pass. That second pass needs the
419/// seed again, which is why it is `Clone`: a seed is consumed by the pass it
420/// drives.
421///
422/// # Errors
423///
424/// Returns [`DecodeError`] when the input is not UTF-8, is nested too deeply,
425/// is not valid JSON, or does not have the shape the seed expects.
426pub(crate) fn decode_seed<'de, S>(bytes: &'de [u8], seed: S) -> Result<S::Value, DecodeError>
427where
428    S: DeserializeSeed<'de> + Clone,
429{
430    let text = as_text(bytes)?;
431    check_depth(bytes)?;
432    let _inside = DecoderMark::enter();
433    // The codec's entry point for a type checks that the value is followed by
434    // nothing but whitespace; its deserializer does that only when asked, with
435    // `end`.
436    let decoded = {
437        let mut deserializer = backend::Deserializer::from_str(text);
438        seed.clone()
439            .deserialize(&mut deserializer)
440            .ok()
441            .and_then(|value| deserializer.end().ok().map(|()| value))
442    };
443    decoded.ok_or_else(|| describe_failure(text, seed))
444}
445
446/// Re-runs a failed decode with path tracking and turns the result into a
447/// [`DecodeError`] that carries no part of the input.
448///
449/// `text` is what [`as_text`] returned, so it is read without a second check.
450fn describe_failure<'de, S>(text: &'de str, seed: S) -> DecodeError
451where
452    S: DeserializeSeed<'de>,
453{
454    let mut deserializer = backend::Deserializer::from_str(text);
455    let mut track = serde_path_to_error::Track::new();
456    let failure = seed
457        .deserialize(serde_path_to_error::Deserializer::new(&mut deserializer, &mut track))
458        .err();
459    let Some(inner) = failure else {
460        // The tracked pass reads one value and stops there; unlike the first
461        // pass it never looks at what follows it. So a document with anything
462        // but whitespace after its value parses here and failed there, and
463        // asking the deserializer to finish is the only way to get the
464        // position of the byte the first pass tripped on.
465        return match deserializer.end() {
466            Err(trailing) => {
467                let (line, column) = backend::error_position(&trailing);
468                DecodeError { detail: Detail::Syntax { line, column } }
469            }
470            // Both passes read the same bytes with the same type and
471            // disagreed on whether they parse at all. Nothing about the
472            // input can be reported beyond that disagreement.
473            Ok(()) => DecodeError { detail: Detail::Opaque },
474        };
475    };
476    let path = track.path();
477
478    let (line, column) = backend::error_position(&inner);
479
480    if backend::is_syntax(&inner) {
481        return DecodeError { detail: Detail::Syntax { line, column } };
482    }
483
484    // `serde` reports a missing field at the struct that misses it, and names
485    // the field only in the message. The message itself is not kept - a
486    // type-mismatch message quotes the offending value - but the field name in
487    // it comes from the target type, so appending it is safe and gives a
488    // missing and a wrongly typed field the same shape of path.
489    let message = inner.to_string();
490    let path = render_path(&path, missing_field_name(&message));
491
492    DecodeError { detail: Detail::Data { path: path.into_boxed_str(), line, column } }
493}
494
495/// The most characters one name in a field path is rendered with before it is
496/// cut and marked with an ellipsis.
497///
498/// A name in a path can be a key the server chose - a question name, a legend
499/// level, a choice option - so it is bounded like any other server text in an
500/// error. The bound is well above any name a caller would give a question.
501const MAX_PATH_SEGMENT_CHARS: usize = 128;
502
503/// The most characters a whole field path is rendered with before it is cut
504/// and marked with an ellipsis.
505///
506/// It holds the deepest path the response schema has,
507/// `answers.<name>.probabilities.<option>`, with both names at their own cap.
508const MAX_PATH_CHARS: usize = 320;
509
510/// Renders a field path the way `serde_path_to_error` does - dotted names,
511/// bracketed indices, `.` for the root - with every name escaped and cut as
512/// `crate::text` describes, and a backslash written `\\` so that no escape
513/// can be mistaken for text. Each name is capped at [`MAX_PATH_SEGMENT_CHARS`]
514/// characters and the whole path at [`MAX_PATH_CHARS`].
515fn render_path(path: &serde_path_to_error::Path, missing: Option<&str>) -> String {
516    use serde_path_to_error::Segment;
517
518    let mut out = SafeText::new(MAX_PATH_CHARS, Backslash::Double);
519    // A name is preceded by a dot unless it starts the path; an index never
520    // is. Whether it starts the path cannot be read off the text, because a
521    // key may be the empty string.
522    let mut first = true;
523    for segment in path {
524        match segment {
525            Segment::Seq { index } => out.fixed(&format!("[{index}]")),
526            Segment::Map { key } | Segment::Enum { variant: key } => {
527                if !first {
528                    out.fixed(".");
529                }
530                out.untrusted(key, MAX_PATH_SEGMENT_CHARS);
531            }
532            Segment::Unknown => out.fixed(if first { "?" } else { ".?" }),
533        }
534        first = false;
535    }
536    match missing {
537        Some(field) => {
538            if !first {
539                out.fixed(".");
540            }
541            out.untrusted(field, MAX_PATH_SEGMENT_CHARS);
542        }
543        None if first => out.fixed("."),
544        None => {}
545    }
546    out.into_string()
547}
548
549/// Extracts `noul` from ``missing field `noul` at line 1 column 101``.
550fn missing_field_name(message: &str) -> Option<&str> {
551    let rest = message.strip_prefix("missing field `")?;
552    let end = rest.find('`')?;
553    Some(&rest[..end])
554}
555
556// ------------------------------------------------------------- raw JSON
557
558/// The private map key serde_json uses for arbitrary-precision numbers.
559const NUMBER_TOKEN: &str = "$serde_json::private::Number";
560
561thread_local! {
562    /// How many [`encode_into`] calls this thread is inside.
563    ///
564    /// A counter rather than a flag, because a `Serialize` implementation the
565    /// encoder reaches may encode a value of its own.
566    static INSIDE_SDK_ENCODER: Cell<u32> = const { Cell::new(0) };
567    /// How many synchronous SDK decode calls this thread is inside.
568    static INSIDE_SDK_DECODER: Cell<u32> = const { Cell::new(0) };
569}
570
571/// Marks the synchronous SDK decode, including its failure re-read.
572///
573/// This means the thread is inside the SDK, not that any particular serde
574/// deserializer is the SDK's: a caller decoding RawJson inside its own
575/// Deserialize implementation also gets the verbatim form. Enter only in
576/// decode/decode_seed, never across an await; the counter preserves nesting
577/// and Drop clears the mark during unwinding.
578struct DecoderMark;
579
580impl DecoderMark {
581    fn enter() -> Self {
582        INSIDE_SDK_DECODER.with(|depth| depth.set(depth.get().saturating_add(1)));
583        Self
584    }
585
586    #[cfg(not(feature = "sonic"))]
587    fn is_set() -> bool {
588        INSIDE_SDK_DECODER.with(|depth| depth.get() > 0)
589    }
590}
591
592impl Drop for DecoderMark {
593    fn drop(&mut self) {
594        INSIDE_SDK_DECODER.with(|depth| depth.set(depth.get().saturating_sub(1)));
595    }
596}
597
598/// Marks this thread as being inside the SDK's serializer while it lives.
599///
600/// serde offers no way to ask a `Serializer` which implementation it is, and
601/// the verbatim splice below is a protocol only this crate's codec
602/// understands. The mark is therefore set where the codec's serializer is
603/// built - [`encode_into`], the single place in the crate that builds one -
604/// and read by [`serialize_raw`].
605struct EncoderMark;
606
607impl EncoderMark {
608    fn enter() -> Self {
609        INSIDE_SDK_ENCODER.with(|depth| depth.set(depth.get().saturating_add(1)));
610        Self
611    }
612
613    /// Whether the value being serialized on this thread is on its way into
614    /// the SDK's own encoder.
615    fn is_set() -> bool {
616        INSIDE_SDK_ENCODER.with(|depth| depth.get() > 0)
617    }
618}
619
620impl Drop for EncoderMark {
621    fn drop(&mut self) {
622        INSIDE_SDK_ENCODER.with(|depth| depth.set(depth.get().saturating_sub(1)));
623    }
624}
625
626/// Writes raw JSON text through `serializer`.
627///
628/// Inside this crate's encoder the text is spliced in byte for byte. Through
629/// any other serializer it is streamed out as ordinary JSON data instead, so
630/// that a value which travels through, say, `serde_json` carries the data it
631/// holds rather than a protocol this crate's codec invented.
632///
633/// # Errors
634///
635/// Returns the serializer's own error, and a too-deep error when a value on
636/// the transcoding path is nested deeper than [`MAX_JSON_DEPTH`].
637fn serialize_raw<S>(text: &str, serializer: S) -> Result<S::Ok, S::Error>
638where
639    S: Serializer,
640{
641    if EncoderMark::is_set() { splice(text, serializer) } else { transcode(text, serializer) }
642}
643
644/// Hands `text` to this crate's codec for a verbatim splice.
645///
646/// Nothing parses the text here: a `RawJson` only ever holds text the codec
647/// produced or captured, so the splice writes bytes the codec has already
648/// accepted once.
649fn splice<S>(text: &str, serializer: S) -> Result<S::Ok, S::Error>
650where
651    S: Serializer,
652{
653    let mut raw = serializer.serialize_struct(SPLICE_TOKEN, 1)?;
654    raw.serialize_field(SPLICE_TOKEN, text)?;
655    raw.end()
656}
657
658/// Streams the JSON value in `text` into a serializer that is not this crate's
659/// codec.
660///
661/// Nothing is buffered and no value tree is built: every value read out of
662/// `text` is handed straight to `serializer`. The data is preserved; its
663/// spelling is not, because the target serializer chooses its own number
664/// format and drops the insignificant whitespace the text may carry.
665///
666/// # Errors
667///
668/// Returns a too-deep error when `text` is nested deeper than
669/// [`MAX_JSON_DEPTH`], and otherwise whatever `serializer` returns.
670fn transcode<S>(text: &str, serializer: S) -> Result<S::Ok, S::Error>
671where
672    S: Serializer,
673{
674    // Both the transcode and the parser driving it descend one stack frame per
675    // nesting level. The cap the decode path uses bounds that recursion, which
676    // is what stops a `RawJson` built by `RawJson::from_value` from an
677    // arbitrarily deep value from overflowing the stack here; the splice path
678    // above does not read the text at all and so needs no cap.
679    check_depth(text.as_bytes()).map_err(ser::Error::custom)?;
680
681    let mut source = backend::Deserializer::from_str(text);
682    Transcoder::new(&mut source).serialize(serializer)
683}
684
685/// The prefix that marks a serializer error on its way out through the
686/// deserializer driving a transcode.
687const REFUSED: &str = "the JSON writer refused a value: ";
688
689/// Wraps a serializer error so that it survives the trip out through the
690/// deserializer. The two halves of a transcode share no error type, so the
691/// message is all that can cross.
692fn writer_refused<E, D>(error: E) -> D
693where
694    E: fmt::Display,
695    D: de::Error,
696{
697    de::Error::custom(format_args!("{REFUSED}{error}"))
698}
699
700/// Turns the error a transcode comes back with into a serializer error.
701///
702/// Only a message [`writer_refused`] marked is passed on. Anything else was
703/// raised by the parser, whose `Display` embeds an excerpt of what it was
704/// reading, and the text of a `RawJson` may be application data.
705fn transcode_failed<E, S>(error: E) -> S
706where
707    E: fmt::Display,
708    S: ser::Error,
709{
710    let rendered = error.to_string();
711    match rendered.split_once(REFUSED) {
712        Some((_, message)) => ser::Error::custom(message),
713        None => ser::Error::custom("the stored JSON text could not be read back"),
714    }
715}
716
717/// A `Serialize` that writes whatever one deserializer yields.
718///
719/// serde drives serializing from the value side and deserializing from the
720/// visitor side, so a transcode has to hand the serializer something that
721/// implements `Serialize` and pulls from a deserializer when it is asked to
722/// write. That single call consumes the deserializer, which is why it sits in
723/// a `RefCell<Option<_>>` rather than being held by value.
724struct Transcoder<D> {
725    source: RefCell<Option<D>>,
726}
727
728impl<D> Transcoder<D> {
729    fn new(source: D) -> Self {
730        Self { source: RefCell::new(Some(source)) }
731    }
732}
733
734impl<'de, D> Serialize for Transcoder<D>
735where
736    D: Deserializer<'de>,
737{
738    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
739    where
740        S: Serializer,
741    {
742        let Some(source) = self.source.borrow_mut().take() else {
743            return Err(ser::Error::custom("a raw JSON value can be written only once"));
744        };
745        source.deserialize_any(TranscodeVisitor { serializer }).map_err(transcode_failed)
746    }
747}
748
749/// Hands every value it is shown straight to `serializer`.
750struct TranscodeVisitor<S> {
751    serializer: S,
752}
753
754impl<'de, S> de::Visitor<'de> for TranscodeVisitor<S>
755where
756    S: Serializer,
757{
758    type Value = S::Ok;
759
760    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
761        formatter.write_str("any JSON value")
762    }
763
764    fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
765        self.serializer.serialize_bool(value).map_err(writer_refused)
766    }
767
768    fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
769        self.serializer.serialize_i64(value).map_err(writer_refused)
770    }
771
772    fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
773        self.serializer.serialize_i128(value).map_err(writer_refused)
774    }
775
776    fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
777        self.serializer.serialize_u64(value).map_err(writer_refused)
778    }
779
780    fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
781        self.serializer.serialize_u128(value).map_err(writer_refused)
782    }
783
784    fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
785        self.serializer.serialize_f64(value).map_err(writer_refused)
786    }
787
788    fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
789        self.serializer.serialize_str(value).map_err(writer_refused)
790    }
791
792    fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
793        self.serializer.serialize_unit().map_err(writer_refused)
794    }
795
796    fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
797        self.serializer.serialize_none().map_err(writer_refused)
798    }
799
800    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
801    where
802        D: Deserializer<'de>,
803    {
804        deserializer.deserialize_any(self)
805    }
806
807    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
808    where
809        D: Deserializer<'de>,
810    {
811        deserializer.deserialize_any(self)
812    }
813
814    fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
815    where
816        A: de::SeqAccess<'de>,
817    {
818        let mut sequence =
819            self.serializer.serialize_seq(access.size_hint()).map_err(writer_refused)?;
820        while access.next_element_seed(TranscodeElement { sequence: &mut sequence })?.is_some() {}
821        sequence.end().map_err(writer_refused)
822    }
823
824    fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
825    where
826        A: de::MapAccess<'de>,
827    {
828        #[cfg(not(feature = "sonic"))]
829        let first = access.next_key_seed(TextSeed)?;
830        #[cfg(not(feature = "sonic"))]
831        if first.as_deref() == Some(NUMBER_TOKEN) {
832            let text: String = access.next_value()?;
833            if access.next_key::<IgnoredAny>()?.is_some() {
834                return Err(de::Error::custom("a JSON number token must be the only entry"));
835            }
836            // Match serde_json without arbitrary_precision: wide integers
837            // become f64 here, not serializer-dependent 128-bit integers.
838            if let Ok(value) = text.parse::<u64>() {
839                return self.serializer.serialize_u64(value).map_err(writer_refused);
840            }
841            if let Ok(value) = text.parse::<i64>() {
842                return self.serializer.serialize_i64(value).map_err(writer_refused);
843            }
844            let value = text
845                .parse::<f64>()
846                .map_err(|_| <A::Error as de::Error>::custom("number out of range"))?;
847            if !value.is_finite() {
848                return Err(de::Error::custom("number out of range"));
849            }
850            return self.serializer.serialize_f64(value).map_err(writer_refused);
851        }
852        let mut map = self.serializer.serialize_map(access.size_hint()).map_err(writer_refused)?;
853        #[cfg(not(feature = "sonic"))]
854        match first {
855            Some(key) => {
856                map.serialize_key(key.as_ref()).map_err(writer_refused)?;
857                access.next_value_seed(TranscodeValue { map: &mut map })?;
858            }
859            None => return map.end().map_err(writer_refused),
860        }
861        loop {
862            let key = access.next_key_seed(TranscodeKey { map: &mut map })?;
863            if key.is_none() {
864                break;
865            }
866            access.next_value_seed(TranscodeValue { map: &mut map })?;
867        }
868        map.end().map_err(writer_refused)
869    }
870}
871
872/// Writes the element the deserializer is positioned on into `sequence`.
873struct TranscodeElement<'s, S> {
874    sequence: &'s mut S,
875}
876
877impl<'de, S> de::DeserializeSeed<'de> for TranscodeElement<'_, S>
878where
879    S: SerializeSeq,
880{
881    type Value = ();
882
883    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
884    where
885        D: Deserializer<'de>,
886    {
887        self.sequence.serialize_element(&Transcoder::new(deserializer)).map_err(writer_refused)
888    }
889}
890
891/// Writes the key the deserializer is positioned on into `map`.
892struct TranscodeKey<'s, S> {
893    map: &'s mut S,
894}
895
896impl<'de, S> de::DeserializeSeed<'de> for TranscodeKey<'_, S>
897where
898    S: SerializeMap,
899{
900    type Value = ();
901
902    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
903    where
904        D: Deserializer<'de>,
905    {
906        self.map.serialize_key(&Transcoder::new(deserializer)).map_err(writer_refused)
907    }
908}
909
910/// Writes the value the deserializer is positioned on into `map`.
911struct TranscodeValue<'s, S> {
912    map: &'s mut S,
913}
914
915impl<'de, S> de::DeserializeSeed<'de> for TranscodeValue<'_, S>
916where
917    S: SerializeMap,
918{
919    type Value = ();
920
921    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
922    where
923        D: Deserializer<'de>,
924    {
925        self.map.serialize_value(&Transcoder::new(deserializer)).map_err(writer_refused)
926    }
927}
928
929/// Rejects text that is not exactly one complete JSON value.
930///
931/// A [`RawJson`] is written into a request body without being read again, so
932/// text carrying a second value would splice that value - a key of the
933/// caller's choosing, say - into the enclosing object, and text that is not
934/// JSON at all would make the whole body unparseable. Every value this codec
935/// captures is one value already; what needs guarding is a string handed over
936/// by a deserializer that answered the raw-text request with whatever the
937/// caller had put in it.
938///
939/// The scan allocates nothing on the accepting path: the depth pre-scan reads
940/// the bytes, and the parser then skips one value and checks that only
941/// whitespace follows.
942fn one_json_value<E: de::Error>(text: &str) -> Result<(), E> {
943    decode::<IgnoredAny>(text.as_bytes()).map_err(de::Error::custom)?;
944    Ok(())
945}
946
947/// Reads the next value as its raw JSON text, without interpreting it.
948///
949/// This crate's codec answers the request with the text of the value as the
950/// wire carried it, borrowed from the input whenever it can be - which it
951/// cannot when the value is a string holding escape sequences. Any other
952/// deserializer does not know the request and passes itself on instead; the
953/// value is then read as ordinary JSON and rendered back to compact text, so
954/// what comes out holds the same data rather than failing.
955///
956/// A format that neither knows the request nor forwards itself, but answers it
957/// with a bare string, cannot be told apart from the codec's own raw-text
958/// answer, so the string is read as JSON text rather than as a JSON string.
959/// Such text is checked before it is accepted: one complete JSON value is
960/// taken at face value, and anything else - a second value after the first,
961/// or text that is not JSON - is refused rather than carried into a request
962/// body. No JSON codec behaves that way, so in practice this guards a string
963/// a caller supplied by hand.
964///
965/// # Errors
966///
967/// Returns the deserializer's own error, and a too-deep error when a document
968/// read through a foreign deserializer nests deeper than [`MAX_JSON_DEPTH`].
969pub(crate) fn deserialize_raw<'de, D>(deserializer: D) -> Result<Cow<'de, str>, D::Error>
970where
971    D: Deserializer<'de>,
972{
973    deserializer.deserialize_newtype_struct(SPLICE_TOKEN, RawTextVisitor)
974}
975
976/// A string seed that retains a borrow or takes an owned string without copying it.
977#[cfg(not(feature = "sonic"))]
978struct TextSeed;
979
980#[cfg(not(feature = "sonic"))]
981impl<'de> DeserializeSeed<'de> for TextSeed {
982    type Value = Cow<'de, str>;
983
984    fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
985        deserializer.deserialize_str(self)
986    }
987}
988
989#[cfg(not(feature = "sonic"))]
990impl<'de> de::Visitor<'de> for TextSeed {
991    type Value = Cow<'de, str>;
992
993    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
994        formatter.write_str("a string")
995    }
996
997    fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Self::Value, E> {
998        Ok(Cow::Borrowed(value))
999    }
1000
1001    fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
1002        Ok(Cow::Owned(value.to_owned()))
1003    }
1004
1005    fn visit_string<E: de::Error>(self, value: String) -> Result<Self::Value, E> {
1006        Ok(Cow::Owned(value))
1007    }
1008}
1009
1010/// The raw text or ordinary data a deserializer provides.
1011struct RawTextVisitor;
1012
1013impl<'de> de::Visitor<'de> for RawTextVisitor {
1014    type Value = Cow<'de, str>;
1015
1016    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1017        formatter.write_str("any JSON value")
1018    }
1019
1020    /// This crate's codec, handing over the raw text of the value.
1021    ///
1022    /// The check is redundant for that codec, which never hands over anything
1023    /// else, and is what holds the invariant for a deserializer that answers
1024    /// the raw-text request with a string of the caller's own. The borrow
1025    /// survives it.
1026    fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Self::Value, E> {
1027        one_json_value(value)?;
1028        Ok(Cow::Borrowed(value))
1029    }
1030
1031    /// The same, for text the codec had to rebuild because it holds escapes.
1032    fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
1033        one_json_value(value)?;
1034        Ok(Cow::Owned(value.to_owned()))
1035    }
1036
1037    fn visit_string<E: de::Error>(self, value: String) -> Result<Self::Value, E> {
1038        one_json_value(&value)?;
1039        Ok(Cow::Owned(value))
1040    }
1041
1042    /// Any other deserializer: it does not know the request above, so it hands
1043    /// itself over and the value is read as data.
1044    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1045    where
1046        D: Deserializer<'de>,
1047    {
1048        let mut out = Vec::new();
1049        deserializer.deserialize_any(Render { out: &mut out, depth: 0 })?;
1050        Ok(Cow::Owned(rendered_text(out)))
1051    }
1052
1053    fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
1054        Ok(Cow::Borrowed(if value { "true" } else { "false" }))
1055    }
1056
1057    fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
1058        render_scalar(&value)
1059    }
1060
1061    fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
1062        render_scalar(&value)
1063    }
1064
1065    fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
1066        render_scalar(&value)
1067    }
1068
1069    fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
1070        render_scalar(&value)
1071    }
1072
1073    fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
1074        render_scalar(&value)
1075    }
1076
1077    fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
1078        Ok(Cow::Borrowed("null"))
1079    }
1080
1081    fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
1082        Ok(Cow::Borrowed("null"))
1083    }
1084
1085    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1086    where
1087        D: Deserializer<'de>,
1088    {
1089        self.visit_newtype_struct(deserializer)
1090    }
1091
1092    fn visit_seq<A>(self, access: A) -> Result<Self::Value, A::Error>
1093    where
1094        A: de::SeqAccess<'de>,
1095    {
1096        let mut out = Vec::new();
1097        de::Visitor::visit_seq(Render { out: &mut out, depth: 0 }, access)?;
1098        Ok(Cow::Owned(rendered_text(out)))
1099    }
1100
1101    #[cfg(feature = "sonic")]
1102    fn visit_map<A>(self, access: A) -> Result<Self::Value, A::Error>
1103    where
1104        A: de::MapAccess<'de>,
1105    {
1106        let mut out = Vec::new();
1107        de::Visitor::visit_map(Render { out: &mut out, depth: 0 }, access)?;
1108        Ok(Cow::Owned(rendered_text(out)))
1109    }
1110
1111    #[cfg(not(feature = "sonic"))]
1112    fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
1113    where
1114        A: de::MapAccess<'de>,
1115    {
1116        let first = access.next_key_seed(TextSeed)?;
1117        let mut out = Vec::new();
1118        match first {
1119            Some(key) if key == SPLICE_TOKEN => {
1120                let text = access.next_value_seed(TextSeed)?;
1121                one_json_value(&text)?;
1122                if access.next_key::<IgnoredAny>()?.is_some() {
1123                    return Err(de::Error::custom("a raw JSON token must be the only entry"));
1124                }
1125                // one_json_value entered and left its own mark; only an outer
1126                // SDK decode still has one. A caller's reload always renders.
1127                if DecoderMark::is_set() {
1128                    return Ok(text);
1129                }
1130                let mut source = backend::Deserializer::from_str(&text);
1131                Render { out: &mut out, depth: 0 }
1132                    .deserialize(&mut source)
1133                    .map_err(de::Error::custom)?;
1134                source.end().map_err(de::Error::custom)?;
1135            }
1136            Some(key) => Render { out: &mut out, depth: 0 }.map_after_key(&key, access)?,
1137            None => out.extend_from_slice(b"{}"),
1138        }
1139        Ok(Cow::Owned(rendered_text(out)))
1140    }
1141}
1142
1143/// Encodes one scalar on its own, for a value that reached
1144/// [`RawTextVisitor`] without any surrounding structure.
1145fn render_scalar<'de, T, E>(value: &T) -> Result<Cow<'de, str>, E>
1146where
1147    T: Serialize + ?Sized,
1148    E: de::Error,
1149{
1150    let mut out = Vec::new();
1151    encode_into(&mut out, value).map_err(de::Error::custom)?;
1152    Ok(Cow::Owned(rendered_text(out)))
1153}
1154
1155/// The bytes a render wrote, as text.
1156fn rendered_text(out: Vec<u8>) -> String {
1157    String::from_utf8(out).expect("invariant: the renderer emits UTF-8")
1158}
1159
1160/// Writes one JSON value, read from a deserializer that is not this crate's
1161/// codec, into `out` as compact JSON text.
1162///
1163/// It is both the seed that a container hands to its elements and the visitor
1164/// that writes them, so a nested document costs one stack frame per level and
1165/// no intermediate value.
1166struct Render<'b> {
1167    out: &'b mut Vec<u8>,
1168    depth: usize,
1169}
1170
1171impl Render<'_> {
1172    /// Continues an object after its first key was read by raw-value dispatch.
1173    #[cfg(not(feature = "sonic"))]
1174    fn map_after_key<'de, A: de::MapAccess<'de>>(
1175        self,
1176        key: &str,
1177        access: A,
1178    ) -> Result<(), A::Error> {
1179        if key == NUMBER_TOKEN {
1180            return self.number_map(access);
1181        }
1182        self.out.push(b'{');
1183        write_json_string(self.out, key);
1184        self.finish_map(access)
1185    }
1186
1187    /// Finishes an object whose opening brace and first key are already written.
1188    fn finish_map<'de, A: de::MapAccess<'de>>(self, mut access: A) -> Result<(), A::Error> {
1189        let inner = one_level_in(self.depth)?;
1190        let out = self.out;
1191        out.push(b':');
1192        access.next_value_seed(Render { out: &mut *out, depth: inner })?;
1193        while access.next_key_seed(RenderKey { out: &mut *out, first: false })?.is_some() {
1194            out.push(b':');
1195            access.next_value_seed(Render { out: &mut *out, depth: inner })?;
1196        }
1197        out.push(b'}');
1198        Ok(())
1199    }
1200
1201    /// Renders serde_json's number protocol as a scalar, not an object.
1202    fn number_map<'de, A: de::MapAccess<'de>>(self, mut access: A) -> Result<(), A::Error> {
1203        let text: String = access.next_value()?;
1204        if !matches!(text.as_bytes().first(), Some(b'-' | b'0'..=b'9'))
1205            || !text.as_bytes().last().is_some_and(u8::is_ascii_digit)
1206        {
1207            return Err(de::Error::custom("invalid JSON number token"));
1208        }
1209        one_json_value(&text)?;
1210        if access.next_key::<IgnoredAny>()?.is_some() {
1211            return Err(de::Error::custom("a JSON number token must be the only entry"));
1212        }
1213        // arbitrary_precision preserves scanned text here, including 1e400;
1214        // the transcoder instead requires a finite typed number. A caller's
1215        // arbitrary_precision combined with the sonic feature has no test run.
1216        self.out.extend_from_slice(text.as_bytes());
1217        Ok(())
1218    }
1219}
1220
1221/// The depth one level in, or a too-deep error at the cap.
1222fn one_level_in<E: de::Error>(depth: usize) -> Result<usize, E> {
1223    if depth >= MAX_JSON_DEPTH {
1224        return Err(de::Error::custom(DecodeError::too_deep()));
1225    }
1226    Ok(depth + 1)
1227}
1228
1229impl<'de> de::DeserializeSeed<'de> for Render<'_> {
1230    type Value = ();
1231
1232    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1233    where
1234        D: Deserializer<'de>,
1235    {
1236        deserializer.deserialize_any(self)
1237    }
1238}
1239
1240impl<'de> de::Visitor<'de> for Render<'_> {
1241    type Value = ();
1242
1243    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1244        formatter.write_str("any JSON value")
1245    }
1246
1247    fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
1248        self.out.extend_from_slice(if value { b"true" } else { b"false" });
1249        Ok(())
1250    }
1251
1252    fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
1253        encode_into(self.out, &value).map_err(de::Error::custom)
1254    }
1255
1256    fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
1257        encode_into(self.out, &value).map_err(de::Error::custom)
1258    }
1259
1260    fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
1261        encode_into(self.out, &value).map_err(de::Error::custom)
1262    }
1263
1264    fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
1265        encode_into(self.out, &value).map_err(de::Error::custom)
1266    }
1267
1268    fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
1269        encode_into(self.out, &value).map_err(de::Error::custom)
1270    }
1271
1272    fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
1273        write_json_string(self.out, value);
1274        Ok(())
1275    }
1276
1277    fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
1278        self.out.extend_from_slice(b"null");
1279        Ok(())
1280    }
1281
1282    fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
1283        self.out.extend_from_slice(b"null");
1284        Ok(())
1285    }
1286
1287    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1288    where
1289        D: Deserializer<'de>,
1290    {
1291        deserializer.deserialize_any(self)
1292    }
1293
1294    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1295    where
1296        D: Deserializer<'de>,
1297    {
1298        deserializer.deserialize_any(self)
1299    }
1300
1301    fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
1302    where
1303        A: de::SeqAccess<'de>,
1304    {
1305        let inner = one_level_in(self.depth)?;
1306        let out = self.out;
1307        out.push(b'[');
1308        let mut first = true;
1309        loop {
1310            let element = RenderElement { out: &mut *out, depth: inner, first };
1311            if access.next_element_seed(element)?.is_none() {
1312                break;
1313            }
1314            first = false;
1315        }
1316        out.push(b']');
1317        Ok(())
1318    }
1319
1320    fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
1321    where
1322        A: de::MapAccess<'de>,
1323    {
1324        match access.next_key_seed(RenderKey { out: &mut *self.out, first: true })? {
1325            Some(true) => self.number_map(access),
1326            Some(false) => self.finish_map(access),
1327            None => {
1328                one_level_in::<A::Error>(self.depth)?;
1329                self.out.extend_from_slice(b"{}");
1330                Ok(())
1331            }
1332        }
1333    }
1334}
1335
1336/// One element of an array, with the comma that precedes it.
1337///
1338/// The separator is written here rather than in the loop because whether there
1339/// is another element is only known once the deserializer has been asked for
1340/// it, and asking is what renders it.
1341struct RenderElement<'b> {
1342    out: &'b mut Vec<u8>,
1343    depth: usize,
1344    first: bool,
1345}
1346
1347impl<'de> de::DeserializeSeed<'de> for RenderElement<'_> {
1348    type Value = ();
1349
1350    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1351    where
1352        D: Deserializer<'de>,
1353    {
1354        if !self.first {
1355            self.out.push(b',');
1356        }
1357        deserializer.deserialize_any(Render { out: self.out, depth: self.depth })
1358    }
1359}
1360
1361/// One key of an object, with the comma that precedes it. A JSON key is always
1362/// a string, so anything else is a type error rather than a rendered value.
1363struct RenderKey<'b> {
1364    out: &'b mut Vec<u8>,
1365    first: bool,
1366}
1367
1368impl<'de> de::DeserializeSeed<'de> for RenderKey<'_> {
1369    type Value = bool;
1370
1371    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1372    where
1373        D: Deserializer<'de>,
1374    {
1375        deserializer.deserialize_str(self)
1376    }
1377}
1378
1379impl<'de> de::Visitor<'de> for RenderKey<'_> {
1380    type Value = bool;
1381
1382    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1383        formatter.write_str("a JSON object key")
1384    }
1385
1386    fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
1387        if self.first && value == NUMBER_TOKEN {
1388            return Ok(true);
1389        }
1390        self.out.push(if self.first { b'{' } else { b',' });
1391        write_json_string(self.out, value);
1392        Ok(false)
1393    }
1394}
1395
1396/// An owned piece of JSON text that travels through the SDK unchanged.
1397///
1398/// It holds whatever value it was built from - an object, an array or a
1399/// scalar - as the text the wire carried, so a response field of a shape this
1400/// version does not know survives a decode and can be read later with
1401/// [`decode`](RawJson::decode). Two values are equal when their text
1402/// is equal, which means equality is textual: `{"a":1}` and `{ "a": 1 }` are
1403/// different values.
1404///
1405/// # Invariant
1406///
1407/// The text is always exactly one complete JSON value whose structure is
1408/// valid. Nothing builds a `RawJson` without the codec having established
1409/// that, because the text is written into a request body unread: a second
1410/// value in it would become a field of the enclosing object. Escapes inside
1411/// strings are passed through unchecked: a `\u` escape with bad hex digits,
1412/// or a lone surrogate half, is kept as it was written, and a strict server
1413/// refuses the request that carries it. String boundaries are found the same
1414/// way either way, so such an escape cannot end a string early.
1415///
1416/// # Serialization
1417///
1418/// Inside the SDK the text is spliced into the request body byte for byte:
1419/// key order, spacing and the exact spelling of every number are what the
1420/// caller or the server wrote. Through any other serializer - `serde_json`,
1421/// for instance - the value is written out as ordinary JSON data instead, so
1422/// the data survives while its spelling may not: numbers are re-rendered by
1423/// that serializer and insignificant whitespace is dropped.
1424///
1425/// Which of the two happens is decided by whether the SDK's own encoder is
1426/// running on this thread, not by the type of the serializer, because serde
1427/// offers no way to ask a serializer what it is. A `RawJson` handed to a
1428/// foreign serializer from inside a caller's own `Serialize` implementation
1429/// while the SDK is encoding a request is therefore spliced rather than
1430/// transcoded; use [`as_str`](RawJson::as_str) there.
1431#[derive(Clone, PartialEq, Eq, Hash)]
1432pub struct RawJson {
1433    text: Box<str>,
1434}
1435
1436impl RawJson {
1437    /// Encodes `value` and keeps the resulting JSON text.
1438    ///
1439    /// # Errors
1440    ///
1441    /// Returns [`EncodeError`] when the value cannot be represented as JSON.
1442    pub fn from_value<T>(value: &T) -> Result<Self, EncodeError>
1443    where
1444        T: Serialize + ?Sized,
1445    {
1446        let mut buffer = Vec::new();
1447        encode_into(&mut buffer, value)?;
1448        Ok(Self::from_text(String::from_utf8(buffer).expect("invariant: the codec emits UTF-8")))
1449    }
1450
1451    /// The JSON text, exactly as it was received or encoded.
1452    #[must_use]
1453    pub fn as_str(&self) -> &str {
1454        &self.text
1455    }
1456
1457    /// Decodes the held text into `T`.
1458    ///
1459    /// It is `decode` rather than `deserialize` so that it does not shadow
1460    /// [`Deserialize::deserialize`], which a caller reaches for when they read
1461    /// a `RawJson` out of a document with a codec of their own.
1462    ///
1463    /// # Errors
1464    ///
1465    /// Returns [`DecodeError`] when the text does not have the shape `T`
1466    /// expects, or when it is nested deeper than the decoder allows - which a
1467    /// value built by [`from_value`](RawJson::from_value) can be, since
1468    /// encoding is not depth limited.
1469    pub fn decode<'de, T>(&'de self) -> Result<T, DecodeError>
1470    where
1471        T: Deserialize<'de>,
1472    {
1473        decode(self.text.as_bytes())
1474    }
1475
1476    /// Wraps text the codec has already established to be one JSON value:
1477    /// what [`encode_into`] wrote, or what [`deserialize_raw`] captured and
1478    /// checked.
1479    pub(crate) fn from_text(text: String) -> Self {
1480        Self { text: text.into_boxed_str() }
1481    }
1482}
1483
1484impl fmt::Debug for RawJson {
1485    /// Prints the JSON text itself, with control characters and the format
1486    /// characters that reorder or hide text written as Rust escapes: JSON
1487    /// allows those raw inside a string, the text usually came from a server,
1488    /// and a `{:?}` usually ends up in a log line. Backslashes are kept as
1489    /// they are, since they are the JSON's own escapes. `Display`,
1490    /// [`as_str`](RawJson::as_str) and serialization give the text byte for
1491    /// byte. The default derive would wrap the text in a struct with one
1492    /// field and quote it a second time.
1493    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1494        let mut shown = SafeText::new(usize::MAX, Backslash::Keep);
1495        shown.untrusted(&self.text, usize::MAX);
1496        formatter.write_str(&shown.into_string())
1497    }
1498}
1499
1500impl fmt::Display for RawJson {
1501    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1502        formatter.write_str(&self.text)
1503    }
1504}
1505
1506impl Serialize for RawJson {
1507    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1508    where
1509        S: Serializer,
1510    {
1511        serialize_raw(&self.text, serializer)
1512    }
1513}
1514
1515impl<'de> Deserialize<'de> for RawJson {
1516    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1517    where
1518        D: Deserializer<'de>,
1519    {
1520        deserialize_raw(deserializer).map(|raw| Self::from_text(raw.into_owned()))
1521    }
1522}
1523
1524#[cfg(test)]
1525#[path = "codec_tests.rs"]
1526mod tests;