use std::{
collections::VecDeque,
io::{self, sink, Error, ErrorKind, Write},
str::from_utf8_unchecked,
};
use serde_json::ser::{CompactFormatter, Formatter};
#[derive(Clone, Debug)]
pub(crate) struct ObjectEntry {
key: Vec<u8>,
key_bytes: Vec<u8>,
value: Vec<u8>,
is_key_done: bool,
}
impl ObjectEntry {
pub(crate) fn new() -> Self {
Self {
key: Vec::new(),
key_bytes: Vec::new(),
value: Vec::new(),
is_key_done: false,
}
}
#[inline]
pub(crate) fn end_key(&mut self) {
self.is_key_done = true;
}
pub(crate) fn is_in_key(&mut self) -> bool {
!self.is_key_done
}
#[inline]
pub(crate) fn cmpable<'a>(&'a self) -> impl Iterator<Item = impl Ord + 'a> {
let key_orig = unsafe { from_utf8_unchecked(self.key_bytes.as_slice()) };
key_orig.encode_utf16()
}
#[inline]
pub(crate) fn scope<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
if self.is_in_key() {
Ok(&mut self.key)
} else {
Ok(&mut self.value)
}
}
#[inline]
pub(crate) fn scope_with_key<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
let writer = if self.is_in_key() {
EitherWriter::Left(BothWriter::new(&mut self.key, &mut self.key_bytes))
} else {
EitherWriter::Right(&mut self.value)
};
Ok(writer)
}
#[inline]
pub(crate) fn key_bytes<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
let writer = if self.is_in_key() {
EitherWriter::Left(&mut self.key_bytes)
} else {
EitherWriter::Right(sink())
};
Ok(writer)
}
#[inline]
pub(crate) fn to_writer<W>(&self, first: bool, writer: &mut W) -> io::Result<()>
where
W: Write + ?Sized,
{
CompactFormatter.begin_object_key(writer, first)?;
writer.write_all(self.key.as_slice())?;
CompactFormatter.end_object_key(writer)?;
CompactFormatter.begin_object_value(writer)?;
writer.write_all(self.value.as_slice())?;
CompactFormatter.end_object_value(writer)?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub(crate) struct Object {
entries: Vec<ObjectEntry>,
}
impl Object {
pub(crate) fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub(crate) fn current_entry(&mut self) -> io::Result<&mut ObjectEntry> {
self.entries.last_mut().ok_or_else(|| {
Error::new(
ErrorKind::InvalidData,
"Object entry requested when entry is not active.",
)
})
}
#[inline]
pub(crate) fn start_key(&mut self) {
self.entries.push(ObjectEntry::new())
}
#[inline]
pub(crate) fn end_key(&mut self) -> io::Result<()> {
Ok(self.current_entry()?.end_key())
}
#[inline]
pub(crate) fn is_in_key(&mut self) -> io::Result<bool> {
Ok(self.current_entry()?.is_in_key())
}
#[inline]
pub(crate) fn scope<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
Ok(self.current_entry()?.scope()?)
}
#[inline]
pub(crate) fn scope_with_key<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
Ok(self.current_entry()?.scope_with_key()?)
}
#[inline]
pub(crate) fn key_bytes<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
Ok(self.current_entry()?.key_bytes()?)
}
#[inline]
pub(crate) fn to_writer<W>(&mut self, writer: &mut W) -> io::Result<()>
where
W: Write + ?Sized,
{
CompactFormatter.begin_object(writer)?;
let mut entries = self.entries.clone();
entries.sort_by(|a, b| a.cmpable().cmp(b.cmpable()));
let mut first = true;
for entry in entries {
entry.to_writer(first, writer)?;
first = false;
}
CompactFormatter.end_object(writer)?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub(crate) struct ObjectStack {
objects: VecDeque<Object>,
}
impl ObjectStack {
pub(crate) fn new() -> Self {
Self {
objects: VecDeque::new(),
}
}
pub(crate) fn current_object(&mut self) -> io::Result<&mut Object> {
self.objects.front_mut().ok_or_else(|| {
Error::new(
ErrorKind::InvalidData,
"Object requested when object is not active.",
)
})
}
pub(crate) fn has_current_object(&mut self) -> bool {
!self.objects.is_empty()
}
#[inline]
pub(crate) fn start_object(&mut self) {
self.objects.push_front(Object::new())
}
#[inline]
pub(crate) fn end_object<W>(&mut self, writer: &mut W) -> io::Result<()>
where
W: Write + ?Sized,
{
let mut object = self.objects.pop_front().ok_or_else(|| {
Error::new(
ErrorKind::InvalidData,
"Object requested when object is not active.",
)
})?;
if self.has_current_object() {
let mut writer = self.current_object()?.scope()?;
object.to_writer(&mut writer)?;
} else {
object.to_writer(writer)?;
}
Ok(())
}
#[inline]
pub(crate) fn start_key(&mut self) -> io::Result<()> {
Ok(self.current_object()?.start_key())
}
#[inline]
pub(crate) fn end_key(&mut self) -> io::Result<()> {
Ok(self.current_object()?.end_key()?)
}
#[inline]
pub(crate) fn is_in_key(&mut self) -> io::Result<bool> {
if self.has_current_object() {
Ok(self.current_object()?.is_in_key()?)
} else {
Ok(false)
}
}
pub(crate) fn scope<'a, W>(&'a mut self, writer: &'a mut W) -> io::Result<impl Write + 'a>
where
W: Write + ?Sized,
{
let writer: EitherWriter<_, _> = if self.has_current_object() {
let object_writer = self.current_object()?.scope()?;
EitherWriter::Left(object_writer)
} else {
EitherWriter::Right(writer)
};
Ok(writer)
}
pub(crate) fn scope_with_key<'a, W>(
&'a mut self,
writer: &'a mut W,
) -> io::Result<impl Write + 'a>
where
W: Write + ?Sized,
{
let writer: EitherWriter<_, _> = if self.has_current_object() {
let object_writer = self.current_object()?.scope_with_key()?;
EitherWriter::Left(object_writer)
} else {
EitherWriter::Right(writer)
};
Ok(writer)
}
pub(crate) fn key_bytes<'a>(&'a mut self) -> io::Result<impl Write + 'a> {
let writer: EitherWriter<_, _> = if self.has_current_object() {
let key_bytes_writer = self.current_object()?.key_bytes()?;
EitherWriter::Left(key_bytes_writer)
} else {
EitherWriter::Right(sink())
};
Ok(writer)
}
}
enum EitherWriter<LeftWriter, RightWriter> {
Left(LeftWriter),
Right(RightWriter),
}
impl<LeftWriter, RightWriter> Write for EitherWriter<LeftWriter, RightWriter>
where
LeftWriter: Write,
RightWriter: Write,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
EitherWriter::Left(writer) => writer.write(buf),
EitherWriter::Right(writer) => writer.write(buf),
}
}
fn flush(&mut self) -> io::Result<()> {
match self {
EitherWriter::Left(writer) => writer.flush(),
EitherWriter::Right(writer) => writer.flush(),
}
}
}
struct BothWriter<LeftWriter, RightWriter> {
left: LeftWriter,
right: RightWriter,
}
impl<LeftWriter, RightWriter> BothWriter<LeftWriter, RightWriter> {
fn new(left: LeftWriter, right: RightWriter) -> Self {
Self { left, right }
}
}
impl<LeftWriter, RightWriter> Write for BothWriter<LeftWriter, RightWriter>
where
LeftWriter: Write,
RightWriter: Write,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.left.write_all(buf)?;
self.right.write_all(buf)?;
self.flush()?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
self.left.flush()?;
self.right.flush()?;
Ok(())
}
}