pub(crate) mod backend;
use std::{
borrow::Cow,
cell::{Cell, RefCell},
fmt,
marker::PhantomData,
};
use bytes::Bytes;
use serde::{
Deserialize, Deserializer, Serialize, Serializer, de,
de::{DeserializeSeed, IgnoredAny},
ser,
ser::{SerializeMap, SerializeSeq, SerializeStruct},
};
use thiserror::Error;
use self::backend::SPLICE_TOKEN;
use crate::text::{Backslash, SafeText};
pub(crate) const MAX_JSON_DEPTH: usize = 16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DecodeErrorKind {
TooDeep,
Syntax,
Data,
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[error("{detail}")]
#[non_exhaustive]
pub struct DecodeError {
detail: Detail,
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
enum Detail {
#[error("JSON input is nested deeper than the maximum of {}", MAX_JSON_DEPTH)]
TooDeep,
#[error("invalid JSON syntax at line {line} column {column}")]
Syntax { line: usize, column: usize },
#[error("unexpected JSON value at `{path}`, line {line} column {column}")]
Data { path: Box<str>, line: usize, column: usize },
#[error("the JSON document does not have the expected shape")]
Opaque,
}
impl DecodeError {
#[must_use]
pub fn kind(&self) -> DecodeErrorKind {
match self.detail {
Detail::TooDeep => DecodeErrorKind::TooDeep,
Detail::Syntax { .. } => DecodeErrorKind::Syntax,
Detail::Data { .. } | Detail::Opaque => DecodeErrorKind::Data,
}
}
#[must_use]
pub fn line(&self) -> usize {
match self.detail {
Detail::TooDeep | Detail::Opaque => 0,
Detail::Syntax { line, .. } | Detail::Data { line, .. } => line,
}
}
#[must_use]
pub fn column(&self) -> usize {
match self.detail {
Detail::TooDeep | Detail::Opaque => 0,
Detail::Syntax { column, .. } | Detail::Data { column, .. } => column,
}
}
#[must_use]
pub fn path(&self) -> &str {
match &self.detail {
Detail::TooDeep | Detail::Syntax { .. } | Detail::Opaque => "",
Detail::Data { path, .. } => path,
}
}
fn too_deep() -> Self {
Self { detail: Detail::TooDeep }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[error("the value could not be encoded as JSON: {message}")]
#[non_exhaustive]
pub struct EncodeError {
message: Box<str>,
}
impl EncodeError {
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
fn from_codec(error: backend::Error) -> Self {
Self { message: error.to_string().into_boxed_str() }
}
}
thread_local! {
static SCRATCH: RefCell<Option<Vec<u8>>> = const { RefCell::new(None) };
static SCRATCH_HINT: Cell<usize> = const { Cell::new(0) };
}
const MAX_RETAINED_SCRATCH: usize = 8 * 1024 * 1024;
pub(crate) fn encode_into<T>(buf: &mut Vec<u8>, value: &T) -> Result<(), EncodeError>
where
T: Serialize + ?Sized,
{
let _inside = EncoderMark::enter();
backend::to_writer(&mut *buf, value).map_err(EncodeError::from_codec)
}
pub(crate) fn write_json_string(buf: &mut Vec<u8>, text: &str) {
encode_into(buf, text).expect("invariant: encoding a string into a Vec cannot fail");
}
pub(crate) fn encode_body<F>(fill: F) -> Result<Bytes, EncodeError>
where
F: FnOnce(&mut Vec<u8>) -> Result<(), EncodeError>,
{
let mut scratch = SCRATCH.with(|cell| cell.borrow_mut().take()).unwrap_or_default();
scratch.clear();
let body = fill(&mut scratch).map(|()| Bytes::from(scratch.as_slice().to_vec()));
let hint = SCRATCH_HINT.get();
let decayed = scratch.len().max(hint - hint / 16);
SCRATCH_HINT.set(decayed);
if scratch.capacity() > MAX_RETAINED_SCRATCH {
scratch = Vec::new();
} else if scratch.capacity() > decayed.saturating_mul(8) {
scratch.shrink_to(decayed);
}
SCRATCH.with(|cell| cell.replace(Some(scratch)));
body
}
#[cfg(any(test, feature = "internals"))]
pub(crate) fn scratch_capacity() -> usize {
SCRATCH.with(|cell| cell.borrow().as_ref().map_or(0, Vec::capacity))
}
#[cfg(any(test, feature = "internals"))]
pub(crate) fn scratch_hint() -> usize {
SCRATCH_HINT.get()
}
#[cfg(any(test, feature = "internals"))]
pub(crate) fn reset_scratch() {
SCRATCH.with(|cell| cell.replace(None));
SCRATCH_HINT.set(0);
}
pub(crate) fn check_depth(json: &[u8]) -> Result<(), DecodeError> {
let mut depth = 0usize;
let mut in_string = false;
let mut escaped = false;
for &byte in json {
if in_string {
if escaped {
escaped = false;
} else if byte == b'\\' {
escaped = true;
} else if byte == b'"' {
in_string = false;
}
continue;
}
match byte {
b'"' => in_string = true,
b'[' | b'{' => {
depth += 1;
if depth > MAX_JSON_DEPTH {
return Err(DecodeError::too_deep());
}
}
b']' | b'}' => depth = depth.saturating_sub(1),
_ => {}
}
}
Ok(())
}
fn as_text(bytes: &[u8]) -> Result<&str, DecodeError> {
std::str::from_utf8(bytes).map_err(|failure| {
let before = &bytes[..failure.valid_up_to()];
let line = 1 + before.iter().filter(|&&byte| byte == b'\n').count();
let line_start = before.iter().rposition(|&byte| byte == b'\n').map_or(0, |at| at + 1);
let column = 1 + before.len() - line_start;
DecodeError { detail: Detail::Syntax { line, column } }
})
}
pub(crate) fn decode<'de, T>(bytes: &'de [u8]) -> Result<T, DecodeError>
where
T: Deserialize<'de>,
{
let text = as_text(bytes)?;
check_depth(bytes)?;
let _inside = DecoderMark::enter();
backend::from_str::<T>(text).map_err(|_| describe_failure(text, PhantomData::<T>))
}
pub(crate) fn decode_seed<'de, S>(bytes: &'de [u8], seed: S) -> Result<S::Value, DecodeError>
where
S: DeserializeSeed<'de> + Clone,
{
let text = as_text(bytes)?;
check_depth(bytes)?;
let _inside = DecoderMark::enter();
let decoded = {
let mut deserializer = backend::Deserializer::from_str(text);
seed.clone()
.deserialize(&mut deserializer)
.ok()
.and_then(|value| deserializer.end().ok().map(|()| value))
};
decoded.ok_or_else(|| describe_failure(text, seed))
}
fn describe_failure<'de, S>(text: &'de str, seed: S) -> DecodeError
where
S: DeserializeSeed<'de>,
{
let mut deserializer = backend::Deserializer::from_str(text);
let mut track = serde_path_to_error::Track::new();
let failure = seed
.deserialize(serde_path_to_error::Deserializer::new(&mut deserializer, &mut track))
.err();
let Some(inner) = failure else {
return match deserializer.end() {
Err(trailing) => {
let (line, column) = backend::error_position(&trailing);
DecodeError { detail: Detail::Syntax { line, column } }
}
Ok(()) => DecodeError { detail: Detail::Opaque },
};
};
let path = track.path();
let (line, column) = backend::error_position(&inner);
if backend::is_syntax(&inner) {
return DecodeError { detail: Detail::Syntax { line, column } };
}
let message = inner.to_string();
let path = render_path(&path, missing_field_name(&message));
DecodeError { detail: Detail::Data { path: path.into_boxed_str(), line, column } }
}
const MAX_PATH_SEGMENT_CHARS: usize = 128;
const MAX_PATH_CHARS: usize = 320;
fn render_path(path: &serde_path_to_error::Path, missing: Option<&str>) -> String {
use serde_path_to_error::Segment;
let mut out = SafeText::new(MAX_PATH_CHARS, Backslash::Double);
let mut first = true;
for segment in path {
match segment {
Segment::Seq { index } => out.fixed(&format!("[{index}]")),
Segment::Map { key } | Segment::Enum { variant: key } => {
if !first {
out.fixed(".");
}
out.untrusted(key, MAX_PATH_SEGMENT_CHARS);
}
Segment::Unknown => out.fixed(if first { "?" } else { ".?" }),
}
first = false;
}
match missing {
Some(field) => {
if !first {
out.fixed(".");
}
out.untrusted(field, MAX_PATH_SEGMENT_CHARS);
}
None if first => out.fixed("."),
None => {}
}
out.into_string()
}
fn missing_field_name(message: &str) -> Option<&str> {
let rest = message.strip_prefix("missing field `")?;
let end = rest.find('`')?;
Some(&rest[..end])
}
const NUMBER_TOKEN: &str = "$serde_json::private::Number";
thread_local! {
static INSIDE_SDK_ENCODER: Cell<u32> = const { Cell::new(0) };
static INSIDE_SDK_DECODER: Cell<u32> = const { Cell::new(0) };
}
struct DecoderMark;
impl DecoderMark {
fn enter() -> Self {
INSIDE_SDK_DECODER.with(|depth| depth.set(depth.get().saturating_add(1)));
Self
}
#[cfg(not(feature = "sonic"))]
fn is_set() -> bool {
INSIDE_SDK_DECODER.with(|depth| depth.get() > 0)
}
}
impl Drop for DecoderMark {
fn drop(&mut self) {
INSIDE_SDK_DECODER.with(|depth| depth.set(depth.get().saturating_sub(1)));
}
}
struct EncoderMark;
impl EncoderMark {
fn enter() -> Self {
INSIDE_SDK_ENCODER.with(|depth| depth.set(depth.get().saturating_add(1)));
Self
}
fn is_set() -> bool {
INSIDE_SDK_ENCODER.with(|depth| depth.get() > 0)
}
}
impl Drop for EncoderMark {
fn drop(&mut self) {
INSIDE_SDK_ENCODER.with(|depth| depth.set(depth.get().saturating_sub(1)));
}
}
fn serialize_raw<S>(text: &str, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if EncoderMark::is_set() { splice(text, serializer) } else { transcode(text, serializer) }
}
fn splice<S>(text: &str, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut raw = serializer.serialize_struct(SPLICE_TOKEN, 1)?;
raw.serialize_field(SPLICE_TOKEN, text)?;
raw.end()
}
fn transcode<S>(text: &str, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
check_depth(text.as_bytes()).map_err(ser::Error::custom)?;
let mut source = backend::Deserializer::from_str(text);
Transcoder::new(&mut source).serialize(serializer)
}
const REFUSED: &str = "the JSON writer refused a value: ";
fn writer_refused<E, D>(error: E) -> D
where
E: fmt::Display,
D: de::Error,
{
de::Error::custom(format_args!("{REFUSED}{error}"))
}
fn transcode_failed<E, S>(error: E) -> S
where
E: fmt::Display,
S: ser::Error,
{
let rendered = error.to_string();
match rendered.split_once(REFUSED) {
Some((_, message)) => ser::Error::custom(message),
None => ser::Error::custom("the stored JSON text could not be read back"),
}
}
struct Transcoder<D> {
source: RefCell<Option<D>>,
}
impl<D> Transcoder<D> {
fn new(source: D) -> Self {
Self { source: RefCell::new(Some(source)) }
}
}
impl<'de, D> Serialize for Transcoder<D>
where
D: Deserializer<'de>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(source) = self.source.borrow_mut().take() else {
return Err(ser::Error::custom("a raw JSON value can be written only once"));
};
source.deserialize_any(TranscodeVisitor { serializer }).map_err(transcode_failed)
}
}
struct TranscodeVisitor<S> {
serializer: S,
}
impl<'de, S> de::Visitor<'de> for TranscodeVisitor<S>
where
S: Serializer,
{
type Value = S::Ok;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("any JSON value")
}
fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
self.serializer.serialize_bool(value).map_err(writer_refused)
}
fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
self.serializer.serialize_i64(value).map_err(writer_refused)
}
fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
self.serializer.serialize_i128(value).map_err(writer_refused)
}
fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
self.serializer.serialize_u64(value).map_err(writer_refused)
}
fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
self.serializer.serialize_u128(value).map_err(writer_refused)
}
fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
self.serializer.serialize_f64(value).map_err(writer_refused)
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
self.serializer.serialize_str(value).map_err(writer_refused)
}
fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
self.serializer.serialize_unit().map_err(writer_refused)
}
fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
self.serializer.serialize_none().map_err(writer_refused)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
let mut sequence =
self.serializer.serialize_seq(access.size_hint()).map_err(writer_refused)?;
while access.next_element_seed(TranscodeElement { sequence: &mut sequence })?.is_some() {}
sequence.end().map_err(writer_refused)
}
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
#[cfg(not(feature = "sonic"))]
let first = access.next_key_seed(TextSeed)?;
#[cfg(not(feature = "sonic"))]
if first.as_deref() == Some(NUMBER_TOKEN) {
let text: String = access.next_value()?;
if access.next_key::<IgnoredAny>()?.is_some() {
return Err(de::Error::custom("a JSON number token must be the only entry"));
}
if let Ok(value) = text.parse::<u64>() {
return self.serializer.serialize_u64(value).map_err(writer_refused);
}
if let Ok(value) = text.parse::<i64>() {
return self.serializer.serialize_i64(value).map_err(writer_refused);
}
let value = text
.parse::<f64>()
.map_err(|_| <A::Error as de::Error>::custom("number out of range"))?;
if !value.is_finite() {
return Err(de::Error::custom("number out of range"));
}
return self.serializer.serialize_f64(value).map_err(writer_refused);
}
let mut map = self.serializer.serialize_map(access.size_hint()).map_err(writer_refused)?;
#[cfg(not(feature = "sonic"))]
match first {
Some(key) => {
map.serialize_key(key.as_ref()).map_err(writer_refused)?;
access.next_value_seed(TranscodeValue { map: &mut map })?;
}
None => return map.end().map_err(writer_refused),
}
loop {
let key = access.next_key_seed(TranscodeKey { map: &mut map })?;
if key.is_none() {
break;
}
access.next_value_seed(TranscodeValue { map: &mut map })?;
}
map.end().map_err(writer_refused)
}
}
struct TranscodeElement<'s, S> {
sequence: &'s mut S,
}
impl<'de, S> de::DeserializeSeed<'de> for TranscodeElement<'_, S>
where
S: SerializeSeq,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.sequence.serialize_element(&Transcoder::new(deserializer)).map_err(writer_refused)
}
}
struct TranscodeKey<'s, S> {
map: &'s mut S,
}
impl<'de, S> de::DeserializeSeed<'de> for TranscodeKey<'_, S>
where
S: SerializeMap,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.map.serialize_key(&Transcoder::new(deserializer)).map_err(writer_refused)
}
}
struct TranscodeValue<'s, S> {
map: &'s mut S,
}
impl<'de, S> de::DeserializeSeed<'de> for TranscodeValue<'_, S>
where
S: SerializeMap,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.map.serialize_value(&Transcoder::new(deserializer)).map_err(writer_refused)
}
}
fn one_json_value<E: de::Error>(text: &str) -> Result<(), E> {
decode::<IgnoredAny>(text.as_bytes()).map_err(de::Error::custom)?;
Ok(())
}
pub(crate) fn deserialize_raw<'de, D>(deserializer: D) -> Result<Cow<'de, str>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_newtype_struct(SPLICE_TOKEN, RawTextVisitor)
}
#[cfg(not(feature = "sonic"))]
struct TextSeed;
#[cfg(not(feature = "sonic"))]
impl<'de> DeserializeSeed<'de> for TextSeed {
type Value = Cow<'de, str>;
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
deserializer.deserialize_str(self)
}
}
#[cfg(not(feature = "sonic"))]
impl<'de> de::Visitor<'de> for TextSeed {
type Value = Cow<'de, str>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Self::Value, E> {
Ok(Cow::Borrowed(value))
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
Ok(Cow::Owned(value.to_owned()))
}
fn visit_string<E: de::Error>(self, value: String) -> Result<Self::Value, E> {
Ok(Cow::Owned(value))
}
}
struct RawTextVisitor;
impl<'de> de::Visitor<'de> for RawTextVisitor {
type Value = Cow<'de, str>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("any JSON value")
}
fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Self::Value, E> {
one_json_value(value)?;
Ok(Cow::Borrowed(value))
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
one_json_value(value)?;
Ok(Cow::Owned(value.to_owned()))
}
fn visit_string<E: de::Error>(self, value: String) -> Result<Self::Value, E> {
one_json_value(&value)?;
Ok(Cow::Owned(value))
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
let mut out = Vec::new();
deserializer.deserialize_any(Render { out: &mut out, depth: 0 })?;
Ok(Cow::Owned(rendered_text(out)))
}
fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
Ok(Cow::Borrowed(if value { "true" } else { "false" }))
}
fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
render_scalar(&value)
}
fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
render_scalar(&value)
}
fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
render_scalar(&value)
}
fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
render_scalar(&value)
}
fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
render_scalar(&value)
}
fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
Ok(Cow::Borrowed("null"))
}
fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
Ok(Cow::Borrowed("null"))
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.visit_newtype_struct(deserializer)
}
fn visit_seq<A>(self, access: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
let mut out = Vec::new();
de::Visitor::visit_seq(Render { out: &mut out, depth: 0 }, access)?;
Ok(Cow::Owned(rendered_text(out)))
}
#[cfg(feature = "sonic")]
fn visit_map<A>(self, access: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
let mut out = Vec::new();
de::Visitor::visit_map(Render { out: &mut out, depth: 0 }, access)?;
Ok(Cow::Owned(rendered_text(out)))
}
#[cfg(not(feature = "sonic"))]
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
let first = access.next_key_seed(TextSeed)?;
let mut out = Vec::new();
match first {
Some(key) if key == SPLICE_TOKEN => {
let text = access.next_value_seed(TextSeed)?;
one_json_value(&text)?;
if access.next_key::<IgnoredAny>()?.is_some() {
return Err(de::Error::custom("a raw JSON token must be the only entry"));
}
if DecoderMark::is_set() {
return Ok(text);
}
let mut source = backend::Deserializer::from_str(&text);
Render { out: &mut out, depth: 0 }
.deserialize(&mut source)
.map_err(de::Error::custom)?;
source.end().map_err(de::Error::custom)?;
}
Some(key) => Render { out: &mut out, depth: 0 }.map_after_key(&key, access)?,
None => out.extend_from_slice(b"{}"),
}
Ok(Cow::Owned(rendered_text(out)))
}
}
fn render_scalar<'de, T, E>(value: &T) -> Result<Cow<'de, str>, E>
where
T: Serialize + ?Sized,
E: de::Error,
{
let mut out = Vec::new();
encode_into(&mut out, value).map_err(de::Error::custom)?;
Ok(Cow::Owned(rendered_text(out)))
}
fn rendered_text(out: Vec<u8>) -> String {
String::from_utf8(out).expect("invariant: the renderer emits UTF-8")
}
struct Render<'b> {
out: &'b mut Vec<u8>,
depth: usize,
}
impl Render<'_> {
#[cfg(not(feature = "sonic"))]
fn map_after_key<'de, A: de::MapAccess<'de>>(
self,
key: &str,
access: A,
) -> Result<(), A::Error> {
if key == NUMBER_TOKEN {
return self.number_map(access);
}
self.out.push(b'{');
write_json_string(self.out, key);
self.finish_map(access)
}
fn finish_map<'de, A: de::MapAccess<'de>>(self, mut access: A) -> Result<(), A::Error> {
let inner = one_level_in(self.depth)?;
let out = self.out;
out.push(b':');
access.next_value_seed(Render { out: &mut *out, depth: inner })?;
while access.next_key_seed(RenderKey { out: &mut *out, first: false })?.is_some() {
out.push(b':');
access.next_value_seed(Render { out: &mut *out, depth: inner })?;
}
out.push(b'}');
Ok(())
}
fn number_map<'de, A: de::MapAccess<'de>>(self, mut access: A) -> Result<(), A::Error> {
let text: String = access.next_value()?;
if !matches!(text.as_bytes().first(), Some(b'-' | b'0'..=b'9'))
|| !text.as_bytes().last().is_some_and(u8::is_ascii_digit)
{
return Err(de::Error::custom("invalid JSON number token"));
}
one_json_value(&text)?;
if access.next_key::<IgnoredAny>()?.is_some() {
return Err(de::Error::custom("a JSON number token must be the only entry"));
}
self.out.extend_from_slice(text.as_bytes());
Ok(())
}
}
fn one_level_in<E: de::Error>(depth: usize) -> Result<usize, E> {
if depth >= MAX_JSON_DEPTH {
return Err(de::Error::custom(DecodeError::too_deep()));
}
Ok(depth + 1)
}
impl<'de> de::DeserializeSeed<'de> for Render<'_> {
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
}
impl<'de> de::Visitor<'de> for Render<'_> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("any JSON value")
}
fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
self.out.extend_from_slice(if value { b"true" } else { b"false" });
Ok(())
}
fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
encode_into(self.out, &value).map_err(de::Error::custom)
}
fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
encode_into(self.out, &value).map_err(de::Error::custom)
}
fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
encode_into(self.out, &value).map_err(de::Error::custom)
}
fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
encode_into(self.out, &value).map_err(de::Error::custom)
}
fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
encode_into(self.out, &value).map_err(de::Error::custom)
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
write_json_string(self.out, value);
Ok(())
}
fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
self.out.extend_from_slice(b"null");
Ok(())
}
fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
self.out.extend_from_slice(b"null");
Ok(())
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
let inner = one_level_in(self.depth)?;
let out = self.out;
out.push(b'[');
let mut first = true;
loop {
let element = RenderElement { out: &mut *out, depth: inner, first };
if access.next_element_seed(element)?.is_none() {
break;
}
first = false;
}
out.push(b']');
Ok(())
}
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
match access.next_key_seed(RenderKey { out: &mut *self.out, first: true })? {
Some(true) => self.number_map(access),
Some(false) => self.finish_map(access),
None => {
one_level_in::<A::Error>(self.depth)?;
self.out.extend_from_slice(b"{}");
Ok(())
}
}
}
}
struct RenderElement<'b> {
out: &'b mut Vec<u8>,
depth: usize,
first: bool,
}
impl<'de> de::DeserializeSeed<'de> for RenderElement<'_> {
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
if !self.first {
self.out.push(b',');
}
deserializer.deserialize_any(Render { out: self.out, depth: self.depth })
}
}
struct RenderKey<'b> {
out: &'b mut Vec<u8>,
first: bool,
}
impl<'de> de::DeserializeSeed<'de> for RenderKey<'_> {
type Value = bool;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
}
impl<'de> de::Visitor<'de> for RenderKey<'_> {
type Value = bool;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a JSON object key")
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
if self.first && value == NUMBER_TOKEN {
return Ok(true);
}
self.out.push(if self.first { b'{' } else { b',' });
write_json_string(self.out, value);
Ok(false)
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct RawJson {
text: Box<str>,
}
impl RawJson {
pub fn from_value<T>(value: &T) -> Result<Self, EncodeError>
where
T: Serialize + ?Sized,
{
let mut buffer = Vec::new();
encode_into(&mut buffer, value)?;
Ok(Self::from_text(String::from_utf8(buffer).expect("invariant: the codec emits UTF-8")))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.text
}
pub fn decode<'de, T>(&'de self) -> Result<T, DecodeError>
where
T: Deserialize<'de>,
{
decode(self.text.as_bytes())
}
pub(crate) fn from_text(text: String) -> Self {
Self { text: text.into_boxed_str() }
}
}
impl fmt::Debug for RawJson {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut shown = SafeText::new(usize::MAX, Backslash::Keep);
shown.untrusted(&self.text, usize::MAX);
formatter.write_str(&shown.into_string())
}
}
impl fmt::Display for RawJson {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(&self.text)
}
}
impl Serialize for RawJson {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serialize_raw(&self.text, serializer)
}
}
impl<'de> Deserialize<'de> for RawJson {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserialize_raw(deserializer).map(|raw| Self::from_text(raw.into_owned()))
}
}
#[cfg(test)]
#[path = "codec_tests.rs"]
mod tests;