#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::iter::Cloned;
use core::marker::PhantomData;
use core::slice;
use crate::parser::{JsonKind, ParseConfig, ParseDelegate, Parser};
#[cfg(feature = "alloc")]
use crate::{value::Entry, Object, Value};
use crate::{Error, ErrorKind, JsonNumber, JsonString};
#[derive(Debug, Eq, PartialEq)]
pub struct GenericDocument<'a, Backing> {
nodes: Nodes<'a, Backing>,
}
impl<'a, Backing> GenericDocument<'a, Backing>
where
Backing: NodeCollection<'a>,
{
pub fn from_json_bytes(source: &'a [u8]) -> Result<Self, Error>
where
Backing: Default,
{
let mut nodes = Nodes::default();
Parser::parse_json_bytes(source, &mut nodes).map_err(Error::into_infallable)?;
Ok(Self { nodes })
}
pub fn from_json_bytes_with_config(source: &'a [u8], config: ParseConfig) -> Result<Self, Error>
where
Backing: Default,
{
let mut nodes = Nodes::default();
Parser::parse_json_bytes_with_config(source, config, &mut nodes)
.map_err(Error::into_infallable)?;
Ok(Self { nodes })
}
pub fn from_json(source: &'a str) -> Result<Self, Error>
where
Backing: Default,
{
let mut nodes = Nodes::default();
Parser::parse_json(source, &mut nodes).map_err(Error::into_infallable)?;
Ok(Self { nodes })
}
pub fn from_json_with_config(source: &'a str, config: ParseConfig) -> Result<Self, Error>
where
Backing: Default,
{
let mut nodes = Nodes::default();
Parser::parse_json_with_config(source, config, &mut nodes)
.map_err(Error::into_infallable)?;
Ok(Self { nodes })
}
#[must_use]
pub fn iter(&self) -> DocumentIter<'_, 'a> {
self.into_iter()
}
}
#[cfg(feature = "alloc")]
impl<'a, Backing> From<GenericDocument<'a, Backing>> for Value<'a>
where
Backing: NodeCollection<'a>,
{
fn from(doc: GenericDocument<'a, Backing>) -> Self {
let mut nodes = doc.nodes.collection.into_iter();
let root = nodes.next().expect("empty document is invalid");
hydrate_value_from_node(root, &mut nodes)
}
}
#[cfg(feature = "alloc")]
fn hydrate_value_from_node<'a, I>(node: Node<'a>, remaining_nodes: &mut I) -> Value<'a>
where
I: Iterator<Item = Node<'a>>,
{
match node {
Node::Null => Value::Null,
Node::Boolean(value) => Value::Boolean(value),
Node::String(value) => Value::String(value),
Node::Number(number) => Value::Number(number),
Node::Object { length: len } => {
let mut obj = Object::with_capacity(len);
for _ in 0..len {
let node = remaining_nodes.next().expect("obbject missing value");
let Node::String(key) = node else { unreachable!("object key must be string") };
let node = remaining_nodes.next().expect("object missing value");
obj.push(Entry {
key,
value: hydrate_value_from_node(node, remaining_nodes),
});
}
Value::Object(obj)
}
Node::Array { length: len } => {
let mut values = Vec::with_capacity(len);
for _ in 0..len {
let node = remaining_nodes.next().expect("array missing value");
values.push(hydrate_value_from_node(node, remaining_nodes));
}
Value::Array(values)
}
}
}
impl<'doc, 'a, Backing> IntoIterator for &'doc GenericDocument<'a, Backing>
where
Backing: NodeCollection<'a>,
{
type IntoIter = DocumentIter<'doc, 'a>;
type Item = Node<'a>;
fn into_iter(self) -> Self::IntoIter {
DocumentIter {
nodes: self.nodes.collection.as_ref().iter().cloned(),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Node<'a> {
Null,
Boolean(bool),
String(JsonString<'a>),
Number(JsonNumber<'a>),
Object {
length: usize,
},
Array {
length: usize,
},
}
#[derive(Default, Debug, Eq, PartialEq)]
struct Nodes<'a, Backing> {
collection: Backing,
_phantom: PhantomData<&'a ()>,
}
impl<'a, Backing> Nodes<'a, Backing>
where
Backing: NodeCollection<'a>,
{
fn push_node(&mut self, node: Node<'a>) -> Result<usize, ErrorKind> {
let index = self.collection.as_ref().len();
self.collection.push(node)?;
Ok(index)
}
pub fn push_null(&mut self) -> Result<usize, ErrorKind> {
self.push_node(Node::Null)
}
pub fn push_bool(&mut self, boolean: bool) -> Result<usize, ErrorKind> {
self.push_node(Node::Boolean(boolean))
}
pub fn push_string(&mut self, string: JsonString<'a>) -> Result<usize, ErrorKind> {
self.push_node(Node::String(string))
}
pub fn push_number(&mut self, number: JsonNumber<'a>) -> Result<usize, ErrorKind> {
self.push_node(Node::Number(number))
}
pub fn push_object(&mut self) -> Result<usize, ErrorKind> {
self.push_node(Node::Object { length: 0 })
}
pub fn push_array(&mut self) -> Result<usize, ErrorKind> {
self.push_node(Node::Array { length: 0 })
}
pub fn extend_object(&mut self, index: usize) {
let Node::Object { length: len } = &mut self.collection.as_mut()[index] else { unreachable!("extended wrong type") };
*len += 1;
}
pub fn extend_array(&mut self, index: usize) {
let Node::Array { length: len } = &mut self.collection.as_mut()[index] else { unreachable!("extended wrong type") };
*len += 1;
}
}
impl<'a, 'b, Backing> ParseDelegate<'a> for &'b mut Nodes<'a, Backing>
where
Backing: NodeCollection<'a>,
{
type Array = usize;
type Error = ErrorKind;
type Key = ();
type Object = usize;
type Value = usize;
#[inline]
fn null(&mut self) -> Result<Self::Value, Self::Error> {
self.push_null()
}
#[inline]
fn boolean(&mut self, value: bool) -> Result<Self::Value, Self::Error> {
self.push_bool(value)
}
#[inline]
fn number(&mut self, value: JsonNumber<'a>) -> Result<Self::Value, Self::Error> {
self.push_number(value)
}
#[inline]
fn string(&mut self, value: JsonString<'a>) -> Result<Self::Value, Self::Error> {
self.push_string(value)
}
#[inline]
fn begin_object(&mut self) -> Result<Self::Object, Self::Error> {
self.push_object()
}
#[inline]
fn object_key(
&mut self,
object: &mut Self::Object,
key: JsonString<'a>,
) -> Result<Self::Key, Self::Error> {
self.extend_object(*object);
self.push_string(key)?;
Ok(())
}
#[inline]
fn object_value(
&mut self,
_object: &mut Self::Object,
_key: Self::Key,
_value: Self::Value,
) -> Result<(), Self::Error> {
Ok(())
}
#[inline]
fn object_is_empty(&self, object: &Self::Object) -> bool {
let Node::Object { length: len } = &self.collection.as_ref()[*object] else { unreachable!("invalid object") };
*len == 0
}
#[inline]
fn end_object(&mut self, object: Self::Object) -> Result<Self::Value, Self::Error> {
Ok(object)
}
#[inline]
fn begin_array(&mut self) -> Result<Self::Array, Self::Error> {
self.push_array()
}
#[inline]
fn array_value(
&mut self,
array: &mut Self::Array,
_value: Self::Value,
) -> Result<(), Self::Error> {
self.extend_array(*array);
Ok(())
}
#[inline]
fn array_is_empty(&self, array: &Self::Array) -> bool {
let Node::Array { length: len } = &self.collection.as_ref()[*array] else { unreachable!("invalid array") };
*len == 0
}
#[inline]
fn end_array(&mut self, array: Self::Array) -> Result<Self::Value, Self::Error> {
Ok(array)
}
#[inline]
fn kind_of(&self, value: &Self::Value) -> JsonKind {
match &self.collection.as_ref()[*value] {
Node::Null => JsonKind::Null,
Node::Boolean(_) => JsonKind::Boolean,
Node::String(_) => JsonKind::String,
Node::Number(_) => JsonKind::Number,
Node::Object { .. } => JsonKind::Object,
Node::Array { .. } => JsonKind::Array,
}
}
}
#[derive(Debug, Clone)]
pub struct DocumentIter<'doc, 'a> {
nodes: Cloned<slice::Iter<'doc, Node<'a>>>,
}
impl<'doc, 'a> DocumentIter<'doc, 'a> {
#[cfg(feature = "alloc")]
pub fn next_value(&mut self) -> Option<Value<'a>> {
let node = self.nodes.next()?;
Some(hydrate_value_from_node(node, &mut self.nodes))
}
pub fn skip_next_value(&mut self) {
if let Some(node) = self.nodes.next() {
match node {
Node::Null | Node::Boolean(_) | Node::String(_) | Node::Number(_) => {}
Node::Object { length: len } => {
for _ in 0..len {
self.skip_next_value();
self.skip_next_value();
}
}
Node::Array { length: len } => {
for _ in 0..len {
self.skip_next_value();
}
}
}
}
}
}
impl<'doc, 'a> Iterator for DocumentIter<'doc, 'a> {
type Item = Node<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.nodes.next()
}
}
#[test]
#[cfg(feature = "alloc")]
fn document_iteration() {
let source = r#"{"a":1,"b":true,"c":"hello","d":[null],"e":{}}"#;
let doc = Document::from_json(source).unwrap();
assert_eq!(
doc.iter().collect::<Vec<_>>(),
alloc::vec![
Node::Object { length: 5 },
Node::String(JsonString::from_json("\"a\"").unwrap()),
Node::Number(JsonNumber::from_json("1").unwrap()),
Node::String(JsonString::from_json("\"b\"").unwrap()),
Node::Boolean(true),
Node::String(JsonString::from_json("\"c\"").unwrap()),
Node::String(JsonString::from_json("\"hello\"").unwrap()),
Node::String(JsonString::from_json("\"d\"").unwrap()),
Node::Array { length: 1 },
Node::Null,
Node::String(JsonString::from_json("\"e\"").unwrap()),
Node::Object { length: 0 },
]
);
let value = doc.iter().next_value().unwrap();
assert_eq!(value, Value::from_json(source).unwrap());
let mut iter = doc.iter();
iter.skip_next_value();
assert!(iter.next().is_none());
}
pub trait NodeCollection<'a>:
AsRef<[Node<'a>]> + AsMut<[Node<'a>]> + IntoIterator<Item = Node<'a>>
{
fn push(&mut self, node: Node<'a>) -> Result<(), ErrorKind>;
}
#[cfg(feature = "alloc")]
impl<'a> NodeCollection<'a> for Vec<Node<'a>> {
#[inline]
fn push(&mut self, node: Node<'a>) -> Result<(), ErrorKind> {
self.push(node);
Ok(())
}
}
#[cfg(feature = "heapless")]
impl<'a, const N: usize> NodeCollection<'a> for heapless::Vec<Node<'a>, N> {
#[inline]
fn push(&mut self, node: Node<'a>) -> Result<(), ErrorKind> {
self.push(node).map_err(|_| ErrorKind::PaylodTooLarge)
}
}
#[cfg(feature = "alloc")]
pub type Document<'a> = GenericDocument<'a, Vec<Node<'a>>>;
#[cfg(feature = "heapless")]
pub type HeaplessDocument<'a, const N: usize> = GenericDocument<'a, heapless::Vec<Node<'a>, N>>;