use core::{fmt, marker};
use musli::context::Buffer;
use musli::en::{Encoder, PairEncoder, PairsEncoder, SequenceEncoder, VariantEncoder};
use musli::mode::Mode;
use musli::Context;
use musli_common::writer::Writer;
use crate::error::Error;
pub struct JsonEncoder<M, W> {
writer: W,
_marker: marker::PhantomData<M>,
}
impl<M, W> JsonEncoder<M, W> {
#[inline]
pub(crate) fn new(writer: W) -> Self {
Self {
writer,
_marker: marker::PhantomData,
}
}
}
#[musli::encoder]
impl<M, W> Encoder for JsonEncoder<M, W>
where
M: Mode,
W: Writer,
Error: From<W::Error>,
{
type Error = Error;
type Ok = ();
type Pack<B> = JsonArrayEncoder<M, W> where B: Buffer;
type Some = Self;
type Sequence = JsonArrayEncoder<M, W>;
type Tuple = JsonArrayEncoder<M, W>;
type Map = JsonObjectEncoder<M, W>;
type Struct = JsonObjectEncoder<M, W>;
type Variant = JsonVariantEncoder<M, W>;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "value that can be encoded to JSON")
}
#[inline]
fn encode_unit<C>(mut self, cx: &mut C) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer.write_bytes(cx.adapt(), b"null")
}
#[inline]
fn encode_bool<C>(mut self, cx: &mut C, value: bool) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer
.write_bytes(cx.adapt(), if value { b"true" } else { b"false" })
}
#[inline]
fn encode_char<C>(mut self, cx: &mut C, value: char) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
encode_string(
cx,
self.writer.borrow_mut(),
value.encode_utf8(&mut [0, 0, 0, 0]).as_bytes(),
)
}
#[inline]
fn encode_u8<C>(mut self, cx: &mut C, value: u8) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_u16<C>(mut self, cx: &mut C, value: u16) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_u32<C>(mut self, cx: &mut C, value: u32) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_u64<C>(mut self, cx: &mut C, value: u64) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_u128<C>(mut self, cx: &mut C, value: u128) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_i8<C>(mut self, cx: &mut C, value: i8) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_i16<C>(mut self, cx: &mut C, value: i16) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_i32<C>(mut self, cx: &mut C, value: i32) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_i64<C>(mut self, cx: &mut C, value: i64) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_i128<C>(mut self, cx: &mut C, value: i128) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_usize<C>(mut self, cx: &mut C, value: usize) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_isize<C>(mut self, cx: &mut C, value: isize) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = itoa::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_f32<C>(mut self, cx: &mut C, value: f32) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = ryu::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_f64<C>(mut self, cx: &mut C, value: f64) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buffer = ryu::Buffer::new();
self.writer
.write_bytes(cx.adapt(), buffer.format(value).as_bytes())
}
#[inline]
fn encode_array<C, const N: usize>(
self,
cx: &mut C,
bytes: [u8; N],
) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.encode_bytes(cx, bytes.as_slice())
}
#[inline]
fn encode_bytes<C>(mut self, cx: &mut C, bytes: &[u8]) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut buf = itoa::Buffer::new();
let mut it = bytes.iter();
let last = it.next_back();
self.writer.write_byte(cx.adapt(), b'[')?;
for b in it {
self.writer
.write_bytes(cx.adapt(), buf.format(*b).as_bytes())?;
self.writer.write_byte(cx.adapt(), b',')?;
}
if let Some(b) = last {
self.writer
.write_bytes(cx.adapt(), buf.format(*b).as_bytes())?;
}
self.writer.write_byte(cx.adapt(), b']')?;
Ok(())
}
#[inline]
fn encode_bytes_vectored<C>(self, cx: &mut C, bytes: &[&[u8]]) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
let mut seq = JsonArrayEncoder::<M, _>::new(cx, self.writer)?;
for bb in bytes {
for b in *bb {
seq.push::<M, _, _>(cx, b)?;
}
}
seq.end(cx)
}
#[inline]
fn encode_string<C>(mut self, cx: &mut C, string: &str) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
encode_string(cx, self.writer.borrow_mut(), string.as_bytes())
}
#[inline]
fn encode_some<C>(self, _: &mut C) -> Result<Self::Some, C::Error>
where
C: Context<Input = Self::Error>,
{
Ok(self)
}
#[inline]
fn encode_none<C>(self, cx: &mut C) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.encode_unit(cx)
}
#[inline]
fn encode_pack<C>(self, cx: &mut C) -> Result<Self::Pack<C::Buf>, C::Error>
where
C: Context<Input = Self::Error>,
{
JsonArrayEncoder::new(cx, self.writer)
}
#[inline]
fn encode_sequence<C>(self, cx: &mut C, _: usize) -> Result<Self::Sequence, C::Error>
where
C: Context<Input = Self::Error>,
{
JsonArrayEncoder::new(cx, self.writer)
}
#[inline]
fn encode_tuple<C>(self, cx: &mut C, _: usize) -> Result<Self::Tuple, C::Error>
where
C: Context<Input = Self::Error>,
{
JsonArrayEncoder::new(cx, self.writer)
}
#[inline]
fn encode_map<C>(self, cx: &mut C, _: usize) -> Result<Self::Map, C::Error>
where
C: Context<Input = Self::Error>,
{
JsonObjectEncoder::new(cx, self.writer)
}
#[inline]
fn encode_struct<C>(self, cx: &mut C, _: usize) -> Result<Self::Struct, C::Error>
where
C: Context<Input = Self::Error>,
{
JsonObjectEncoder::new(cx, self.writer)
}
#[inline]
fn encode_variant<C>(self, cx: &mut C) -> Result<Self::Variant, C::Error>
where
C: Context<Input = Self::Error>,
{
JsonVariantEncoder::new(cx, self.writer)
}
}
pub struct JsonObjectEncoder<M, W> {
len: usize,
writer: W,
_marker: marker::PhantomData<M>,
}
impl<M, W> JsonObjectEncoder<M, W>
where
W: Writer,
Error: From<W::Error>,
{
#[inline]
fn new<C>(cx: &mut C, mut writer: W) -> Result<Self, C::Error>
where
C: Context<Input = Error>,
{
writer.write_byte(cx.adapt(), b'{')?;
Ok(Self {
len: 0,
writer,
_marker: marker::PhantomData,
})
}
}
impl<M, W> PairsEncoder for JsonObjectEncoder<M, W>
where
M: Mode,
W: Writer,
Error: From<W::Error>,
{
type Ok = ();
type Error = Error;
type Encoder<'this> = JsonObjectPairEncoder<M, W::Mut<'this>>
where
Self: 'this;
#[inline]
fn next<C>(&mut self, _: &mut C) -> Result<Self::Encoder<'_>, C::Error>
where
C: Context<Input = Self::Error>,
{
let len = self.len;
self.len += 1;
Ok(JsonObjectPairEncoder::new(
len == 0,
self.writer.borrow_mut(),
))
}
#[inline]
fn end<C>(mut self, cx: &mut C) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer.write_byte(cx.adapt(), b'}')?;
Ok(())
}
}
pub struct JsonObjectPairEncoder<M, W> {
empty: bool,
writer: W,
_marker: marker::PhantomData<M>,
}
impl<M, W> JsonObjectPairEncoder<M, W> {
#[inline]
const fn new(empty: bool, writer: W) -> Self {
Self {
empty,
writer,
_marker: marker::PhantomData,
}
}
}
impl<M, W> PairEncoder for JsonObjectPairEncoder<M, W>
where
M: Mode,
W: Writer,
Error: From<W::Error>,
{
type Ok = ();
type Error = Error;
type First<'this> = JsonObjectKeyEncoder<W::Mut<'this>>
where
Self: 'this;
type Second<'this> = JsonEncoder<M, W::Mut<'this>> where Self: 'this;
#[inline]
fn first<C>(&mut self, cx: &mut C) -> Result<Self::First<'_>, C::Error>
where
C: Context<Input = Self::Error>,
{
if !self.empty {
self.writer.write_byte(cx.adapt(), b',')?;
}
Ok(JsonObjectKeyEncoder::new(self.writer.borrow_mut()))
}
#[inline]
fn second<C>(&mut self, cx: &mut C) -> Result<Self::Second<'_>, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer.write_byte(cx.adapt(), b':')?;
Ok(JsonEncoder::new(self.writer.borrow_mut()))
}
#[inline]
fn end<C>(self, _: &mut C) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
Ok(())
}
}
pub struct JsonVariantEncoder<M, W> {
writer: W,
_marker: marker::PhantomData<M>,
}
impl<M, W> JsonVariantEncoder<M, W>
where
W: Writer,
Error: From<W::Error>,
{
#[inline]
fn new<C>(cx: &mut C, mut writer: W) -> Result<Self, C::Error>
where
C: Context<Input = Error>,
{
writer.write_byte(cx.adapt(), b'{')?;
Ok(Self {
writer,
_marker: marker::PhantomData,
})
}
}
impl<M, W> VariantEncoder for JsonVariantEncoder<M, W>
where
M: Mode,
W: Writer,
Error: From<W::Error>,
{
type Ok = ();
type Error = Error;
type Tag<'this> = JsonObjectKeyEncoder<W::Mut<'this>>
where
Self: 'this;
type Variant<'this> = JsonEncoder<M, W::Mut<'this>>
where
Self: 'this;
#[inline]
fn tag<C>(&mut self, _: &mut C) -> Result<Self::Tag<'_>, C::Error>
where
C: Context<Input = Self::Error>,
{
Ok(JsonObjectKeyEncoder::new(self.writer.borrow_mut()))
}
#[inline]
fn variant<C>(&mut self, cx: &mut C) -> Result<Self::Variant<'_>, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer.write_byte(cx.adapt(), b':')?;
Ok(JsonEncoder::new(self.writer.borrow_mut()))
}
#[inline]
fn end<C>(mut self, cx: &mut C) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer.write_byte(cx.adapt(), b'}')
}
}
pub struct JsonObjectKeyEncoder<W> {
writer: W,
}
impl<W> JsonObjectKeyEncoder<W> {
#[inline]
fn new(writer: W) -> Self {
Self { writer }
}
}
macro_rules! format_integer {
($slf:ident, $cx:expr, $value:ident) => {{
$slf.writer.write_byte($cx.adapt(), b'"')?;
let mut buffer = itoa::Buffer::new();
$slf.writer
.write_bytes($cx.adapt(), buffer.format($value).as_bytes())?;
$slf.writer.write_byte($cx.adapt(), b'"')?;
Ok(())
}};
}
#[musli::encoder]
impl<W> Encoder for JsonObjectKeyEncoder<W>
where
W: Writer,
Error: From<W::Error>,
{
type Ok = ();
type Error = Error;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "any type that can be used as an object key")
}
#[inline]
fn encode_u8<C>(mut self, cx: &mut C, value: u8) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_u16<C>(mut self, cx: &mut C, value: u16) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_u32<C>(mut self, cx: &mut C, value: u32) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_u64<C>(mut self, cx: &mut C, value: u64) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_u128<C>(mut self, cx: &mut C, value: u128) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_i8<C>(mut self, cx: &mut C, value: i8) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_i16<C>(mut self, cx: &mut C, value: i16) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_i32<C>(mut self, cx: &mut C, value: i32) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_i64<C>(mut self, cx: &mut C, value: i64) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_i128<C>(mut self, cx: &mut C, value: i128) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_usize<C>(mut self, cx: &mut C, value: usize) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_isize<C>(mut self, cx: &mut C, value: isize) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
format_integer!(self, cx, value)
}
#[inline]
fn encode_string<C>(self, cx: &mut C, string: &str) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
encode_string(cx, self.writer, string.as_bytes())
}
}
pub struct JsonArrayEncoder<M, W> {
first: bool,
writer: W,
_marker: marker::PhantomData<M>,
}
impl<M, W> JsonArrayEncoder<M, W>
where
W: Writer,
Error: From<W::Error>,
{
#[inline]
fn new<C>(cx: &mut C, mut writer: W) -> Result<Self, C::Error>
where
C: Context<Input = Error>,
{
writer.write_byte(cx.adapt(), b'[')?;
Ok(Self {
first: true,
writer,
_marker: marker::PhantomData,
})
}
}
impl<M, W> SequenceEncoder for JsonArrayEncoder<M, W>
where
M: Mode,
W: Writer,
Error: From<W::Error>,
{
type Ok = ();
type Error = Error;
type Encoder<'this> = JsonEncoder<M, W::Mut<'this>>
where
Self: 'this;
#[inline]
fn next<C>(&mut self, cx: &mut C) -> Result<Self::Encoder<'_>, C::Error>
where
C: Context<Input = Self::Error>,
{
if !self.first {
self.writer.write_byte(cx.adapt(), b',')?;
}
self.first = false;
Ok(JsonEncoder::new(self.writer.borrow_mut()))
}
#[inline]
fn end<C>(mut self, cx: &mut C) -> Result<Self::Ok, C::Error>
where
C: Context<Input = Self::Error>,
{
self.writer.write_byte(cx.adapt(), b']')?;
Ok(())
}
}
#[inline]
fn encode_string<C, W>(cx: &mut C, mut writer: W, bytes: &[u8]) -> Result<(), C::Error>
where
C: Context<Input = Error>,
W: Writer,
Error: From<W::Error>,
{
writer.write_byte(cx.adapt(), b'"')?;
let mut start = 0;
for (i, &b) in bytes.iter().enumerate() {
let escape = ESCAPE[b as usize];
if escape == 0 {
continue;
}
if start < i {
writer.write_bytes(cx.adapt(), &bytes[start..i])?;
}
write_escape(cx, &mut writer, escape, b)?;
start = i + 1;
}
if start != bytes.len() {
writer.write_bytes(cx.adapt(), &bytes[start..])?;
}
writer.write_byte(cx.adapt(), b'"')?;
Ok(())
}
const BB: u8 = b'b'; const TT: u8 = b't'; const NN: u8 = b'n'; const FF: u8 = b'f'; const RR: u8 = b'r'; const QU: u8 = b'"'; const BS: u8 = b'\\'; const UU: u8 = b'u'; const __: u8 = 0;
static ESCAPE: [u8; 256] = [
UU, UU, UU, UU, UU, UU, UU, UU, BB, TT, NN, UU, FF, RR, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ];
static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
fn write_escape<C, W>(cx: &mut C, writer: &mut W, escape: u8, byte: u8) -> Result<(), C::Error>
where
C: Context<Input = Error>,
W: Writer,
Error: From<W::Error>,
{
let s = match escape {
BB => b"\\b",
TT => b"\\t",
NN => b"\\n",
FF => b"\\f",
RR => b"\\r",
QU => b"\\\"",
BS => b"\\\\",
UU => {
let bytes = &[
b'\\',
b'u',
b'0',
b'0',
HEX_DIGITS[(byte >> 4) as usize],
HEX_DIGITS[(byte & 0xF) as usize],
];
return writer.write_bytes(cx.adapt(), bytes);
}
_ => unreachable!(),
};
writer.write_bytes(cx.adapt(), s)
}