use alloc::borrow::Cow;
use alloc::vec::Vec;
use crate::de::{Decoder, FormatDecoder, Mark, NsonDeserialize, Token};
use crate::error::{Error, Result};
use crate::formats::tree::CollectEncoder;
use crate::formats::Format;
use crate::number::Number;
use crate::ser::NsonSerialize;
use crate::value::Value;
#[derive(Clone, Copy, Debug)]
pub struct Ndjson;
impl Format for Ndjson {
const NAME: &'static str = "ndjson";
const MIME: &'static str = "application/x-ndjson";
const EXTENSIONS: &'static [&'static str] = &["ndjson", "jsonl"];
const BINARY: bool = false;
fn encode<T: NsonSerialize + ?Sized>(self, value: &T) -> Result<Vec<u8>> {
let mut collector = CollectEncoder::new();
T::nextencode(value, &mut collector)?;
let root = collector.take_root()?;
let mut out = Vec::new();
match root {
Value::Array(items) => {
for item in items {
let line = crate::nextencode(&item)?;
out.extend_from_slice(&line);
out.push(b'\n');
}
}
other => {
let line = crate::nextencode(&other)?;
out.extend_from_slice(&line);
out.push(b'\n');
}
}
Ok(out)
}
fn decode<'de, T: NsonDeserialize<'de>>(self, input: &'de [u8]) -> Result<T> {
let mut decoder = NdjsonDecoder::new(input);
let value = T::nextdecode(&mut decoder)?;
decoder.expect_end()?;
Ok(value)
}
}
pub struct NdjsonDecoder<'de> {
input: &'de [u8],
line_start: usize,
current: Option<Decoder<'de>>,
stream_mode: bool,
depth: u32,
started: bool,
}
impl<'de> NdjsonDecoder<'de> {
pub fn new(input: &'de [u8]) -> Self {
NdjsonDecoder {
input,
line_start: 0,
current: None,
stream_mode: false,
depth: 0,
started: false,
}
}
pub fn end(&mut self) -> Result<()> {
self.expect_end()
}
fn expect_end(&mut self) -> Result<()> {
if self.stream_mode {
if self.current.is_some() {
return Err(Error::custom("ndjson: trailing data after array"));
}
Ok(())
} else if self.started {
self.current = None;
let has_more = self.load_next_line()?;
if has_more {
Err(Error::custom("ndjson: trailing data after value"))
} else {
Ok(())
}
} else {
Err(Error::custom("ndjson: no value"))
}
}
fn load_next_line(&mut self) -> Result<bool> {
'lines: loop {
let input = self.input;
let line_begin = self.line_start;
let mut i = line_begin;
let mut saw_content = false;
while i < input.len() {
if input[i] == b'\n' {
let mut line = &input[line_begin..i];
if line.last() == Some(&b'\r') {
line = &line[..line.len() - 1];
}
self.line_start = i + 1;
if !saw_content {
continue 'lines; }
self.current = Some(Decoder::new(line));
return Ok(true);
}
match input[i] {
b' ' | b'\t' | b'\r' => {}
_ => saw_content = true,
}
i += 1;
}
if saw_content {
let line = &input[line_begin..];
self.line_start = input.len();
self.current = Some(Decoder::new(line));
return Ok(true);
}
self.line_start = input.len();
self.current = None;
return Ok(false);
}
}
fn ensure_line(&mut self) -> Result<()> {
if !self.started {
self.started = true;
if self.current.is_none() && !self.load_next_line()? {
return Err(Error::custom("ndjson: empty input"));
}
}
Ok(())
}
fn with_current<T>(&mut self, f: impl FnOnce(&mut Decoder<'de>) -> Result<T>) -> Result<T> {
self.ensure_line()?;
let decoder = self
.current
.as_mut()
.ok_or_else(|| Error::custom("ndjson: no line loaded"))?;
f(decoder)
}
fn at_stream_root(&self) -> bool {
self.stream_mode && self.depth == 0
}
}
impl<'de> FormatDecoder<'de> for NdjsonDecoder<'de> {
type Error = crate::error::Error;
fn begin_array(&mut self) -> Result<(), Self::Error> {
if !self.started {
self.stream_mode = true;
self.started = true;
self.current = None;
self.depth = 0;
return Ok(());
}
self.depth += 1;
self.with_current(|d| d.begin_array())
}
fn end_array(&mut self) -> Result<(), Self::Error> {
if self.at_stream_root() {
self.current = None;
return Ok(());
}
self.depth = self.depth.saturating_sub(1);
self.with_current(|d| d.end_array())
}
fn array_has_more(&mut self) -> Result<bool, Self::Error> {
if self.at_stream_root() {
if self.current.is_none() {
self.load_next_line()?;
}
return Ok(self.current.is_some());
}
self.with_current(|d| d.array_has_more())
}
fn array_entry_sep(&mut self) -> Result<bool, Self::Error> {
if self.at_stream_root() {
self.current = None;
return self.load_next_line();
}
self.with_current(|d| d.array_entry_sep())
}
fn begin_object(&mut self) -> Result<(), Self::Error> {
self.depth += 1;
self.with_current(|d| d.begin_object())
}
fn end_object(&mut self) -> Result<(), Self::Error> {
self.depth = self.depth.saturating_sub(1);
self.with_current(|d| d.end_object())
}
fn object_key(&mut self) -> Result<Option<Cow<'de, str>>, Self::Error> {
self.with_current(|d| d.object_key())
}
fn object_entry_sep(&mut self) -> Result<bool, Self::Error> {
self.with_current(|d| d.object_entry_sep())
}
fn unit(&mut self) -> Result<(), Self::Error> {
self.with_current(|d| d.unit())
}
fn bool(&mut self) -> Result<bool, Self::Error> {
self.with_current(|d| d.bool())
}
fn number(&mut self) -> Result<Number, Self::Error> {
self.with_current(|d| d.number())
}
fn string(&mut self) -> Result<Cow<'de, str>, Self::Error> {
self.with_current(|d| d.string())
}
fn char(&mut self) -> Result<char, Self::Error> {
self.with_current(|d| d.char())
}
fn skip_value(&mut self) -> Result<(), Self::Error> {
self.with_current(|d| d.skip_value())
}
fn peek_token(&mut self) -> Result<Token<'de>, Self::Error> {
self.with_current(|d| d.peek_token())
}
fn next_token(&mut self) -> Result<Token<'de>, Self::Error> {
self.with_current(|d| d.next_token())
}
fn save(&self) -> Mark {
Mark::new(self.line_start, 0)
}
fn restore(&mut self, mark: Mark) {
self.line_start = mark.pos;
self.current = None;
self.started = true;
let _ = self.load_next_line();
}
fn is_human_readable(&self) -> bool {
true
}
}