From 457c7e49d08d51c66656334fd6514d72b267aa2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Haudebourg?= Date: Wed, 24 Jan 2024 15:54:31 +0100 Subject: [PATCH] Add `CodeMap` type. Remove embedded metadata. The code-mapping info is now part of the returned `CodeMap`. --- src/code_map.rs | 156 +++++++++++++ src/lib.rs | 477 +++++++++++----------------------------- src/macros.rs | 151 ++----------- src/object.rs | 427 +++++++++++------------------------ src/object/index_map.rs | 69 ++---- src/parse.rs | 367 ++++++++++++------------------- src/parse/array.rs | 58 ++--- src/parse/boolean.rs | 54 ++--- src/parse/null.rs | 31 +-- src/parse/number.rs | 38 ++-- src/parse/object.rs | 94 +++----- src/parse/string.rs | 169 +++++--------- src/parse/value.rs | 202 ++++++++--------- src/print.rs | 14 +- src/unordered.rs | 12 +- tests/macro.rs | 142 +++++------- tests/parse.rs | 2 +- tests/print.rs | 31 ++- 18 files changed, 956 insertions(+), 1538 deletions(-) create mode 100644 src/code_map.rs diff --git a/src/code_map.rs b/src/code_map.rs new file mode 100644 index 0000000..42f9416 --- /dev/null +++ b/src/code_map.rs @@ -0,0 +1,156 @@ +use std::{borrow::Borrow, ops::Deref}; + +use locspan::Span; + +/// Code-map. +#[derive(Debug, Default, Clone)] +pub struct CodeMap(Vec); + +impl CodeMap { + pub fn as_slice(&self) -> &[Entry] { + &self.0 + } + + pub(crate) fn reserve(&mut self, position: usize) -> usize { + let i = self.0.len(); + self.0.push(Entry { + span: Span::new(position, position), + volume: 0, + }); + i + } + + pub(crate) fn get_mut(&mut self, i: usize) -> Option<&mut Entry> { + self.0.get_mut(i) + } + + pub fn iter(&self) -> Iter { + self.0.iter().enumerate() + } +} + +impl Deref for CodeMap { + type Target = [Entry]; + + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl AsRef<[Entry]> for CodeMap { + fn as_ref(&self) -> &[Entry] { + self.as_slice() + } +} + +impl Borrow<[Entry]> for CodeMap { + fn borrow(&self) -> &[Entry] { + self.as_slice() + } +} + +pub type Iter<'a> = std::iter::Enumerate>; + +pub type IntoIter = std::iter::Enumerate>; + +impl<'a> IntoIterator for &'a CodeMap { + type IntoIter = Iter<'a>; + type Item = (usize, &'a Entry); + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl IntoIterator for CodeMap { + type IntoIter = IntoIter; + type Item = (usize, Entry); + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter().enumerate() + } +} + +/// Code-map entry. +/// +/// Provides code-mapping metadata about a fragment of JSON value. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Entry { + /// Byte span of the fragment in the original source code. + pub span: Span, + + /// Number of sub-fragment (including the fragment itself). + pub volume: usize, +} + +impl Entry { + pub fn new(span: Span, volume: usize) -> Self { + Self { span, volume } + } +} + +#[cfg(test)] +mod tests { + use super::Entry; + use crate::{Parse, Value}; + use locspan::Span; + + #[test] + fn code_map_t1() { + let (value, code_map) = Value::parse_str(r#"{ "a": 0, "b": [1, 2] }"#).unwrap(); + let expected = [ + Entry::new(Span::new(0, 23), 9), // { "a": 0, "b": [1, 2] } + Entry::new(Span::new(2, 8), 3), // "a": 0 + Entry::new(Span::new(2, 5), 1), // "a" + Entry::new(Span::new(7, 8), 1), // 0 + Entry::new(Span::new(10, 21), 5), // "b": [1, 2] + Entry::new(Span::new(10, 13), 1), // "b" + Entry::new(Span::new(15, 21), 3), // [1, 2] + Entry::new(Span::new(16, 17), 1), // 1 + Entry::new(Span::new(19, 20), 1), // 2 + ]; + + assert_eq!(code_map.len(), expected.len()); + assert_eq!(value.traverse().count(), expected.len()); + for (i, entry) in code_map { + assert_eq!(entry, expected[i]) + } + } + + #[test] + fn code_map_t2() { + let (value, code_map) = + Value::parse_str(r#"{ "a": 0, "b": { "c": 1, "d": [2, 3] }, "e": [4, [5, 6]] }"#) + .unwrap(); + let expected = [ + Entry::new(Span::new(0, 58), 22), // { "a": 0, "b": { "c": 1, "d": [2, 3] }, "e": [4, [5, 6]] } + Entry::new(Span::new(2, 8), 3), // "a": 0 + Entry::new(Span::new(2, 5), 1), // "a" + Entry::new(Span::new(7, 8), 1), // 0 + Entry::new(Span::new(10, 38), 11), // "b": { "c": 1, "d": [2, 3] } + Entry::new(Span::new(10, 13), 1), // "b" + Entry::new(Span::new(15, 38), 9), // { "c": 1, "d": [2, 3] } + Entry::new(Span::new(17, 23), 3), // "c": 1 + Entry::new(Span::new(17, 20), 1), // "c" + Entry::new(Span::new(22, 23), 1), // 1 + Entry::new(Span::new(25, 36), 5), // "d": [2, 3] + Entry::new(Span::new(25, 28), 1), // "d" + Entry::new(Span::new(30, 36), 3), // [2, 3] + Entry::new(Span::new(31, 32), 1), // 2 + Entry::new(Span::new(34, 35), 1), // 3 + Entry::new(Span::new(40, 56), 7), // "e": [4, [5, 6]] + Entry::new(Span::new(40, 43), 1), // "e" + Entry::new(Span::new(45, 56), 5), // [4, [5, 6]] + Entry::new(Span::new(46, 47), 1), // 4 + Entry::new(Span::new(49, 55), 3), // [5, 6] + Entry::new(Span::new(50, 51), 1), // 5 + Entry::new(Span::new(53, 54), 1), // 6 + ]; + + assert_eq!(code_map.len(), expected.len()); + assert_eq!(value.traverse().count(), expected.len()); + for (i, entry) in code_map { + assert_eq!(entry, expected[i]) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index ae8c762..bdc7ed8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,8 @@ //! This library provides a strict JSON parser as defined by //! [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) and //! [ECMA-404](https://www.ecma-international.org/publications-and-standards/standards/ecma-404/). -//! It is built on the [`locspan`](https://crates.io/crates/locspan) library -//! so as to keep track of the position of each JSON value in the parsed -//! document. +//! Parsing values generates a [`CodeMap`] that keeps track of the position of +//! each JSON value fragment in the parsed document. //! //! # Features //! @@ -33,18 +32,18 @@ //! //! let filename = "tests/inputs/y_structure_500_nested_arrays.json"; //! let input = fs::read_to_string(filename).unwrap(); -//! let mut value = Value::parse_str(&input, |span| span).expect("parse error"); +//! let mut value = Value::parse_str(&input).expect("parse error").0; //! println!("value: {}", value.pretty_print()); //! ``` pub use json_number::Number; -use locspan::Meta; -use locspan_derive::*; use smallvec::SmallVec; use std::fmt; +pub mod code_map; pub mod object; pub mod parse; mod unordered; +pub use code_map::CodeMap; pub use parse::Parse; pub mod print; pub use print::Print; @@ -57,15 +56,10 @@ mod serde; #[cfg(feature = "serde")] pub use self::serde::*; +#[cfg(feature = "serde_json")] pub use convert::*; pub use unordered::*; -/// Value wrapped inside a [`locspan::Meta`] container. -/// -/// This type alias is useful if the same metadata is used for the top level -/// value and the sub value to avoid repetition of the `M` type. -pub type MetaValue = Meta, M>; - /// String stack capacity. /// /// If a string is longer than this value, @@ -76,15 +70,7 @@ pub const SMALL_STRING_CAPACITY: usize = 16; pub type String = smallstr::SmallString<[u8; SMALL_STRING_CAPACITY]>; /// Array. -pub type Array = Vec, M>>; - -impl UnorderedPartialEq for Array { - fn unordered_eq(&self, other: &Self) -> bool { - self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.unordered_eq(b)) - } -} - -impl UnorderedEq for Array {} +pub type Array = Vec; pub use object::Object; @@ -121,13 +107,7 @@ impl fmt::Display for Kind { } } -/// Value. -/// -/// The type parameter `M` is the type of metadata attached to each syntax node -/// (values, sub values and object keys). -/// The metadata is derived from the [`locspan::Span`] of the node in the source -/// document using the metadata builder function passed to the parsing function -/// (see the [`Parse`] trait for more details). +/// JSON Value. /// /// # Parsing /// @@ -137,36 +117,36 @@ impl fmt::Display for Kind { /// ## Example /// /// ``` -/// use json_syntax::{Value, Parse}; -/// use locspan::{Meta, Span}; -/// -/// let value: Meta, Span> = Value::parse_str("{ \"key\": \"value\" }", |span| span).unwrap(); +/// use json_syntax::{Value, Parse, CodeMap}; +/// let (value, code_map) = Value::parse_str("{ \"key\": \"value\" }").unwrap(); /// ``` /// -/// You don't need to specify the return type, here only shown to make it clear. -/// Furthermore the `MetaValue` type alias can be used instead of -/// `Meta, Span>` to avoid repetition of the metadata type. +/// The `code_map` value of type [`CodeMap`] contains code-mapping information +/// about all the fragments of the JSON value (their location in the source +/// text). /// /// # Comparison /// /// This type implements the usual comparison traits `PartialEq`, `Eq`, -/// `PartialOrd` and `Ord`. However these implementations will also compare the -/// metadata. -/// If you want to do comparisons while ignoring ths metadata, you can use -/// the [`locspan::Stripped`] type -/// (combined with the [`locspan::BorrowStripped`] trait). +/// `PartialOrd` and `Ord`. However by default JSON object entries ordering +/// matters, meaning that `{ "a": 0, "b": 1 }` is **not** equal to +/// `{ "b": 1, "a": 0 }`. +/// If you want to do comparisons while ignoring entries ordering, you can use +/// the [`Unordered`] type (combined with the [`UnorderedPartialEq`] trait). +/// Any `T` reference can be turned into an [`Unordered`] reference +/// at will using the [`BorrowUnordered::as_unordered`] method. /// /// ## Example /// /// ``` -/// use json_syntax::{Value, Parse}; -/// use locspan::BorrowStripped; +/// use json_syntax::{json, Unordered, BorrowUnordered}; /// -/// let a = Value::parse_str("null", |_| 0).unwrap(); -/// let b = Value::parse_str("null", |_| 1).unwrap(); +/// let a = json!({ "a": 0, "b": 1 }); +/// let b = json!({ "b": 1, "a": 0 }); /// -/// assert_ne!(a, b); // not equals because the metadata is different. -/// assert_eq!(a.stripped(), b.stripped()); // equals because the metadata is ignored. +/// assert_ne!(a, b); // not equals entries are in a different order. +/// assert_eq!(a.as_unordered(), b.as_unordered()); // equals modulo entry order. +/// assert_eq!(Unordered(a), Unordered(b)); // equals modulo entry order. /// ``` /// /// # Printing @@ -178,7 +158,7 @@ impl fmt::Display for Kind { /// ``` /// use json_syntax::{Value, Parse, Print}; /// -/// let value = Value::parse_str("[ 0, 1, { \"key\": \"value\" }, null ]", |span| span).unwrap(); +/// let value = Value::parse_str("[ 0, 1, { \"key\": \"value\" }, null ]").unwrap().0; /// /// println!("{}", value.pretty_print()); // multi line, indent with 2 spaces /// println!("{}", value.inline_print()); // single line, spaces @@ -188,42 +168,51 @@ impl fmt::Display for Kind { /// options.indent = json_syntax::print::Indent::Tabs(1); /// println!("{}", value.print_with(options)); // multi line, indent with tabs /// ``` -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - StrippedPartialEq, - StrippedEq, - StrippedPartialOrd, - StrippedOrd, - StrippedHash, -)] -#[locspan(ignore(M))] -pub enum Value { +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum Value { /// `null`. Null, /// Boolean `true` or `false`. - Boolean(#[locspan(stripped)] bool), + Boolean(bool), /// Number. - Number(#[locspan(stripped)] NumberBuf), + Number(NumberBuf), /// String. - String(#[locspan(stripped)] String), + String(String), /// Array. - Array(Array), + Array(Array), /// Object. - Object(Object), + Object(Object), } -impl Value { +pub fn get_array_fragment(array: &[Value], mut index: usize) -> Result { + for v in array { + match v.get_fragment(index) { + Ok(value) => return Ok(value), + Err(i) => index = i, + } + } + + Err(index) +} + +impl Value { + pub fn get_fragment(&self, index: usize) -> Result { + if index == 0 { + Ok(FragmentRef::Value(self)) + } else { + match self { + Self::Array(a) => get_array_fragment(a, index - 1), + Self::Object(o) => o.get_fragment(index - 1), + _ => Err(index - 1), + } + } + } + #[inline] pub fn kind(&self) -> Kind { match self { @@ -336,7 +325,7 @@ impl Value { } #[inline] - pub fn as_array(&self) -> Option<&[Meta]> { + pub fn as_array(&self) -> Option<&[Self]> { match self { Self::Array(a) => Some(a), _ => None, @@ -344,7 +333,7 @@ impl Value { } #[inline] - pub fn as_array_mut(&mut self) -> Option<&mut Array> { + pub fn as_array_mut(&mut self) -> Option<&mut Array> { match self { Self::Array(a) => Some(a), _ => None, @@ -356,15 +345,15 @@ impl Value { /// Returns the input value as is if it is already an array, /// or puts it in a slice with a single element if it is not. #[inline] - pub fn force_as_array(value: &Meta) -> Meta<&[Meta], &M> { - match value { - Meta(Self::Array(a), meta) => Meta(a, meta), - other @ Meta(_, meta) => Meta(core::slice::from_ref(other), meta), + pub fn force_as_array(&self) -> &[Self] { + match self { + Self::Array(a) => a, + other => core::slice::from_ref(other), } } #[inline] - pub fn as_object(&self) -> Option<&Object> { + pub fn as_object(&self) -> Option<&Object> { match self { Self::Object(o) => Some(o), _ => None, @@ -372,7 +361,7 @@ impl Value { } #[inline] - pub fn as_object_mut(&mut self) -> Option<&mut Object> { + pub fn as_object_mut(&mut self) -> Option<&mut Object> { match self { Self::Object(o) => Some(o), _ => None, @@ -404,7 +393,7 @@ impl Value { } #[inline] - pub fn into_array(self) -> Option> { + pub fn into_array(self) -> Option { match self { Self::Array(a) => Some(a), _ => None, @@ -412,22 +401,22 @@ impl Value { } #[inline] - pub fn into_object(self) -> Option> { + pub fn into_object(self) -> Option { match self { Self::Object(o) => Some(o), _ => None, } } - pub fn traverse(&self) -> TraverseStripped { + pub fn traverse(&self) -> Traverse { let mut stack = SmallVec::new(); - stack.push(StrippedFragmentRef::Value(self)); - TraverseStripped { stack } + stack.push(FragmentRef::Value(self)); + Traverse { offset: 0, stack } } /// Recursively count the number of values for which `f` returns `true`. - pub fn count(&self, mut f: impl FnMut(StrippedFragmentRef) -> bool) -> usize { - self.traverse().filter(|i| f(*i)).count() + pub fn count(&self, mut f: impl FnMut(usize, FragmentRef) -> bool) -> usize { + self.traverse().filter(|(i, q)| f(*i, *q)).count() } /// Returns the volume of the value. @@ -435,68 +424,9 @@ impl Value { /// The volume is the sum of all values and recursively nested values /// included in `self`, including `self` (the volume is at least `1`). /// - /// This is equivalent to `value.traverse().filter(StrippedFragmentRef::is_value).count()`. + /// This is equivalent to `value.traverse().filter(|(_, f)| f.is_value()).count()`. pub fn volume(&self) -> usize { - self.traverse() - .filter(StrippedFragmentRef::is_value) - .count() - } - - /// Recursively maps the metadata inside the value. - fn map_metadata_mut_ref(self, f: &mut F) -> Value - where - F: FnMut(M) -> N, - { - match self { - Self::Null => Value::Null, - Self::Boolean(b) => Value::Boolean(b), - Self::Number(n) => Value::Number(n), - Self::String(s) => Value::String(s), - Self::Array(a) => Value::Array( - a.into_iter() - .map(|Meta(item, meta)| Meta(item.map_metadata_mut_ref::(f), f(meta))) - .collect(), - ), - Self::Object(o) => Value::Object(o.map_metadata_mut_ref::(f)), - } - } - - /// Recursively maps the metadata inside the value. - pub fn map_metadata(self, mut f: F) -> Value - where - F: FnMut(M) -> N, - { - self.map_metadata_mut_ref(&mut f) - } - - /// Tries to recursively maps the metadata inside the value. - fn try_map_metadata_mut_ref(self, f: &mut F) -> Result, E> - where - F: FnMut(M) -> Result, - { - match self { - Self::Null => Ok(Value::Null), - Self::Boolean(b) => Ok(Value::Boolean(b)), - Self::Number(n) => Ok(Value::Number(n)), - Self::String(s) => Ok(Value::String(s)), - Self::Array(a) => { - let mut items = Vec::with_capacity(a.len()); - for item in a { - use locspan::TryMapMetadataRecursively; - items.push(item.try_map_metadata_recursively_mut_ref::(&mut *f)?) - } - Ok(Value::Array(items)) - } - Self::Object(o) => Ok(Value::Object(o.try_map_metadata_mut_ref::(f)?)), - } - } - - /// Tries to recursively maps the metadata inside the value. - pub fn try_map_metadata(self, mut f: F) -> Result, E> - where - F: FnMut(M) -> Result, - { - self.try_map_metadata_mut_ref::(&mut f) + self.traverse().filter(|(_, f)| f.is_value()).count() } /// Move and return the value, leaves `null` in its place. @@ -534,7 +464,7 @@ impl Value { } } -impl UnorderedPartialEq for Value { +impl UnorderedPartialEq for Value { fn unordered_eq(&self, other: &Self) -> bool { match (self, other) { (Self::Null, Self::Null) => true, @@ -548,104 +478,64 @@ impl UnorderedPartialEq for Value { } } -impl UnorderedEq for Value {} +impl UnorderedEq for Value {} -impl fmt::Display for Value { +impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.compact_print().fmt(f) } } -impl From> for ::std::string::String { - fn from(value: Value) -> Self { +impl From for ::std::string::String { + fn from(value: Value) -> Self { value.to_string() } } -pub trait Traversal<'a> { - type Fragment; - type Traverse: Iterator; - - fn traverse(&'a self) -> Self::Traverse; -} - -impl<'a, M: 'a> Traversal<'a> for Meta, M> { - type Fragment = FragmentRef<'a, M>; - type Traverse = Traverse<'a, M>; - - fn traverse(&'a self) -> Self::Traverse { - let mut stack = SmallVec::new(); - stack.push(FragmentRef::Value(self)); - Traverse { stack } - } -} - -impl locspan::MapMetadataRecursively for Value { - type Output = Value; - - fn map_metadata_recursively_mut_ref(self, f: &mut F) -> Value - where - F: FnMut(M) -> N, - { - self.map_metadata_mut_ref::(f) - } -} - -impl locspan::TryMapMetadataRecursively for Value { - type Output = Value; - - fn try_map_metadata_recursively_mut_ref(self, f: &mut F) -> Result, E> - where - F: FnMut(M) -> Result, - { - self.try_map_metadata_mut_ref::(f) - } -} - -impl From for Value { +impl From for Value { fn from(b: bool) -> Self { Self::Boolean(b) } } -impl From for Value { +impl From for Value { fn from(n: NumberBuf) -> Self { Self::Number(n) } } -impl<'n, M> From<&'n Number> for Value { +impl<'n> From<&'n Number> for Value { fn from(n: &'n Number) -> Self { Self::Number(unsafe { NumberBuf::new_unchecked(n.as_bytes().into()) }) } } -impl From for Value { +impl From for Value { fn from(s: String) -> Self { Self::String(s) } } -impl From<::std::string::String> for Value { +impl From<::std::string::String> for Value { fn from(s: ::std::string::String) -> Self { Self::String(s.into()) } } -impl<'s, M> From<&'s str> for Value { +impl<'s> From<&'s str> for Value { fn from(s: &'s str) -> Self { Self::String(s.into()) } } -impl From> for Value { - fn from(a: Array) -> Self { +impl From for Value { + fn from(a: Array) -> Self { Self::Array(a) } } -impl From> for Value { - fn from(o: Object) -> Self { +impl From for Value { + fn from(o: Object) -> Self { Self::Object(o) } } @@ -653,7 +543,7 @@ impl From> for Value { macro_rules! from_integer { ($($ty:ident),*) => { $( - impl From<$ty> for Value { + impl From<$ty> for Value { fn from(n: $ty) -> Self { Value::Number(n.into()) } @@ -676,7 +566,7 @@ from_integer! { macro_rules! try_from_float { ($($ty:ident),*) => { $( - impl TryFrom<$ty> for Value { + impl TryFrom<$ty> for Value { type Error = json_number::TryFromFloatError; fn try_from(n: $ty) -> Result { @@ -692,13 +582,13 @@ try_from_float! { f64 } -pub enum StrippedFragmentRef<'a, M> { - Value(&'a Value), - Entry(&'a object::Entry), +pub enum FragmentRef<'a> { + Value(&'a Value), + Entry(&'a object::Entry), Key(&'a object::Key), } -impl<'a, M> StrippedFragmentRef<'a, M> { +impl<'a> FragmentRef<'a> { pub fn is_entry(&self) -> bool { matches!(self, Self::Entry(_)) } @@ -730,114 +620,44 @@ impl<'a, M> StrippedFragmentRef<'a, M> { pub fn is_object(&self) -> bool { matches!(self, Self::Value(Value::Object(_))) } -} - -impl<'a, M> Clone for StrippedFragmentRef<'a, M> { - fn clone(&self) -> Self { - *self - } -} - -impl<'a, M> Copy for StrippedFragmentRef<'a, M> {} - -impl<'a, M> StrippedFragmentRef<'a, M> { - pub fn sub_fragments(&self) -> SubFragments<'a, M> { - match self { - Self::Value(Value::Array(a)) => SubFragments::Array(a.iter()), - Self::Value(Value::Object(o)) => SubFragments::Object(o.iter()), - Self::Entry(e) => SubFragments::Entry(Some(&e.key), Some(&e.value)), - _ => SubFragments::None, - } - } -} - -pub enum FragmentRef<'a, M> { - Value(&'a Meta, M>), - Entry(&'a object::Entry), - Key(&'a Meta), -} - -impl<'a, M> FragmentRef<'a, M> { - pub fn is_entry(&self) -> bool { - matches!(self, Self::Entry(_)) - } - - pub fn is_key(&self) -> bool { - matches!(self, Self::Key(_)) - } - - pub fn is_value(&self) -> bool { - matches!(self, Self::Value(_)) - } - pub fn is_null(&self) -> bool { - matches!(self, Self::Value(Meta(Value::Null, _))) - } - - pub fn is_number(&self) -> bool { - matches!(self, Self::Value(Meta(Value::Number(_), _))) - } - - pub fn is_string(&self) -> bool { - matches!(self, Self::Value(Meta(Value::String(_), _))) - } - - pub fn is_array(&self) -> bool { - matches!(self, Self::Value(Meta(Value::Array(_), _))) - } - - pub fn is_object(&self) -> bool { - matches!(self, Self::Value(Meta(Value::Object(_), _))) - } - - pub fn strip(self) -> StrippedFragmentRef<'a, M> { + pub fn strip(self) -> FragmentRef<'a> { match self { - Self::Value(v) => StrippedFragmentRef::Value(v.value()), - Self::Entry(e) => StrippedFragmentRef::Entry(e), - Self::Key(k) => StrippedFragmentRef::Key(k.value()), + Self::Value(v) => FragmentRef::Value(v), + Self::Entry(e) => FragmentRef::Entry(e), + Self::Key(k) => FragmentRef::Key(k), } } } -impl<'a, M> locspan::Strip for FragmentRef<'a, M> { - type Stripped = StrippedFragmentRef<'a, M>; - - fn strip(self) -> Self::Stripped { - self.strip() - } -} - -impl<'a, M> Clone for FragmentRef<'a, M> { +impl<'a> Clone for FragmentRef<'a> { fn clone(&self) -> Self { *self } } -impl<'a, M> Copy for FragmentRef<'a, M> {} +impl<'a> Copy for FragmentRef<'a> {} -impl<'a, M> FragmentRef<'a, M> { - pub fn sub_fragments(&self) -> SubFragments<'a, M> { +impl<'a> FragmentRef<'a> { + pub fn sub_fragments(&self) -> SubFragments<'a> { match self { - Self::Value(Meta(Value::Array(a), _)) => SubFragments::Array(a.iter()), - Self::Value(Meta(Value::Object(o), _)) => SubFragments::Object(o.iter()), + Self::Value(Value::Array(a)) => SubFragments::Array(a.iter()), + Self::Value(Value::Object(o)) => SubFragments::Object(o.iter()), Self::Entry(e) => SubFragments::Entry(Some(&e.key), Some(&e.value)), _ => SubFragments::None, } } } -pub enum SubFragments<'a, M> { +pub enum SubFragments<'a> { None, - Array(core::slice::Iter<'a, Meta, M>>), - Object(core::slice::Iter<'a, object::Entry>), - Entry( - Option<&'a Meta>, - Option<&'a Meta, M>>, - ), + Array(core::slice::Iter<'a, Value>), + Object(core::slice::Iter<'a, object::Entry>), + Entry(Option<&'a object::Key>, Option<&'a Value>), } -impl<'a, M> Iterator for SubFragments<'a, M> { - type Item = FragmentRef<'a, M>; +impl<'a> Iterator for SubFragments<'a> { + type Item = FragmentRef<'a>; fn next(&mut self) -> Option { match self { @@ -852,36 +672,35 @@ impl<'a, M> Iterator for SubFragments<'a, M> { } } -pub struct TraverseStripped<'a, M> { - stack: SmallVec<[StrippedFragmentRef<'a, M>; 8]>, -} - -impl<'a, M> Iterator for TraverseStripped<'a, M> { - type Item = StrippedFragmentRef<'a, M>; - - fn next(&mut self) -> Option { - match self.stack.pop() { - Some(v) => { - self.stack.extend(v.sub_fragments().map(FragmentRef::strip)); - Some(v) - } - None => None, +impl<'a> DoubleEndedIterator for SubFragments<'a> { + fn next_back(&mut self) -> Option { + match self { + Self::None => None, + Self::Array(a) => a.next_back().map(FragmentRef::Value), + Self::Object(e) => e.next_back().map(FragmentRef::Entry), + Self::Entry(k, v) => v + .take() + .map(FragmentRef::Value) + .or_else(|| k.take().map(FragmentRef::Key)), } } } -pub struct Traverse<'a, M> { - stack: SmallVec<[FragmentRef<'a, M>; 8]>, +pub struct Traverse<'a> { + offset: usize, + stack: SmallVec<[FragmentRef<'a>; 8]>, } -impl<'a, M> Iterator for Traverse<'a, M> { - type Item = FragmentRef<'a, M>; +impl<'a> Iterator for Traverse<'a> { + type Item = (usize, FragmentRef<'a>); fn next(&mut self) -> Option { match self.stack.pop() { Some(v) => { - self.stack.extend(v.sub_fragments()); - Some(v) + self.stack.extend(v.sub_fragments().rev()); + let i = self.offset; + self.offset += 1; + Some((i, v)) } None => None, } @@ -890,41 +709,10 @@ impl<'a, M> Iterator for Traverse<'a, M> { #[cfg(test)] mod tests { - use super::*; - - #[test] - fn map_recursively() { - let value: Meta, ()> = json!({ - "b": 0.00000000001, - "c": { - "foo": true, - "bar": false - }, - "a": [ "foo", "bar" ] - }); - - value.map_metadata_recursively(|_| ()); - } - - #[test] - fn try_map_recursively() { - let value: Meta, ()> = json!({ - "b": 0.00000000001, - "c": { - "foo": true, - "bar": false - }, - "a": [ "foo", "bar" ] - }); - - value - .try_map_metadata_recursively::<_, std::convert::Infallible, _>(|_| Ok(())) - .unwrap(); - } - #[cfg(feature = "canonicalize")] #[test] fn canonicalize_01() { + use super::*; let mut value: Meta, ()> = json!({ "b": 0.00000000001, "c": { @@ -945,6 +733,7 @@ mod tests { #[cfg(feature = "canonicalize")] #[test] fn canonicalize_02() { + use super::*; let mut value = Value::parse_str( "{ \"numbers\": [333333333.33333329, 1E30, 4.50, 2e-3, 0.000000000000000000000000001], diff --git a/src/macros.rs b/src/macros.rs index 00796d4..3efcfe0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,9 +1,8 @@ -/// Constructs a `Loc` from a JSON literal. +/// Constructs a `json_syntax::Value` from a JSON literal. /// /// ``` /// # use json_syntax::{Value, json}; -/// # use locspan::Meta; -/// let value: Meta = json!({ +/// let value = json!({ /// "code": 200, /// "success": true, /// "payload": { @@ -19,15 +18,14 @@ /// /// ``` /// # use json_syntax::{Value, object::Key, json}; -/// # use locspan::Meta; /// let code = 200; /// let features = vec!["json", "syntax"]; /// -/// let value: Meta = json!({ -/// "code": Meta(Value::from(code), ()), -/// "success": Meta(Value::from(code == 200), ()), +/// let value = json!({ +/// "code": Value::from(code), +/// "success": Value::from(code == 200), /// "payload": { -/// Meta(Key::from(features[0]), ()): Meta(Value::from(features[1]), ()) +/// Key::from(features[0]): Value::from(features[1]) /// } /// }); /// ``` @@ -36,31 +34,13 @@ /// /// ``` /// # use json_syntax::{Value, json}; -/// # use locspan::Meta; -/// let value: Meta, ()> = json!([ +/// let value = json!([ /// "notice", /// "the", /// "trailing", /// "comma -->", /// ]); /// ``` -/// -/// Metadata information can be added using the `@` symbol. -/// -/// ``` -/// # use json_syntax::{Value, json}; -/// # use locspan::Meta; -/// let value: Meta, u8> = json!({ -/// ("code" @ 0): 200 @ 1, -/// ("success" @ 2): true @ 3, -/// ("payload" @ 4): { -/// ("features" @ 5): [ -/// "json" @ 6, -/// "syntax" @ 7 -/// ] @ 8 -/// } @ 9 -/// } @ 10); -/// ``` #[macro_export(local_inner_macros)] macro_rules! json { ////////////////////////////////////////////////////////////////////////// @@ -80,61 +60,31 @@ macro_rules! json { json_vec![$($elems),*] }; - // Next element is `null` with metadata. - (@array [$($elems:expr,)*] null @ $meta:expr $(,$($rest:tt)*)?) => { - json!(@array [$($elems,)* json!(null @ $meta)] $(,$($rest)*)?) - }; - // Next element is `null`. (@array [$($elems:expr,)*] null $($rest:tt)*) => { json!(@array [$($elems,)* json!(null)] $($rest)*) }; - // Next element is `true` with metadata. - (@array [$($elems:expr,)*] true @ $meta:expr $(,$($rest:tt)*)?) => { - json!(@array [$($elems,)* json!(true @ $meta)] $(,$($rest)*)?) - }; - // Next element is `true`. (@array [$($elems:expr,)*] true $($rest:tt)*) => { json!(@array [$($elems,)* json!(true)] $($rest)*) }; - // Next element is `false` with metadata. - (@array [$($elems:expr,)*] false @ $meta:expr $(,$($rest:tt)*)?) => { - json!(@array [$($elems,)* json!(false @ $meta)] $(,$($rest)*)?) - }; - // Next element is `false`. (@array [$($elems:expr,)*] false $($rest:tt)*) => { json!(@array [$($elems,)* json!(false)] $($rest)*) }; - // Next element is a literal with metadata. - (@array [$($elems:expr,)*] $lit:literal @ $meta:expr $(,$($rest:tt)*)?) => { - json!(@array [$($elems,)* json!($lit @ $meta)] $(,$($rest)*)?) - }; - // Next element is a literal. (@array [$($elems:expr,)*] $lit:literal $($rest:tt)*) => { json!(@array [$($elems,)* json!($lit)] $($rest)*) }; - // Next element is an array with metadata. - (@array [$($elems:expr,)*] [$($array:tt)*] @ $meta:expr $(,$($rest:tt)*)?) => { - json!(@array [$($elems,)* json!([$($array)*] @ $meta)] $(,$($rest)*)?) - }; - // Next element is an array. (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => { json!(@array [$($elems,)* json!([$($array)*])] $($rest)*) }; - // Next element is a map with metadata. - (@array [$($elems:expr,)*] {$($map:tt)*} @ $meta:expr $(,$($rest:tt)*)?) => { - json!(@array [$($elems,)* json!({$($map)*} @ $meta)] $(,$($rest)*)?) - }; - // Next element is a map. (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => { json!(@array [$($elems,)* json!({$($map)*})] $($rest)*) @@ -179,14 +129,9 @@ macro_rules! json { $crate::Object::from_vec(json_vec![$($elems),*]) }; - // Create an entry literal key with metadata. - (@key (($key:literal @ $meta:expr))) => { - ::locspan::Meta($key.into(), $meta) - }; - // Create an entry literal key. (@key ($key:literal)) => { - ::locspan::Meta($key.into(), ()) + $key.into() }; // Create an entry key. @@ -194,61 +139,31 @@ macro_rules! json { $key.into() }; - // Next value is `null` with metadata. - (@object [$($elems:expr,)*] ($($key:tt)+) (: null @ $meta:expr $(,$($rest:tt)*)?) $copy:tt) => { - json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!(null @ $meta))] () ($(,$($rest)*)?) ($(,$($rest)*)?)) - }; - // Next value is `null`. (@object [$($elems:expr,)*] ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => { json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!(null))] () ($($rest)*) ($($rest)*)) }; - // Next value is `true` with metadata. - (@object [$($elems:expr,)*] ($($key:tt)+) (: true @ $meta:expr $(,$($rest:tt)*)?) $copy:tt) => { - json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!(true @ $meta))] () ($(,$($rest)*)?) ($(,$($rest)*)?)) - }; - // Next value is `true`. (@object [$($elems:expr,)*] ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => { json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!(true))] () ($($rest)*) ($($rest)*)) }; - // Next value is `false` with metadata. - (@object [$($elems:expr,)*] ($($key:tt)+) (: false @ $meta:expr $(,$($rest:tt)*)?) $copy:tt) => { - json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!(false @ $meta))] () ($(,$($rest)*)?) ($(,$($rest)*)?)) - }; - // Next value is `false`. (@object [$($elems:expr,)*] ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => { json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!(false))] () ($($rest)*) ($($rest)*)) }; - // Next value is a literal with metadata. - (@object [$($elems:expr,)*] ($($key:tt)+) (: $lit:literal @ $meta:expr $(,$($rest:tt)*)?) $copy:tt) => { - json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!($lit @ $meta))] () ($(,$($rest)*)?) ($(,$($rest)*)?)) - }; - // Next value is a literal. (@object [$($elems:expr,)*] ($($key:tt)+) (: $lit:literal $($rest:tt)*) $copy:tt) => { json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!($lit))] () ($($rest)*) ($($rest)*)) }; - // Next value is a array with metadata. - (@object [$($elems:expr,)*] ($($key:tt)+) (: [$($array:tt)*] @ $meta:expr $(,$($rest:tt)*)?) $copy:tt) => { - json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!([$($array)*] @ $meta))] () ($(,$($rest)*)?) ($(,$($rest)*)?)) - }; - // Next value is a array. (@object [$($elems:expr,)*] ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => { json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!([$($array)*]))] () ($($rest)*) ($($rest)*)) }; - // Next value is a map with metadata. - (@object [$($elems:expr,)*] ($($key:tt)+) (: {$($map:tt)*} @ $meta:expr $(,$($rest:tt)*)?) $copy:tt) => { - json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!({$($map)*} @ $meta))] () ($(,$($rest)*)?) ($(,$($rest)*)?)) - }; - // Next value is a map. (@object [$($elems:expr,)*] ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => { json!(@object [$($elems,)* $crate::object::Entry::new(json!(@key ($($key)+)), json!({$($map)*}))] () ($($rest)*) ($($rest)*)) @@ -316,72 +231,40 @@ macro_rules! json { // Must be invoked as: json!($($json)+) ////////////////////////////////////////////////////////////////////////// - (null @ $meta:expr) => { - ::locspan::Meta($crate::Value::Null, $meta) - }; - (null) => { - json!(null @ ()) - }; - - (true @ $meta:expr) => { - ::locspan::Meta($crate::Value::Boolean(true), $meta) + $crate::Value::Null }; (true) => { - json!(true @ ()) - }; - - (false @ $meta:expr) => { - ::locspan::Meta($crate::Value::Boolean(false), $meta) + $crate::Value::Boolean(true) }; (false) => { - json!(false @ ()) - }; - - ($lit:literal @ $meta:expr) => { - ::locspan::Meta($lit.try_into().unwrap(), $meta) + $crate::Value::Boolean(false) }; ($lit:literal) => { - json!($lit @ ()) - }; - - ([] @ $meta:expr) => { - ::locspan::Meta($crate::Value::Array(json_vec![]), $meta) + $crate::Value::try_from($lit).unwrap() }; ([]) => { - json!([] @ ()) - }; - - ([ $($tt:tt)+ ] @ $meta:expr) => { - ::locspan::Meta($crate::Value::Array(json!(@array [] $($tt)+)), $meta) + $crate::Value::Array(json_vec![]) }; ([ $($tt:tt)+ ]) => { - json!([ $($tt)+ ] @ ()) - }; - - ({} @ $meta:expr) => { - ::locspan::Meta($crate::Value::Object($crate::Object::new()), $meta) + $crate::Value::Array(json!(@array [] $($tt)+)) }; ({}) => { - json!({} @ ()) - }; - - ({ $($tt:tt)+ } @ $meta:expr) => { - ::locspan::Meta($crate::Value::Object(json!(@object [] () ($($tt)+) ($($tt)+))), $meta) + $crate::Value::Object($crate::Object::new()) }; ({ $($tt:tt)+ }) => { - json!({ $($tt)+ } @ ()) + $crate::Value::Object(json!(@object [] () ($($tt)+) ($($tt)+))) }; ($other:expr) => { - $other.into() + $crate::Value::from($other) }; } diff --git a/src/object.rs b/src/object.rs index db52064..afb462f 100644 --- a/src/object.rs +++ b/src/object.rs @@ -1,9 +1,7 @@ -use crate::{MetaValue, UnorderedEq, UnorderedPartialEq, Value}; +use crate::{FragmentRef, UnorderedEq, UnorderedPartialEq, Value}; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; -use locspan::Meta; -use locspan_derive::*; mod index_map; @@ -20,134 +18,61 @@ pub const KEY_CAPACITY: usize = 16; pub type Key = smallstr::SmallString<[u8; KEY_CAPACITY]>; /// Object entry. -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - StrippedPartialEq, - StrippedEq, - StrippedPartialOrd, - StrippedOrd, - StrippedHash, -)] -#[locspan(ignore(M))] -pub struct Entry { - #[locspan(deref_stripped)] - pub key: Meta, - pub value: MetaValue, -} - -impl Entry { - pub fn new(key: Meta, value: MetaValue) -> Self { - Self { key, value } - } - - pub fn as_key(&self) -> &Meta { - &self.key - } - - pub fn as_value(&self) -> &MetaValue { - &self.value - } +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct Entry { + pub key: Key, + pub value: Value, +} - pub fn into_key(self) -> Meta { - self.key +impl Entry { + pub fn new(key: Key, value: Value) -> Self { + Self { key, value } } - pub fn into_value(self) -> MetaValue { - self.value + pub fn get_fragment(&self, index: usize) -> Result { + match index { + 0 => Ok(FragmentRef::Entry(self)), + 1 => Ok(FragmentRef::Key(&self.key)), + _ => self.value.get_fragment(index - 2), + } } - pub fn stripped_key(&self) -> &Key { + pub fn as_key(&self) -> &Key { &self.key } - pub fn stripped_value(&self) -> &Value { + pub fn as_value(&self) -> &Value { &self.value } - pub fn into_stripped_key(self) -> Key { - self.key.into_value() - } - - pub fn into_stripped_value(self) -> Value { - self.value.into_value() - } - - pub fn key_metadata(&self) -> &M { - self.key.metadata() - } - - pub fn value_metadata(&self) -> &M { - self.value.metadata() - } - - pub fn into_key_metadata(self) -> M { - self.key.into_metadata() - } - - pub fn into_value_metadata(self) -> M { - self.value.into_metadata() - } - - pub(crate) fn map_metadata_mut_ref(self, f: &mut F) -> Entry - where - F: FnMut(M) -> N, - { - use locspan::MapMetadataRecursively; - Entry { - key: self.key.map_metadata(&mut *f), - value: self.value.map_metadata_recursively_mut_ref(f), - } - } - - pub fn map_metadata(self, mut f: F) -> Entry - where - F: FnMut(M) -> N, - { - self.map_metadata_mut_ref::(&mut f) + pub fn into_key(self) -> Key { + self.key } - pub(crate) fn try_map_metadata_mut_ref(self, f: &mut F) -> Result, E> - where - F: FnMut(M) -> Result, - { - use locspan::TryMapMetadataRecursively; - Ok(Entry { - key: self.key.try_map_metadata(&mut *f)?, - value: self.value.try_map_metadata_recursively_mut_ref::(f)?, - }) + pub fn into_value(self) -> Value { + self.value } - pub fn try_map_metadata(self, mut f: F) -> Result, E> - where - F: FnMut(M) -> Result, - { - self.try_map_metadata_mut_ref(&mut f) + pub fn as_pair(&self) -> (&Key, &Value) { + (&self.key, &self.value) } - pub fn as_pair(&self) -> (&Meta, &MetaValue) { - (&self.key, &self.value) + pub fn into_pair(self) -> (Key, Value) { + (self.key, self.value) } } /// Object. -#[derive(Clone, StrippedPartialEq, StrippedEq, StrippedPartialOrd, StrippedOrd, StrippedHash)] -#[locspan(ignore(M))] -pub struct Object { +#[derive(Clone)] +pub struct Object { /// The entries of the object, in order. - entries: Vec>, + entries: Vec, - /// Maps each key to - #[locspan(ignore)] + /// Maps each key to an entry index. indexes: IndexMap, } -impl Default for Object { +impl Default for Object { fn default() -> Self { Self { entries: Vec::new(), @@ -156,12 +81,12 @@ impl Default for Object { } } -impl Object { +impl Object { pub fn new() -> Self { Self::default() } - pub fn from_vec(entries: Vec>) -> Self { + pub fn from_vec(entries: Vec) -> Self { let mut indexes = IndexMap::new(); for i in 0..entries.len() { indexes.insert(&entries, i); @@ -182,22 +107,33 @@ impl Object { self.entries.is_empty() } - pub fn entries(&self) -> &[Entry] { + pub fn get_fragment(&self, mut index: usize) -> Result { + for e in &self.entries { + match e.get_fragment(index) { + Ok(value) => return Ok(value), + Err(i) => index = i, + } + } + + Err(index) + } + + pub fn entries(&self) -> &[Entry] { &self.entries } - pub fn iter(&self) -> core::slice::Iter> { + pub fn iter(&self) -> core::slice::Iter { self.entries.iter() } - pub fn iter_mut(&mut self) -> IterMut { + pub fn iter_mut(&mut self) -> IterMut { IterMut(self.entries.iter_mut()) } /// Returns an iterator over the values matching the given key. /// /// Runs in `O(1)` (average). - pub fn get(&self, key: &Q) -> Values + pub fn get(&self, key: &Q) -> Values where Q: Hash + Equivalent, { @@ -215,7 +151,7 @@ impl Object { /// Returns an iterator over the values matching the given key. /// /// Runs in `O(1)` (average). - pub fn get_mut(&mut self, key: &Q) -> ValuesMut + pub fn get_mut(&mut self, key: &Q) -> ValuesMut where Q: Hash + Equivalent, { @@ -235,10 +171,7 @@ impl Object { /// Returns an error if multiple entries match the key. /// /// Runs in `O(1)` (average). - pub fn get_unique( - &self, - key: &Q, - ) -> Result>, Duplicate<&Entry>> + pub fn get_unique(&self, key: &Q) -> Result, Duplicate<&Entry>> where Q: Hash + Equivalent, { @@ -261,7 +194,7 @@ impl Object { pub fn get_unique_mut( &mut self, key: &Q, - ) -> Result>, Duplicate<&Entry>> + ) -> Result, Duplicate<&Entry>> where Q: Hash + Equivalent, { @@ -286,7 +219,7 @@ impl Object { /// Returns an iterator over the entries matching the given key. /// /// Runs in `O(1)` (average). - pub fn get_entries(&self, key: &Q) -> Entries + pub fn get_entries(&self, key: &Q) -> Entries where Q: Hash + Equivalent, { @@ -306,10 +239,7 @@ impl Object { /// Returns an error if multiple entries match the key. /// /// Runs in `O(1)` (average). - pub fn get_unique_entry( - &self, - key: &Q, - ) -> Result>, Duplicate<&Entry>> + pub fn get_unique_entry(&self, key: &Q) -> Result, Duplicate<&Entry>> where Q: Hash + Equivalent, { @@ -327,7 +257,7 @@ impl Object { /// Returns an iterator over the entries matching the given key. /// /// Runs in `O(1)` (average). - pub fn get_with_index(&self, key: &Q) -> ValuesWithIndex + pub fn get_with_index(&self, key: &Q) -> ValuesWithIndex where Q: Hash + Equivalent, { @@ -345,7 +275,7 @@ impl Object { /// Returns an iterator over the entries matching the given key. /// /// Runs in `O(1)` (average). - pub fn get_entries_with_index(&self, key: &Q) -> EntriesWithIndex + pub fn get_entries_with_index(&self, key: &Q) -> EntriesWithIndex where Q: Hash + Equivalent, { @@ -388,11 +318,11 @@ impl Object { .unwrap_or_default() } - pub fn first(&self) -> Option<&Entry> { + pub fn first(&self) -> Option<&Entry> { self.entries.first() } - pub fn last(&self) -> Option<&Entry> { + pub fn last(&self) -> Option<&Entry> { self.entries.last() } @@ -404,18 +334,18 @@ impl Object { /// are preserved, in order. /// /// Runs in `O(1)`. - pub fn push(&mut self, key: Meta, value: MetaValue) -> bool { + pub fn push(&mut self, key: Key, value: Value) -> bool { self.push_entry(Entry::new(key, value)) } - pub fn push_entry(&mut self, entry: Entry) -> bool { + pub fn push_entry(&mut self, entry: Entry) -> bool { let index = self.entries.len(); self.entries.push(entry); self.indexes.insert(&self.entries, index) } /// Removes the entry at the given index. - pub fn remove_at(&mut self, index: usize) -> Option> { + pub fn remove_at(&mut self, index: usize) -> Option { if index < self.entries.len() { self.indexes.remove(&self.entries, index); self.indexes.shift(index); @@ -430,12 +360,8 @@ impl Object { /// If one or more entries are already matching the given key, /// all of them are removed and returned in the resulting iterator. /// Otherwise, `None` is returned. - pub fn insert( - &mut self, - key: Meta, - value: MetaValue, - ) -> Option> { - match self.index_of(key.value()) { + pub fn insert(&mut self, key: Key, value: Value) -> Option { + match self.index_of(&key) { Some(index) => { let mut entry = Entry::new(key, value); core::mem::swap(&mut entry, &mut self.entries[index]); @@ -455,7 +381,7 @@ impl Object { /// Remove all entries associated to the given key. /// /// Runs in `O(n)` time (average). - pub fn remove<'q, Q: ?Sized>(&mut self, key: &'q Q) -> RemovedEntries<'_, 'q, M, Q> + pub fn remove<'q, Q: ?Sized>(&mut self, key: &'q Q) -> RemovedEntries<'_, 'q, Q> where Q: Hash + Equivalent, { @@ -467,10 +393,7 @@ impl Object { /// Returns an error if multiple entries match the key. /// /// Runs in `O(n)` time (average). - pub fn remove_unique( - &mut self, - key: &Q, - ) -> Result>, Duplicate>> + pub fn remove_unique(&mut self, key: &Q) -> Result, Duplicate> where Q: Hash + Equivalent, { @@ -485,55 +408,6 @@ impl Object { } } - /// Recursively maps the metadata inside the object. - pub(crate) fn map_metadata_mut_ref(self, f: &mut F) -> Object - where - F: FnMut(M) -> N, - { - let entries = self - .entries - .into_iter() - .map(|entry| entry.map_metadata_mut_ref::(f)) - .collect(); - - Object { - entries, - indexes: self.indexes, - } - } - - /// Recursively maps the metadata inside the object. - pub fn map_metadata(self, mut f: F) -> Object - where - F: FnMut(M) -> N, - { - self.map_metadata_mut_ref::(&mut f) - } - - /// Tries to recursively maps the metadata inside the object. - pub(crate) fn try_map_metadata_mut_ref(self, f: &mut F) -> Result, E> - where - F: FnMut(M) -> Result, - { - let mut entries = Vec::with_capacity(self.len()); - for entry in self.entries { - entries.push(entry.try_map_metadata_mut_ref::(&mut *f)?) - } - - Ok(Object { - entries, - indexes: self.indexes, - }) - } - - /// Tries to recursively maps the metadata inside the object. - pub fn try_map_metadata(self, mut f: F) -> Result, E> - where - F: FnMut(M) -> Result, - { - self.try_map_metadata_mut_ref(&mut f) - } - /// Sort the entries by key name. /// /// Entries with the same key are sorted by value. @@ -570,37 +444,34 @@ impl Object { } } -pub struct IterMut<'a, M>(std::slice::IterMut<'a, Entry>); +pub struct IterMut<'a>(std::slice::IterMut<'a, Entry>); -impl<'a, M> Iterator for IterMut<'a, M> { - type Item = (&'a Meta, &'a mut MetaValue); +impl<'a> Iterator for IterMut<'a> { + type Item = (&'a Key, &'a mut Value); fn next(&mut self) -> Option { self.0.next().map(|entry| (&entry.key, &mut entry.value)) } } -impl PartialEq for Object { +impl PartialEq for Object { fn eq(&self, other: &Self) -> bool { self.entries == other.entries } } -impl Eq for Object {} +impl Eq for Object {} -impl UnorderedPartialEq for Object { +impl UnorderedPartialEq for Object { fn unordered_eq(&self, other: &Self) -> bool { if self.entries.len() != other.entries.len() { return false; } if !self.iter().all(|Entry { key, value: a }| { - other.get_entries(key.value()).any( - |Entry { - key: other_key, - value: b, - }| key.metadata() == other_key.metadata() && a.unordered_eq(b), - ) + other + .get_entries(key) + .any(|Entry { value: b, .. }| a.unordered_eq(b)) }) { return false; } @@ -611,10 +482,8 @@ impl UnorderedPartialEq for Object { key: other_key, value: b, }| { - self.get_entries(other_key.value()) - .any(|Entry { key, value: a }| { - key.metadata() == other_key.metadata() && a.unordered_eq(b) - }) + self.get_entries(other_key) + .any(|Entry { value: a, .. }| a.unordered_eq(b)) }, ) { return false; @@ -624,27 +493,27 @@ impl UnorderedPartialEq for Object { } } -impl UnorderedEq for Object {} +impl UnorderedEq for Object {} -impl PartialOrd for Object { +impl PartialOrd for Object { fn partial_cmp(&self, other: &Self) -> Option { - self.entries.partial_cmp(&other.entries) + Some(self.entries.cmp(&other.entries)) } } -impl Ord for Object { +impl Ord for Object { fn cmp(&self, other: &Self) -> Ordering { self.entries.cmp(&other.entries) } } -impl Hash for Object { +impl Hash for Object { fn hash(&self, state: &mut H) { self.entries.hash(state) } } -impl fmt::Debug for Object { +impl fmt::Debug for Object { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_map() .entries(self.entries.iter().map(Entry::as_pair)) @@ -652,65 +521,65 @@ impl fmt::Debug for Object { } } -impl From>> for Object { - fn from(entries: Vec>) -> Self { +impl From> for Object { + fn from(entries: Vec) -> Self { Self::from_vec(entries) } } -impl<'a, M> IntoIterator for &'a Object { - type Item = &'a Entry; - type IntoIter = core::slice::Iter<'a, Entry>; +impl<'a> IntoIterator for &'a Object { + type Item = &'a Entry; + type IntoIter = core::slice::Iter<'a, Entry>; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl<'a, M> IntoIterator for &'a mut Object { - type Item = (&'a Meta, &'a mut MetaValue); - type IntoIter = IterMut<'a, M>; +impl<'a> IntoIterator for &'a mut Object { + type Item = (&'a Key, &'a mut Value); + type IntoIter = IterMut<'a>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } -impl IntoIterator for Object { - type Item = Entry; - type IntoIter = std::vec::IntoIter>; +impl IntoIterator for Object { + type Item = Entry; + type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.entries.into_iter() } } -impl Extend> for Object { - fn extend>>(&mut self, iter: I) { +impl Extend for Object { + fn extend>(&mut self, iter: I) { for entry in iter { self.push_entry(entry); } } } -impl FromIterator> for Object { - fn from_iter>>(iter: I) -> Self { +impl FromIterator for Object { + fn from_iter>(iter: I) -> Self { let mut object = Object::default(); object.extend(iter); object } } -impl Extend<(Meta, MetaValue)> for Object { - fn extend, MetaValue)>>(&mut self, iter: I) { +impl Extend<(Key, Value)> for Object { + fn extend>(&mut self, iter: I) { for (key, value) in iter { self.push(key, value); } } } -impl FromIterator<(Meta, MetaValue)> for Object { - fn from_iter, MetaValue)>>(iter: I) -> Self { +impl FromIterator<(Key, Value)> for Object { + fn from_iter>(iter: I) -> Self { let mut object = Object::default(); object.extend(iter); object @@ -752,12 +621,12 @@ macro_rules! entries_iter { fn next(&mut $self:ident, $index:ident) { $e:expr } })*) => { $( - pub struct $id<$lft, M> { + pub struct $id<$lft> { indexes: Indexes<$lft>, - object: &$lft Object + object: &$lft Object } - impl<$lft, M> Iterator for $id<$lft, M> { + impl<$lft> Iterator for $id<$lft> { type Item = $item; fn next(&mut $self) -> Option { @@ -770,25 +639,25 @@ macro_rules! entries_iter { entries_iter! { Values<'a> { - type Item = &'a MetaValue; + type Item = &'a Value; fn next(&mut self, index) { &self.object.entries[index].value } } ValuesWithIndex<'a> { - type Item = (usize, &'a MetaValue); + type Item = (usize, &'a Value); fn next(&mut self, index) { (index, &self.object.entries[index].value) } } Entries<'a> { - type Item = &'a Entry; + type Item = &'a Entry; fn next(&mut self, index) { &self.object.entries[index] } } EntriesWithIndex<'a> { - type Item = (usize, &'a Entry); + type Item = (usize, &'a Entry); fn next(&mut self, index) { (index, &self.object.entries[index]) } } @@ -801,12 +670,12 @@ macro_rules! entries_iter_mut { fn next(&mut $self:ident, $index:ident) { $e:expr } })*) => { $( - pub struct $id<$lft, M> { + pub struct $id<$lft> { indexes: Indexes<$lft>, - entries: &$lft mut [Entry] + entries: &$lft mut [Entry] } - impl<$lft, M> Iterator for $id<$lft, M> { + impl<$lft> Iterator for $id<$lft> { type Item = $item; fn next(&mut $self) -> Option { @@ -819,7 +688,7 @@ macro_rules! entries_iter_mut { entries_iter_mut! { ValuesMut<'a> { - type Item = &'a mut MetaValue; + type Item = &'a mut Value; fn next(&mut self, index) { // This is safe because there is no aliasing between the values. @@ -828,7 +697,7 @@ entries_iter_mut! { } ValuesMutWithIndex<'a> { - type Item = (usize, &'a mut MetaValue); + type Item = (usize, &'a mut Value); fn next(&mut self, index) { // This is safe because there is no aliasing between the values. @@ -837,20 +706,20 @@ entries_iter_mut! { } } -pub struct RemovedByInsertion<'a, M> { +pub struct RemovedByInsertion<'a> { index: usize, - first: Option>, - object: &'a mut Object, + first: Option, + object: &'a mut Object, } -impl<'a, M> Iterator for RemovedByInsertion<'a, M> { - type Item = Entry; +impl<'a> Iterator for RemovedByInsertion<'a> { + type Item = Entry; fn next(&mut self) -> Option { match self.first.take() { Some(entry) => Some(entry), None => { - let key = self.object.entries[self.index].key.value(); + let key = &self.object.entries[self.index].key; self.object .redundant_index_of(key) .and_then(|index| self.object.remove_at(index)) @@ -859,25 +728,25 @@ impl<'a, M> Iterator for RemovedByInsertion<'a, M> { } } -impl<'a, M> Drop for RemovedByInsertion<'a, M> { +impl<'a> Drop for RemovedByInsertion<'a> { fn drop(&mut self) { self.last(); } } -pub struct RemovedEntries<'a, 'q, M, Q: ?Sized> +pub struct RemovedEntries<'a, 'q, Q: ?Sized> where Q: Hash + Equivalent, { key: &'q Q, - object: &'a mut Object, + object: &'a mut Object, } -impl<'a, 'q, M, Q: ?Sized> Iterator for RemovedEntries<'a, 'q, M, Q> +impl<'a, 'q, Q: ?Sized> Iterator for RemovedEntries<'a, 'q, Q> where Q: Hash + Equivalent, { - type Item = Entry; + type Item = Entry; fn next(&mut self) -> Option { self.object @@ -886,7 +755,7 @@ where } } -impl<'a, 'q, M, Q: ?Sized> Drop for RemovedEntries<'a, 'q, M, Q> +impl<'a, 'q, Q: ?Sized> Drop for RemovedEntries<'a, 'q, Q> where Q: Hash + Equivalent, { @@ -907,7 +776,7 @@ mod tests { #[test] fn remove() { let mut object = Object::new(); - object.insert(Meta("a".into(), ()), Meta(Value::Null, ())); + object.insert("a".into(), Value::Null); object.remove("a"); object.remove("a"); @@ -916,56 +785,28 @@ mod tests { #[test] fn unordered_eq1() { let mut a = Object::new(); - a.push(Meta("a".into(), ()), Meta(Value::Null, ())); - a.push(Meta("b".into(), ()), Meta(Value::Null, ())); + a.push("a".into(), Value::Null); + a.push("b".into(), Value::Null); let mut b = Object::new(); - b.push(Meta("b".into(), ()), Meta(Value::Null, ())); - b.push(Meta("a".into(), ()), Meta(Value::Null, ())); + b.push("b".into(), Value::Null); + b.push("a".into(), Value::Null); assert_ne!(a, b); - assert_eq!(a.unordered(), b.unordered()) + assert_eq!(a.as_unordered(), b.as_unordered()) } #[test] fn unordered_eq2() { let mut a = Object::new(); - a.push(Meta("a".into(), ()), Meta(Value::Null, ())); - a.push(Meta("a".into(), ()), Meta(Value::Null, ())); + a.push("a".into(), Value::Null); + a.push("a".into(), Value::Null); let mut b = Object::new(); - b.push(Meta("a".into(), ()), Meta(Value::Null, ())); - b.push(Meta("a".into(), ()), Meta(Value::Null, ())); + b.push("a".into(), Value::Null); + b.push("a".into(), Value::Null); assert_eq!(a, b); - assert_eq!(a.unordered(), b.unordered()) - } - - #[test] - fn unordered_eq3() { - let mut a = Object::new(); - a.push(Meta("a".into(), 0), Meta(Value::Null, 0)); - a.push(Meta("a".into(), 1), Meta(Value::Null, 0)); - - let mut b = Object::new(); - b.push(Meta("a".into(), 1), Meta(Value::Null, 0)); - b.push(Meta("a".into(), 0), Meta(Value::Null, 0)); - - assert_ne!(a, b); - assert_eq!(a.unordered(), b.unordered()) - } - - #[test] - fn unordered_eq4() { - let mut a = Object::new(); - a.push(Meta("a".into(), 0), Meta(Value::Null, 1)); - a.push(Meta("a".into(), 0), Meta(Value::Null, 0)); - - let mut b = Object::new(); - b.push(Meta("a".into(), 0), Meta(Value::Null, 0)); - b.push(Meta("a".into(), 0), Meta(Value::Null, 1)); - - assert_ne!(a, b); - assert_eq!(a.unordered(), b.unordered()) + assert_eq!(a.as_unordered(), b.as_unordered()) } } diff --git a/src/object/index_map.rs b/src/object/index_map.rs index dbca3fb..6ae8fd3 100644 --- a/src/object/index_map.rs +++ b/src/object/index_map.rs @@ -16,42 +16,18 @@ where } } -fn make_insert_hash(hash_builder: &S, val: &K) -> u64 -where - K: ?Sized + Hash, - S: BuildHasher, -{ - use core::hash::Hasher; - let mut state = hash_builder.build_hasher(); - val.hash(&mut state); - state.finish() -} - -fn equivalent_key<'a, M, Q>(entries: &'a [Entry], k: &'a Q) -> impl 'a + Fn(&Indexes) -> bool +fn equivalent_key<'a, Q>(entries: &'a [Entry], k: &'a Q) -> impl 'a + Fn(&Indexes) -> bool where Q: ?Sized + Equivalent, { - move |indexes| k.equivalent(entries[indexes.rep].key.value()) -} - -fn make_hasher<'a, M, S>( - entries: &'a [Entry], - hash_builder: &'a S, -) -> impl 'a + Fn(&Indexes) -> u64 -where - S: BuildHasher, -{ - move |indexes| make_hash::(hash_builder, entries[indexes.rep].key.value()) + move |indexes| k.equivalent(&entries[indexes.rep].key) } -fn make_hash(hash_builder: &S, val: &Key) -> u64 +fn make_hasher<'a, S>(entries: &'a [Entry], hash_builder: &'a S) -> impl 'a + Fn(&Indexes) -> u64 where S: BuildHasher, { - use core::hash::Hasher; - let mut state = hash_builder.build_hasher(); - val.hash(&mut state); - state.finish() + move |indexes| hash_builder.hash_one(&entries[indexes.rep].key) } #[derive(Clone, Debug, PartialEq, Eq)] @@ -191,20 +167,20 @@ impl IndexMap { } impl IndexMap { - pub fn get(&self, entries: &[Entry], key: &Q) -> Option<&Indexes> + pub fn get(&self, entries: &[Entry], key: &Q) -> Option<&Indexes> where Q: Hash + Equivalent, { - let hash = make_insert_hash(&self.hash_builder, key); + let hash = self.hash_builder.hash_one(key); self.table.get(hash, equivalent_key(entries, key)) } /// Associates the given `key` to `index`. /// /// Returns `true` if no index was already associated to the key. - pub fn insert(&mut self, entries: &[Entry], index: usize) -> bool { - let key = entries[index].key.value(); - let hash = make_insert_hash(&self.hash_builder, key); + pub fn insert(&mut self, entries: &[Entry], index: usize) -> bool { + let key = &entries[index].key; + let hash = self.hash_builder.hash_one(key); match self.table.get_mut(hash, equivalent_key(entries, key)) { Some(indexes) => { indexes.insert(index); @@ -214,7 +190,7 @@ impl IndexMap { self.table.insert( hash, Indexes::new(index), - make_hasher::(entries, &self.hash_builder), + make_hasher::(entries, &self.hash_builder), ); true } @@ -222,9 +198,9 @@ impl IndexMap { } /// Removes the association between the given key and index. - pub fn remove(&mut self, entries: &[Entry], index: usize) { - let key = entries[index].key.value(); - let hash = make_insert_hash(&self.hash_builder, key); + pub fn remove(&mut self, entries: &[Entry], index: usize) { + let key = &entries[index].key; + let hash = self.hash_builder.hash_one(key); if let Some(bucket) = self.table.find(hash, equivalent_key(entries, key)) { let indexes = unsafe { bucket.as_mut() }; @@ -253,14 +229,13 @@ impl IndexMap { mod tests { use super::*; use crate::Value; - use locspan::Meta; #[test] fn insert() { let entries = [ - Entry::new(Meta("a".into(), ()), Meta(Value::Null, ())), - Entry::new(Meta("b".into(), ()), Meta(Value::Null, ())), - Entry::new(Meta("a".into(), ()), Meta(Value::Null, ())), + Entry::new("a".into(), Value::Null), + Entry::new("b".into(), Value::Null), + Entry::new("a".into(), Value::Null), ]; let mut indexes: IndexMap = IndexMap::default(); @@ -282,9 +257,9 @@ mod tests { #[test] fn remove1() { let entries = [ - Entry::new(Meta("a".into(), ()), Meta(Value::Null, ())), - Entry::new(Meta("b".into(), ()), Meta(Value::Null, ())), - Entry::new(Meta("a".into(), ()), Meta(Value::Null, ())), + Entry::new("a".into(), Value::Null), + Entry::new("b".into(), Value::Null), + Entry::new("a".into(), Value::Null), ]; let mut indexes: IndexMap = IndexMap::default(); @@ -305,9 +280,9 @@ mod tests { #[test] fn remove2() { let entries = [ - Entry::new(Meta("a".into(), ()), Meta(Value::Null, ())), - Entry::new(Meta("b".into(), ()), Meta(Value::Null, ())), - Entry::new(Meta("a".into(), ()), Meta(Value::Null, ())), + Entry::new("a".into(), Value::Null), + Entry::new("b".into(), Value::Null), + Entry::new("a".into(), Value::Null), ]; let mut indexes: IndexMap = IndexMap::default(); diff --git a/src/parse.rs b/src/parse.rs index c818951..396f32a 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,8 +1,6 @@ -use crate::Value; use decoded_char::DecodedChar; use locspan::{Meta, Span}; use std::fmt; -use std::iter::Peekable; mod array; mod boolean; @@ -12,6 +10,8 @@ mod object; mod string; mod value; +use crate::CodeMap; + /// Parser options. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct Options { @@ -57,187 +57,103 @@ impl Default for Options { } } -pub trait Parse: Sized { - fn parse_str(content: &str, metadata_builder: F) -> Result, Meta, M>> - where - F: FnMut(Span) -> M, - { - Self::parse_utf8(content.chars().map(Ok), metadata_builder) +pub trait Parse: Sized { + fn parse_str(content: &str) -> Result<(Self, CodeMap), Error> { + Self::parse_utf8(content.chars().map(Ok)) } - fn parse_str_with( - content: &str, - options: Options, - metadata_builder: F, - ) -> Result, Meta, M>> - where - F: FnMut(Span) -> M, - { - Self::parse_utf8_with(content.chars().map(Ok), options, metadata_builder) + fn parse_str_with(content: &str, options: Options) -> Result<(Self, CodeMap), Error> { + Self::parse_utf8_with(content.chars().map(Ok), options) } - fn parse_infallible_utf8( - chars: C, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse_infallible_utf8(chars: C) -> Result<(Self, CodeMap), Error> where C: Iterator, - F: FnMut(Span) -> M, { - Self::parse_infallible(chars.map(DecodedChar::from_utf8), metadata_builder) + Self::parse_infallible(chars.map(DecodedChar::from_utf8)) } - fn parse_utf8_infallible_with( - chars: C, - options: Options, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse_utf8_infallible_with(chars: C, options: Options) -> Result<(Self, CodeMap), Error> where C: Iterator, - F: FnMut(Span) -> M, { - Self::parse_infallible_with(chars.map(DecodedChar::from_utf8), options, metadata_builder) + Self::parse_infallible_with(chars.map(DecodedChar::from_utf8), options) } - fn parse_utf8( - chars: C, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse_utf8(chars: C) -> Result<(Self, CodeMap), Error> where C: Iterator>, - F: FnMut(Span) -> M, { - Self::parse( - chars.map(|c| c.map(DecodedChar::from_utf8)), - metadata_builder, - ) + Self::parse(chars.map(|c| c.map(DecodedChar::from_utf8))) } - fn parse_utf8_with( - chars: C, - options: Options, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse_utf8_with(chars: C, options: Options) -> Result<(Self, CodeMap), Error> where C: Iterator>, - F: FnMut(Span) -> M, { - Self::parse_with( - chars.map(|c| c.map(DecodedChar::from_utf8)), - options, - metadata_builder, - ) + Self::parse_with(chars.map(|c| c.map(DecodedChar::from_utf8)), options) } - fn parse_infallible( - chars: C, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse_infallible(chars: C) -> Result<(Self, CodeMap), Error> where C: Iterator, - F: FnMut(Span) -> M, { - let mut parser = Parser::new(chars.map(Ok), metadata_builder); - Self::parse_in(&mut parser, Context::None) + let mut parser = Parser::new(chars.map(Ok)); + let value = Self::parse_in(&mut parser, Context::None)?.into_value(); + Ok((value, parser.code_map)) } - fn parse_infallible_with( - chars: C, - options: Options, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse_infallible_with(chars: C, options: Options) -> Result<(Self, CodeMap), Error> where C: Iterator, - F: FnMut(Span) -> M, - { - let mut parser = Parser::new_with(chars.map(Ok), options, metadata_builder); - Self::parse_in(&mut parser, Context::None) - } - - fn parse(chars: C, metadata_builder: F) -> Result, Meta, M>> - where - C: Iterator>, - F: FnMut(Span) -> M, { - let mut parser = Parser::new(chars, metadata_builder); - Self::parse_in(&mut parser, Context::None) + let mut parser = Parser::new_with(chars.map(Ok), options); + let value = Self::parse_in(&mut parser, Context::None)?.into_value(); + Ok((value, parser.code_map)) } - fn parse_with( - chars: C, - options: Options, - metadata_builder: F, - ) -> Result, Meta, M>> + fn parse(chars: C) -> Result<(Self, CodeMap), Error> where C: Iterator>, - F: FnMut(Span) -> M, { - let mut parser = Parser::new_with(chars, options, metadata_builder); - Self::parse_in(&mut parser, Context::None) + let mut parser = Parser::new(chars); + let value = Self::parse_in(&mut parser, Context::None)?.into_value(); + Ok((value, parser.code_map)) } - fn parse_in( - parser: &mut Parser, - context: Context, - ) -> Result, Meta, M>> + fn parse_with(chars: C, options: Options) -> Result<(Self, CodeMap), Error> where C: Iterator>, - F: FnMut(Span) -> M, { - let Meta(value, span) = Self::parse_spanned(parser, context)?; - Ok(Meta(value, parser.position.metadata_at(span))) + let mut parser = Parser::new_with(chars, options); + let value = Self::parse_in(&mut parser, Context::None)?.into_value(); + Ok((value, parser.code_map)) } - fn parse_spanned( - parser: &mut Parser, + fn parse_in( + parser: &mut Parser, context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where - C: Iterator>, - F: FnMut(Span) -> M; -} - -pub trait ValueOrParse: Parse { - fn value_or_parse( - value: Option, Span>>, - parser: &mut Parser, - context: Context, - ) -> Result, Meta, M>> - where - C: Iterator>, - F: FnMut(Span) -> M; -} - -impl ValueOrParse for T -where - T: Parse + From>, -{ - fn value_or_parse( - value: Option, Span>>, - parser: &mut Parser, - context: Context, - ) -> Result, Meta, M>> - where - C: Iterator>, - F: FnMut(Span) -> M, - { - match value { - Some(value) => Ok(value.cast()), - None => Self::parse_spanned(parser, context), - } - } + C: Iterator>; } /// JSON parser. -pub struct Parser>, F, E> { +pub struct Parser>, E> { /// Character stream. - chars: Peekable, + chars: C, + + /// Pending next char. + pending: Option, /// Position in the stream. - position: Position, + position: usize, /// Parser options. options: Options, + + /// Code-map. + code_map: CodeMap, } /// Checks if the given char `c` is a JSON whitespace. @@ -246,48 +162,72 @@ pub fn is_whitespace(c: char) -> bool { matches!(c, ' ' | '\t' | '\r' | '\n') } -impl>, F, M, E> Parser -where - F: FnMut(Span) -> M, -{ - pub fn new(chars: C, metadata_builder: F) -> Self { +impl>, E> Parser { + pub fn new(chars: C) -> Self { Self { - chars: chars.peekable(), - position: Position::new(metadata_builder), + chars, + pending: None, + position: 0, options: Options::default(), + code_map: CodeMap::default(), } } - pub fn new_with(chars: C, options: Options, metadata_builder: F) -> Self { + pub fn new_with(chars: C, options: Options) -> Self { Self { - chars: chars.peekable(), - position: Position::new(metadata_builder), + chars, + pending: None, + position: 0, options, + code_map: CodeMap::default(), } } - fn peek_char(&mut self) -> Result, Meta, M>> { - match self.chars.peek() { - None => Ok(None), - Some(Ok(c)) => Ok(Some(c.chr())), - Some(Err(_)) => self.next_char(), - } + fn begin_fragment(&mut self) -> usize { + self.code_map.reserve(self.position) } - fn next_char(&mut self) -> Result, Meta, M>> { - match self.chars.next() { - None => Ok(None), - Some(Ok(c)) => { - self.position.span.push(c.len()); - self.position.last_span.clear(); - self.position.last_span.push(c.len()); - Ok(Some(c.into_char())) - } - Some(Err(e)) => Err(Meta(Error::Stream(e), self.position.end())), + fn end_fragment(&mut self, i: usize) { + let entry_count = self.code_map.len(); + let entry = self.code_map.get_mut(i).unwrap(); + entry.span.set_end(self.position); + entry.volume = entry_count - i; + } + + fn peek_char(&mut self) -> Result, Error> { + match self.pending { + Some(c) => Ok(Some(c.chr())), + None => match self.chars.next() { + Some(Ok(c)) => { + self.pending = Some(c); + Ok(Some(c.chr())) + } + Some(Err(e)) => Err(Error::Stream(self.position, e)), + None => Ok(None), + }, } } - fn skip_whitespaces(&mut self) -> Result<(), Meta, M>> { + fn next_char(&mut self) -> Result<(usize, Option), Error> { + let c = match self.pending.take() { + Some(c) => Some(c), + None => self + .chars + .next() + .transpose() + .map_err(|e| Error::Stream(self.position, e))?, + }; + + let p = self.position; + let c = c.map(|c| { + self.position += c.len(); + c.chr() + }); + + Ok((p, c)) + } + + fn skip_whitespaces(&mut self) -> Result<(), Error> { while let Some(c) = self.peek_char()? { if is_whitespace(c) { self.next_char()?; @@ -296,112 +236,87 @@ where } } - self.position.span.clear(); - Ok(()) - } - - fn skip_trailing_whitespaces(&mut self, context: Context) -> Result<(), Meta, M>> { - self.skip_whitespaces()?; - - if let Some(c) = self.peek_char()? { - if !context.follows(c) { - // panic!("unexpected {:?} in {:?}", c, context); - return Err(Meta(Error::unexpected(Some(c)), self.position.last())); - } - } - Ok(()) } } /// Parse error. #[derive(Debug)] -pub enum Error { +pub enum Error { /// Stream error. - Stream(E), + /// + /// The first parameter is the byte index at which the error occurred. + Stream(usize, E), /// Unexpected character or end of stream. - Unexpected(Option), + /// + /// The first parameter is the byte index at which the error occurred. + Unexpected(usize, Option), /// Invalid unicode codepoint. - InvalidUnicodeCodePoint(u32), + /// + /// The first parameter is the span at which the error occurred. + InvalidUnicodeCodePoint(Span, u32), /// Missing low surrogate in a string. - MissingLowSurrogate(Meta), + /// + /// The first parameter is the byte index at which the error occurred. + MissingLowSurrogate(Span, u16), /// Invalid low surrogate in a string. - InvalidLowSurrogate(Meta, u32), + /// + /// The first parameter is the span at which the error occurred. + InvalidLowSurrogate(Span, u16, u32), } -impl Error { +impl Error { /// Creates an `Unexpected` error. #[inline(always)] - fn unexpected(c: Option) -> Self { + fn unexpected(position: usize, c: Option) -> Self { // panic!("unexpected {:?}", c); - Self::Unexpected(c) + Self::Unexpected(position, c) } -} -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + pub fn position(&self) -> usize { match self { - Self::Stream(e) => e.fmt(f), - Self::Unexpected(Some(c)) => write!(f, "unexpected character `{}`", c), - Self::Unexpected(None) => write!(f, "unexpected end of file"), - Self::InvalidUnicodeCodePoint(c) => write!(f, "invalid Unicode code point {:x}", *c), - Self::MissingLowSurrogate(_) => write!(f, "missing low surrogate"), - Self::InvalidLowSurrogate(_, _) => write!(f, "invalid low surrogate"), + Self::Stream(p, _) => *p, + Self::Unexpected(p, _) => *p, + Self::InvalidUnicodeCodePoint(span, _) => span.start(), + Self::MissingLowSurrogate(span, _) => span.start(), + Self::InvalidLowSurrogate(span, _, _) => span.start(), } } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + pub fn span(&self) -> Span { match self { - Self::Stream(e) => Some(e), - _ => None, + Self::Stream(p, _) => Span::new(*p, *p), + Self::Unexpected(p, _) => Span::new(*p, *p), + Self::InvalidUnicodeCodePoint(span, _) => *span, + Self::MissingLowSurrogate(span, _) => *span, + Self::InvalidLowSurrogate(span, _, _) => *span, } } } -pub type MetaError = Meta, M>; - -/// Lexer position. -struct Position { - span: Span, - last_span: Span, - metadata_builder: F, -} - -impl Position { - fn new(metadata_builder: F) -> Self { - Self { - span: Span::default(), - last_span: Span::default(), - metadata_builder, +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Stream(_, e) => e.fmt(f), + Self::Unexpected(_, Some(c)) => write!(f, "unexpected character `{}`", c), + Self::Unexpected(_, None) => write!(f, "unexpected end of file"), + Self::InvalidUnicodeCodePoint(_, c) => write!(f, "invalid Unicode code point {:x}", *c), + Self::MissingLowSurrogate(_, _) => write!(f, "missing low surrogate"), + Self::InvalidLowSurrogate(_, _, _) => write!(f, "invalid low surrogate"), } } - - fn current_span(&self) -> Span { - self.span - } } -impl M, M> Position { - fn metadata_at(&mut self, span: Span) -> M { - (self.metadata_builder)(span) - } - - fn current(&mut self) -> M { - (self.metadata_builder)(self.span) - } - - fn end(&mut self) -> M { - (self.metadata_builder)(self.span.end().into()) - } - - fn last(&mut self) -> M { - (self.metadata_builder)(self.last_span) +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Stream(_, e) => Some(e), + _ => None, + } } } diff --git a/src/parse/array.rs b/src/parse/array.rs index 947b255..e319deb 100644 --- a/src/parse/array.rs +++ b/src/parse/array.rs @@ -1,56 +1,40 @@ use super::{Context, Error, Parse, Parser}; use decoded_char::DecodedChar; -use locspan::{Meta, Span}; +use locspan::Meta; use locspan_derive::*; -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - StrippedPartialEq, - StrippedEq, - StrippedPartialOrd, - StrippedOrd, - StrippedHash, -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum StartFragment { Empty, NonEmpty, } -impl Parse for StartFragment { - fn parse_spanned( - parser: &mut Parser, +impl Parse for StartFragment { + fn parse_in( + parser: &mut Parser, _context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { + let i = parser.begin_fragment(); match parser.next_char()? { - Some('[') => { + (_, Some('[')) => { parser.skip_whitespaces()?; match parser.peek_char()? { Some(']') => { parser.next_char()?; - Ok(Meta(StartFragment::Empty, parser.position.current_span())) + parser.end_fragment(i); + Ok(Meta(StartFragment::Empty, i)) } _ => { // wait for value. - Ok(Meta( - StartFragment::NonEmpty, - parser.position.current_span(), - )) + Ok(Meta(StartFragment::NonEmpty, i)) } } } - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } @@ -75,19 +59,19 @@ pub enum ContinueFragment { End, } -impl Parse for ContinueFragment { - fn parse_spanned( - parser: &mut Parser, - _context: Context, - ) -> Result, Meta, M>> +impl ContinueFragment { + pub fn parse_in(parser: &mut Parser, array: usize) -> Result> where C: Iterator>, - F: FnMut(Span) -> M, { + parser.skip_whitespaces()?; match parser.next_char()? { - Some(',') => Ok(Meta(Self::Item, parser.position.current_span())), - Some(']') => Ok(Meta(Self::End, parser.position.current_span())), - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (_, Some(',')) => Ok(Self::Item), + (_, Some(']')) => { + parser.end_fragment(array); + Ok(Self::End) + } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } diff --git a/src/parse/boolean.rs b/src/parse/boolean.rs index 3daeacb..522e5d3 100644 --- a/src/parse/boolean.rs +++ b/src/parse/boolean.rs @@ -1,47 +1,47 @@ use super::{Context, Error, Parse, Parser}; use decoded_char::DecodedChar; -use locspan::{Meta, Span}; +use locspan::Meta; -impl Parse for bool { - fn parse_spanned( - parser: &mut Parser, +impl Parse for bool { + fn parse_in( + parser: &mut Parser, _context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { + let i = parser.begin_fragment(); match parser.next_char()? { - Some('t') => match parser.next_char()? { - Some('r') => match parser.next_char()? { - Some('u') => match parser.next_char()? { - Some('e') => Ok(Meta(true, parser.position.current_span())), - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) + (_, Some('t')) => match parser.next_char()? { + (_, Some('r')) => match parser.next_char()? { + (_, Some('u')) => match parser.next_char()? { + (_, Some('e')) => { + parser.end_fragment(i); + Ok(Meta(true, i)) } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - Some('f') => match parser.next_char()? { - Some('a') => match parser.next_char()? { - Some('l') => match parser.next_char()? { - Some('s') => match parser.next_char()? { - Some('e') => Ok(Meta(false, parser.position.current_span())), - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) + (_, Some('f')) => match parser.next_char()? { + (_, Some('a')) => match parser.next_char()? { + (_, Some('l')) => match parser.next_char()? { + (_, Some('s')) => match parser.next_char()? { + (_, Some('e')) => { + parser.end_fragment(i); + Ok(Meta(false, i)) } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) - } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } diff --git a/src/parse/null.rs b/src/parse/null.rs index b74e92b..d1c5ffa 100644 --- a/src/parse/null.rs +++ b/src/parse/null.rs @@ -1,30 +1,31 @@ use super::{Context, Error, Parse, Parser}; use decoded_char::DecodedChar; -use locspan::{Meta, Span}; +use locspan::Meta; -impl Parse for () { - fn parse_spanned( - parser: &mut Parser, +impl Parse for () { + fn parse_in( + parser: &mut Parser, _context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { + let i = parser.begin_fragment(); match parser.next_char()? { - Some('n') => match parser.next_char()? { - Some('u') => match parser.next_char()? { - Some('l') => match parser.next_char()? { - Some('l') => Ok(Meta((), parser.position.current_span())), - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) + (_, Some('n')) => match parser.next_char()? { + (_, Some('u')) => match parser.next_char()? { + (_, Some('l')) => match parser.next_char()? { + (_, Some('l')) => { + parser.end_fragment(i); + Ok(Meta((), i)) } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } diff --git a/src/parse/number.rs b/src/parse/number.rs index 4dcf8bb..0cb3892 100644 --- a/src/parse/number.rs +++ b/src/parse/number.rs @@ -1,18 +1,18 @@ use super::{Context, Error, Parse, Parser}; use crate::{NumberBuf, SMALL_STRING_CAPACITY}; use decoded_char::DecodedChar; -use locspan::{Meta, Span}; +use locspan::Meta; use smallvec::SmallVec; -impl Parse for NumberBuf { - fn parse_spanned( - parser: &mut Parser, +impl Parse for NumberBuf { + fn parse_in( + parser: &mut Parser, context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { + let i = parser.begin_fragment(); let mut buffer: SmallVec<[u8; SMALL_STRING_CAPACITY]> = SmallVec::new(); enum State { @@ -35,12 +35,12 @@ impl Parse for NumberBuf { '-' => state = State::FirstDigit, '0' => state = State::Zero, '1'..='9' => state = State::NonZero, - _ => return Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + _ => return Err(Error::unexpected(parser.position, Some(c))), }, State::FirstDigit => match c { '0' => state = State::Zero, '1'..='9' => state = State::NonZero, - _ => return Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + _ => return Err(Error::unexpected(parser.position, Some(c))), }, State::Zero => match c { '.' => state = State::FractionalFirst, @@ -49,7 +49,7 @@ impl Parse for NumberBuf { if context.follows(c) { break; } else { - return Err(Meta(Error::unexpected(Some(c)), parser.position.last())); + return Err(Error::unexpected(parser.position, Some(c))); } } }, @@ -61,13 +61,13 @@ impl Parse for NumberBuf { if context.follows(c) { break; } else { - return Err(Meta(Error::unexpected(Some(c)), parser.position.last())); + return Err(Error::unexpected(parser.position, Some(c))); } } }, State::FractionalFirst => match c { '0'..='9' => state = State::FractionalRest, - _ => return Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + _ => return Err(Error::unexpected(parser.position, Some(c))), }, State::FractionalRest => match c { '0'..='9' => state = State::FractionalRest, @@ -76,18 +76,18 @@ impl Parse for NumberBuf { if context.follows(c) { break; } else { - return Err(Meta(Error::unexpected(Some(c)), parser.position.last())); + return Err(Error::unexpected(parser.position, Some(c))); } } }, State::ExponentSign => match c { '+' | '-' => state = State::ExponentFirst, '0'..='9' => state = State::ExponentRest, - _ => return Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + _ => return Err(Error::unexpected(parser.position, Some(c))), }, State::ExponentFirst => match c { '0'..='9' => state = State::ExponentRest, - _ => return Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + _ => return Err(Error::unexpected(parser.position, Some(c))), }, State::ExponentRest => match c { '0'..='9' => state = State::ExponentRest, @@ -95,7 +95,7 @@ impl Parse for NumberBuf { if context.follows(c) { break; } else { - return Err(Meta(Error::unexpected(Some(c)), parser.position.last())); + return Err(Error::unexpected(parser.position, Some(c))); } } }, @@ -110,12 +110,10 @@ impl Parse for NumberBuf { state, State::Zero | State::NonZero | State::FractionalRest | State::ExponentRest ) { - Ok(Meta( - unsafe { NumberBuf::new_unchecked(buffer) }, - parser.position.current_span(), - )) + parser.end_fragment(i); + Ok(Meta(unsafe { NumberBuf::new_unchecked(buffer) }, i)) } else { - Err(Meta(Error::unexpected(None), parser.position.last())) + Err(Error::unexpected(parser.position, None)) } } } diff --git a/src/parse/object.rs b/src/parse/object.rs index ac57b22..c630535 100644 --- a/src/parse/object.rs +++ b/src/parse/object.rs @@ -1,110 +1,76 @@ use super::{Context, Error, Parse, Parser}; use crate::object::Key; use decoded_char::DecodedChar; -use locspan::{Meta, Span}; -use locspan_derive::*; +use locspan::Meta; -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - StrippedPartialEq, - StrippedEq, - StrippedPartialOrd, - StrippedOrd, - StrippedHash, -)] -#[locspan(ignore(M))] -pub enum StartFragment { +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum StartFragment { Empty, - NonEmpty(#[locspan(deref_stripped)] Meta), + NonEmpty(Meta), } -impl Parse for StartFragment { - fn parse_spanned( - parser: &mut Parser, +impl Parse for StartFragment { + fn parse_in( + parser: &mut Parser, _context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { + let i = parser.begin_fragment(); match parser.next_char()? { - Some('{') => { + (_, Some('{')) => { parser.skip_whitespaces()?; match parser.peek_char()? { Some('}') => { parser.next_char()?; - Ok(Meta(StartFragment::Empty, parser.position.current_span())) + Ok(Meta(StartFragment::Empty, i)) } _ => { - let span = parser.position.span; - parser.position.span.clear(); + let e = parser.begin_fragment(); let key = Key::parse_in(parser, Context::ObjectKey)?; - let span = span.union(parser.position.span); parser.skip_whitespaces()?; match parser.next_char()? { - Some(':') => Ok(Meta(Self::NonEmpty(key), span)), - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) - } + (_, Some(':')) => Ok(Meta(Self::NonEmpty(Meta(key.0, e)), i)), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } } - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - StrippedPartialEq, - StrippedEq, - StrippedPartialOrd, - StrippedOrd, - StrippedHash, -)] -#[locspan(ignore(M))] -pub enum ContinueFragment { +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum ContinueFragment { End, - Entry(#[locspan(deref_stripped)] Meta), + Entry(Meta), } -impl Parse for ContinueFragment { - fn parse_spanned( - parser: &mut Parser, - _context: Context, - ) -> Result, Meta, M>> +impl ContinueFragment { + pub fn parse_in(parser: &mut Parser, object: usize) -> Result> where C: Iterator>, - F: FnMut(Span) -> M, { + parser.skip_whitespaces()?; match parser.next_char()? { - Some(',') => { - let span = parser.position.span; + (_, Some(',')) => { parser.skip_whitespaces()?; + let e = parser.begin_fragment(); let key = Key::parse_in(parser, Context::ObjectKey)?; - let span = span.union(parser.position.span); parser.skip_whitespaces()?; match parser.next_char()? { - Some(':') => Ok(Meta(Self::Entry(key), span)), - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (_, Some(':')) => Ok(Self::Entry(Meta(key.0, e))), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } - Some('}') => Ok(Meta(Self::End, parser.position.current_span())), - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (_, Some('}')) => { + parser.end_fragment(object); + Ok(Self::End) + } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } diff --git a/src/parse/string.rs b/src/parse/string.rs index 3900d33..3354740 100644 --- a/src/parse/string.rs +++ b/src/parse/string.rs @@ -7,102 +7,81 @@ fn is_control(c: char) -> bool { ('\u{0000}'..='\u{001f}').contains(&c) } -fn parse_hex4( - parser: &mut Parser, -) -> Result, Meta, M>> +fn parse_hex4(parser: &mut Parser) -> Result> where C: Iterator>, - F: FnMut(Span) -> M, { match parser.next_char()? { - Some(c) => match c.to_digit(16) { + (p, Some(c)) => match c.to_digit(16) { Some(h3) => match parser.next_char()? { - Some(c) => match c.to_digit(16) { + (p, Some(c)) => match c.to_digit(16) { Some(h2) => match parser.next_char()? { - Some(c) => match c.to_digit(16) { + (p, Some(c)) => match c.to_digit(16) { Some(h1) => match parser.next_char()? { - Some(c) => match c.to_digit(16) { - Some(h0) => Ok(Meta( - h3 << 12 | h2 << 8 | h1 << 4 | h0, - parser.position.current_span(), - )), - None => Err(Meta( - Error::unexpected(Some(c)), - parser.position.last(), - )), + (p, Some(c)) => match c.to_digit(16) { + Some(h0) => Ok(h3 << 12 | h2 << 8 | h1 << 4 | h0), + None => Err(Error::unexpected(p, Some(c))), }, - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) - } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - None => Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + None => Err(Error::unexpected(p, Some(c))), }, - unexpected => { - Err(Meta(Error::unexpected(unexpected), parser.position.last())) - } + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - None => Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + None => Err(Error::unexpected(p, Some(c))), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), }, - None => Err(Meta(Error::unexpected(Some(c)), parser.position.last())), + None => Err(Error::unexpected(p, Some(c))), }, - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } -impl> Parse for SmallString { - fn parse_spanned( - parser: &mut Parser, +impl> Parse for SmallString { + fn parse_in( + parser: &mut Parser, _context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { + let i = parser.begin_fragment(); match parser.next_char()? { - Some('"') => { + (_, Some('"')) => { let mut result = Self::new(); - let span = parser.position.span; - parser.position.span.clear(); - - let mut high_surrogate: Option> = None; - + let mut high_surrogate: Option<(usize, u32)> = None; loop { let c = match parser.next_char()? { - Some('"') => { - if let Some(Meta(high, span)) = high_surrogate { + (p, Some('"')) => { + if let Some((p_high, high)) = high_surrogate { if parser.options.accept_truncated_surrogate_pair { result.push('\u{fffd}'); } else { - break Err(Meta( - Error::MissingLowSurrogate(Meta( - high as u16, - parser.position.metadata_at(span), - )), - parser.position.current(), + break Err(Error::MissingLowSurrogate( + Span::new(p_high, p), + high as u16, )); } } - parser.position.span = span.union(parser.position.span); - break Ok(Meta(result, parser.position.current_span())); + parser.end_fragment(i); + break Ok(Meta(result, i)); } - Some('\\') => match parser.next_char()? { - Some(c @ ('"' | '\\' | '/')) => c, - Some('b') => '\u{0008}', - Some('t') => '\u{0009}', - Some('n') => '\u{000a}', - Some('f') => '\u{000c}', - Some('r') => '\u{000d}', - Some('u') => { - let Meta(codepoint, codepoint_span) = parse_hex4(parser)?; + (_, Some('\\')) => match parser.next_char()? { + (_, Some(c @ ('"' | '\\' | '/'))) => c, + (_, Some('b')) => '\u{0008}', + (_, Some('t')) => '\u{0009}', + (_, Some('n')) => '\u{000a}', + (_, Some('f')) => '\u{000c}', + (_, Some('r')) => '\u{000d}', + (p, Some('u')) => { + let codepoint = parse_hex4(parser)?; match high_surrogate.take() { - Some(Meta(high, high_span)) => { + Some((p_high, high)) => { if (0xdc00..=0xdfff).contains(&codepoint) { let low = codepoint; - let low_span = codepoint_span; let codepoint = ((high - 0xd800) << 10 | (low - 0xdc00)) + 0x010000; match char::from_u32(codepoint) { @@ -111,13 +90,9 @@ impl> Parse for SmallString { if parser.options.accept_invalid_codepoints { '\u{fffd}' } else { - break Err(Meta( - Error::InvalidUnicodeCodePoint( - codepoint, - ), - parser.position.metadata_at( - low_span.union(high_span), - ), + break Err(Error::InvalidUnicodeCodePoint( + Span::new(p_high, parser.position), + codepoint, )); } } @@ -131,33 +106,24 @@ impl> Parse for SmallString { if parser.options.accept_invalid_codepoints { '\u{fffd}' } else { - break Err(Meta( - Error::InvalidUnicodeCodePoint( - codepoint, - ), - parser - .position - .metadata_at(codepoint_span), + break Err(Error::InvalidUnicodeCodePoint( + Span::new(p, parser.position), + codepoint, )); } } } } else { - break Err(Meta( - Error::InvalidLowSurrogate( - Meta( - high as u16, - parser.position.metadata_at(high_span), - ), - codepoint, - ), - parser.position.metadata_at(codepoint_span), + break Err(Error::InvalidLowSurrogate( + Span::new(p, parser.position), + high as u16, + codepoint, )); } } None => { if (0xd800..=0xdbff).contains(&codepoint) { - high_surrogate = Some(Meta(codepoint, codepoint_span)); + high_surrogate = Some((p, codepoint)); continue; } else { match char::from_u32(codepoint) { @@ -166,13 +132,9 @@ impl> Parse for SmallString { if parser.options.accept_invalid_codepoints { '\u{fffd}' } else { - break Err(Meta( - Error::InvalidUnicodeCodePoint( - codepoint, - ), - parser - .position - .metadata_at(codepoint_span), + break Err(Error::InvalidUnicodeCodePoint( + Span::new(p, parser.position), + codepoint, )); } } @@ -181,38 +143,27 @@ impl> Parse for SmallString { } } } - unexpected => { - break Err(Meta( - Error::unexpected(unexpected), - parser.position.last(), - )) - } + (p, unexpected) => break Err(Error::unexpected(p, unexpected)), }, - Some(c) if !is_control(c) => c, - unexpected => { - break Err(Meta(Error::unexpected(unexpected), parser.position.last())) - } + (_, Some(c)) if !is_control(c) => c, + (p, unexpected) => break Err(Error::unexpected(p, unexpected)), }; - if let Some(Meta(high, span)) = high_surrogate.take() { + if let Some((p_high, high)) = high_surrogate.take() { if parser.options.accept_truncated_surrogate_pair { result.push('\u{fffd}'); } else { - break Err(Meta( - Error::MissingLowSurrogate(Meta( - high as u16, - parser.position.metadata_at(span), - )), - parser.position.current(), + break Err(Error::MissingLowSurrogate( + Span::new(p_high, parser.position), + high as u16, )); } } result.push(c); - parser.position.span.clear(); } } - unexpected => Err(Meta(Error::unexpected(unexpected), parser.position.last())), + (p, unexpected) => Err(Error::unexpected(p, unexpected)), } } } diff --git a/src/parse/value.rs b/src/parse/value.rs index 6f55219..5498cd9 100644 --- a/src/parse/value.rs +++ b/src/parse/value.rs @@ -1,60 +1,60 @@ -use super::{array, object, Context, Error, Parse, Parser, ValueOrParse}; +use super::{array, object, Context, Error, Parse, Parser}; use crate::{object::Key, Array, NumberBuf, Object, String, Value}; use decoded_char::DecodedChar; -use locspan::{Meta, Span}; -use locspan_derive::*; +use locspan::Meta; /// Value fragment. -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - StrippedPartialEq, - StrippedEq, - StrippedPartialOrd, - StrippedOrd, - StrippedHash, -)] -#[locspan(ignore(F))] -pub enum Fragment { - Value(Value), +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum Fragment { + Value(Value), BeginArray, - BeginObject(#[locspan(deref_stripped)] Meta), + BeginObject(Meta), } -impl From> for Fragment { - fn from(v: Value) -> Self { +impl Fragment { + fn value_or_parse( + value: Option>, + parser: &mut Parser, + context: Context, + ) -> Result, Error> + where + C: Iterator>, + { + match value { + Some(value) => Ok(value.cast()), + None => Self::parse_in(parser, context), + } + } +} + +impl From for Fragment { + fn from(v: Value) -> Self { Self::Value(v) } } -impl Parse for Fragment { - fn parse_spanned( - parser: &mut Parser, +impl Parse for Fragment { + fn parse_in( + parser: &mut Parser, context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { parser.skip_whitespaces()?; let value = match parser.peek_char()? { - Some('n') => <()>::parse_spanned(parser, context)?.map(|()| Value::Null), - Some('t' | 'f') => bool::parse_spanned(parser, context)?.map(Value::Boolean), - Some('0'..='9' | '-') => NumberBuf::parse_spanned(parser, context)?.map(Value::Number), - Some('"') => String::parse_spanned(parser, context)?.map(Value::String), - Some('[') => match array::StartFragment::parse_spanned(parser, context)? { + Some('n') => <()>::parse_in(parser, context)?.map(|()| Value::Null), + Some('t' | 'f') => bool::parse_in(parser, context)?.map(Value::Boolean), + Some('0'..='9' | '-') => NumberBuf::parse_in(parser, context)?.map(Value::Number), + Some('"') => String::parse_in(parser, context)?.map(Value::String), + Some('[') => match array::StartFragment::parse_in(parser, context)? { Meta(array::StartFragment::Empty, span) => Meta(Value::Array(Array::new()), span), Meta(array::StartFragment::NonEmpty, span) => { return Ok(Meta(Self::BeginArray, span)) } }, - Some('{') => match object::StartFragment::parse_spanned(parser, context)? { + Some('{') => match object::StartFragment::parse_in(parser, context)? { Meta(object::StartFragment::Empty, span) => { Meta(Value::Object(Object::new()), span) } @@ -62,39 +62,36 @@ impl Parse for Fragment { return Ok(Meta(Self::BeginObject(key), span)) } }, - unexpected => return Err(Meta(Error::unexpected(unexpected), parser.position.last())), + unexpected => return Err(Error::unexpected(parser.position, unexpected)), }; - parser.skip_trailing_whitespaces(context)?; - Ok(value.map(Self::Value)) } } -impl Parse for Value { - fn parse_spanned( - parser: &mut Parser, +impl Parse for Value { + fn parse_in( + parser: &mut Parser, context: Context, - ) -> Result, Meta, M>> + ) -> Result, Error> where C: Iterator>, - F: FnMut(Span) -> M, { - enum Item { - Array(Meta, Span>), - ArrayItem(Meta, Span>), - Object(Meta, Span>), - ObjectEntry(Meta, Span>, Meta), + enum StackItem { + Array(Meta), + ArrayItem(Meta), + Object(Meta), + ObjectEntry(Meta, Meta), } - let mut stack: Vec> = vec![]; - let mut value: Option, Span>> = None; + let mut stack: Vec = vec![]; + let mut value: Option> = None; - fn stack_context(stack: &[Item], root: Context) -> Context { + fn stack_context(stack: &[StackItem], root: Context) -> Context { match stack.last() { - Some(Item::Array(_) | Item::ArrayItem(_)) => Context::Array, - Some(Item::Object(_)) => Context::ObjectKey, - Some(Item::ObjectEntry(_, _)) => Context::ObjectValue, + Some(StackItem::Array(_) | StackItem::ArrayItem(_)) => Context::Array, + Some(StackItem::Object(_)) => Context::ObjectKey, + Some(StackItem::ObjectEntry(_, _)) => Context::ObjectValue, None => root, } } @@ -106,79 +103,68 @@ impl Parse for Value { parser, stack_context(&stack, context), )? { - Meta(Fragment::Value(value), span) => break Ok(Meta(value, span)), - Meta(Fragment::BeginArray, span) => { - stack.push(Item::ArrayItem(Meta(Array::new(), span))) + Meta(Fragment::Value(value), i) => { + parser.skip_whitespaces()?; + break match parser.next_char()? { + (p, Some(c)) => Err(Error::unexpected(p, Some(c))), + (_, None) => Ok(Meta(value, i)), + }; } - Meta(Fragment::BeginObject(key), span) => { - stack.push(Item::ObjectEntry(Meta(Object::new(), span), key)) + Meta(Fragment::BeginArray, i) => { + stack.push(StackItem::ArrayItem(Meta(Array::new(), i))) + } + Meta(Fragment::BeginObject(key), i) => { + stack.push(StackItem::ObjectEntry(Meta(Object::new(), i), key)) } }, - Some(Item::Array(Meta(array, span))) => { - match array::ContinueFragment::parse_spanned( - parser, - stack_context(&stack, context), - )? { - Meta(array::ContinueFragment::Item, comma_span) => { - stack.push(Item::ArrayItem(Meta(array, span.union(comma_span)))) - } - Meta(array::ContinueFragment::End, closing_span) => { - parser.skip_trailing_whitespaces(stack_context(&stack, context))?; - value = Some(Meta(Value::Array(array), span.union(closing_span))) + Some(StackItem::Array(Meta(array, i))) => { + match array::ContinueFragment::parse_in(parser, i)? { + array::ContinueFragment::Item => { + stack.push(StackItem::ArrayItem(Meta(array, i))) } + array::ContinueFragment::End => value = Some(Meta(Value::Array(array), i)), } } - Some(Item::ArrayItem(Meta(mut array, span))) => { + Some(StackItem::ArrayItem(Meta(mut array, i))) => { match Fragment::value_or_parse(value.take(), parser, Context::Array)? { - Meta(Fragment::Value(value), value_span) => { - array.push(Meta(value, parser.position.metadata_at(value_span))); - stack.push(Item::Array(Meta(array, span.union(value_span)))); + Meta(Fragment::Value(value), _) => { + array.push(value); + stack.push(StackItem::Array(Meta(array, i))); } - Meta(Fragment::BeginArray, value_span) => { - stack.push(Item::ArrayItem(Meta(array, span.union(value_span)))); - stack.push(Item::ArrayItem(Meta(Array::new(), value_span))) + Meta(Fragment::BeginArray, j) => { + stack.push(StackItem::ArrayItem(Meta(array, i))); + stack.push(StackItem::ArrayItem(Meta(Array::new(), j))) } - Meta(Fragment::BeginObject(value_key), value_span) => { - stack.push(Item::ArrayItem(Meta(array, span.union(value_span)))); - stack.push(Item::ObjectEntry( - Meta(Object::new(), value_span), - value_key, - )) + Meta(Fragment::BeginObject(value_key), j) => { + stack.push(StackItem::ArrayItem(Meta(array, i))); + stack.push(StackItem::ObjectEntry(Meta(Object::new(), j), value_key)) } } } - Some(Item::Object(Meta(object, span))) => { - match object::ContinueFragment::parse_spanned( - parser, - stack_context(&stack, context), - )? { - Meta(object::ContinueFragment::Entry(key), comma_key_span) => stack.push( - Item::ObjectEntry(Meta(object, span.union(comma_key_span)), key), - ), - Meta(object::ContinueFragment::End, closing_span) => { - parser.skip_trailing_whitespaces(stack_context(&stack, context))?; - value = Some(Meta(Value::Object(object), span.union(closing_span))) + Some(StackItem::Object(Meta(object, i))) => { + match object::ContinueFragment::parse_in(parser, i)? { + object::ContinueFragment::Entry(key) => { + stack.push(StackItem::ObjectEntry(Meta(object, i), key)) + } + object::ContinueFragment::End => { + value = Some(Meta(Value::Object(object), i)) } } } - Some(Item::ObjectEntry(Meta(mut object, span), key)) => { + Some(StackItem::ObjectEntry(Meta(mut object, i), Meta(key, e))) => { match Fragment::value_or_parse(value.take(), parser, Context::ObjectValue)? { - Meta(Fragment::Value(value), value_span) => { - object.push(key, Meta(value, parser.position.metadata_at(value_span))); - stack.push(Item::Object(Meta(object, span.union(value_span)))); + Meta(Fragment::Value(value), _) => { + parser.end_fragment(e); + object.push(key, value); + stack.push(StackItem::Object(Meta(object, i))); } - Meta(Fragment::BeginArray, value_span) => { - stack - .push(Item::ObjectEntry(Meta(object, span.union(value_span)), key)); - stack.push(Item::ArrayItem(Meta(Array::new(), value_span))) + Meta(Fragment::BeginArray, j) => { + stack.push(StackItem::ObjectEntry(Meta(object, i), Meta(key, e))); + stack.push(StackItem::ArrayItem(Meta(Array::new(), j))) } - Meta(Fragment::BeginObject(value_key), value_span) => { - stack - .push(Item::ObjectEntry(Meta(object, span.union(value_span)), key)); - stack.push(Item::ObjectEntry( - Meta(Object::new(), value_span), - value_key, - )) + Meta(Fragment::BeginObject(value_key), j) => { + stack.push(StackItem::ObjectEntry(Meta(object, i), Meta(key, e))); + stack.push(StackItem::ObjectEntry(Meta(Object::new(), j), value_key)) } } } diff --git a/src/print.rs b/src/print.rs index 1575506..0886d66 100644 --- a/src/print.rs +++ b/src/print.rs @@ -598,7 +598,7 @@ where f.write_str("}") } -impl PrintWithSize for crate::Object { +impl PrintWithSize for crate::Object { #[inline(always)] fn fmt_with_size( &self, @@ -634,7 +634,7 @@ impl PrecomputeSize for bool { } } -impl PrecomputeSize for crate::Value { +impl PrecomputeSize for crate::Value { fn pre_compute_size(&self, options: &Options, sizes: &mut Vec) -> Size { match self { crate::Value::Null => Size::Width(4), @@ -788,7 +788,7 @@ where size } -impl Print for crate::Value { +impl Print for crate::Value { fn fmt_with(&self, f: &mut fmt::Formatter, options: &Options, indent: usize) -> fmt::Result { match self { Self::Null => f.write_str("null"), @@ -796,13 +796,15 @@ impl Print for crate::Value { Self::Number(n) => n.fmt_with(f, options, indent), Self::String(s) => s.fmt_with(f, options, indent), Self::Array(a) => { - let mut sizes = Vec::with_capacity(self.count(|v| v.is_array() || v.is_object())); + let mut sizes = + Vec::with_capacity(self.count(|_, v| v.is_array() || v.is_object())); self.pre_compute_size(options, &mut sizes); let mut index = 0; a.fmt_with_size(f, options, indent, &sizes, &mut index) } Self::Object(o) => { - let mut sizes = Vec::with_capacity(self.count(|v| v.is_array() || v.is_object())); + let mut sizes = + Vec::with_capacity(self.count(|_, v| v.is_array() || v.is_object())); self.pre_compute_size(options, &mut sizes); let mut index = 0; o.fmt_with_size(f, options, indent, &sizes, &mut index) @@ -811,7 +813,7 @@ impl Print for crate::Value { } } -impl PrintWithSize for crate::Value { +impl PrintWithSize for crate::Value { fn fmt_with_size( &self, f: &mut fmt::Formatter, diff --git a/src/unordered.rs b/src/unordered.rs index 2abec1b..54be4cd 100644 --- a/src/unordered.rs +++ b/src/unordered.rs @@ -6,14 +6,14 @@ use locspan::Meta; /// the objects entries. #[derive(Debug)] #[repr(transparent)] -pub struct Unordered(T); +pub struct Unordered(pub T); pub trait BorrowUnordered { - fn unordered(&self) -> &Unordered; + fn as_unordered(&self) -> &Unordered; } impl BorrowUnordered for T { - fn unordered(&self) -> &Unordered { + fn as_unordered(&self) -> &Unordered { unsafe { core::mem::transmute(self) } } } @@ -28,6 +28,12 @@ impl UnorderedPartialEq for Meta { } } +impl UnorderedPartialEq for Vec { + fn unordered_eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.unordered_eq(b)) + } +} + impl PartialEq for Unordered { fn eq(&self, other: &Self) -> bool { self.0.unordered_eq(&other.0) diff --git a/tests/macro.rs b/tests/macro.rs index 51614b4..94e4e4c 100644 --- a/tests/macro.rs +++ b/tests/macro.rs @@ -3,215 +3,181 @@ use json_syntax::{ object::{Entry, Key}, Object, Value, }; -use locspan::Meta; #[test] fn macro_01() { - let value: Meta, ()> = json! { + let value = json! { null }; - assert_eq!(value, Meta(Value::Null, ())) + assert_eq!(value, Value::Null) } #[test] fn macro_02() { - let value: Meta, ()> = json! { + let value = json! { true }; - assert_eq!(value, Meta(Value::Boolean(true), ())) + assert_eq!(value, Value::Boolean(true)) } #[test] fn macro_03() { - let value: Meta, ()> = json! { + let value = json! { false }; - assert_eq!(value, Meta(Value::Boolean(false), ())) + assert_eq!(value, Value::Boolean(false)) } #[test] fn macro_04() { - let value: Meta, ()> = json! { + let value = json! { [] }; - assert_eq!(value, Meta(Value::Array(vec![]), ())) + assert_eq!(value, Value::Array(vec![])) } #[test] fn macro_05() { - let value: Meta, ()> = json! { + let value = json! { {} }; - assert_eq!(value, Meta(Value::Object(Object::default()), ())) + assert_eq!(value, Value::Object(Object::default())) } #[test] fn macro_06() { - let value: Meta, ()> = json! { + let value = json! { [ null ] }; - assert_eq!(value, Meta(Value::Array(vec![Meta(Value::Null, ())]), ())) + assert_eq!(value, Value::Array(vec![Value::Null])) } #[test] fn macro_07() { - let value: Meta, ()> = json! { + let value = json! { { "foo": null } }; assert_eq!( value, - Meta( - Value::Object(vec![Entry::new(Meta("foo".into(), ()), Meta(Value::Null, ()))].into()), - () - ) + Value::Object(vec![Entry::new("foo".into(), Value::Null)].into()) ) } #[test] fn macro_08() { let item = json! { null }; - let value: Meta, ()> = json! { + let value = json! { [ item ] }; - assert_eq!(value, Meta(Value::Array(vec![Meta(Value::Null, ())]), ())) + assert_eq!(value, Value::Array(vec![Value::Null])) } #[test] fn macro_09() { - let value: Meta, ()> = json! { + let value = json! { [ [ null ], true, false ] }; assert_eq!( value, - Meta( - Value::Array(vec![ - Meta(Value::Array(vec![Meta(Value::Null, ())]), ()), - Meta(Value::Boolean(true), ()), - Meta(Value::Boolean(false), ()) - ]), - () - ) + Value::Array(vec![ + Value::Array(vec![Value::Null]), + Value::Boolean(true), + Value::Boolean(false) + ]) ) } #[test] fn macro_10() { - let value: Meta, ()> = json! { + let value = json! { { "a": true, "b": false } }; assert_eq!( value, - Meta( - Value::Object(Object::from_vec(vec![ - Entry::new(Meta("a".into(), ()), Meta(Value::Boolean(true), ())), - Entry::new(Meta("b".into(), ()), Meta(Value::Boolean(false), ())) - ])), - () - ) + Value::Object(Object::from_vec(vec![ + Entry::new("a".into(), Value::Boolean(true)), + Entry::new("b".into(), Value::Boolean(false)) + ])) ) } #[test] fn macro_11() { - let key = Meta(Key::from("a"), ()); + let key = Key::from("a"); let t = json! { true }; - let value: Meta, ()> = json! { + let value = json! { { key: t, "b": false } }; assert_eq!( value, - Meta( - Value::Object(Object::from_vec(vec![ - Entry::new(Meta("a".into(), ()), Meta(Value::Boolean(true), ())), - Entry::new(Meta("b".into(), ()), Meta(Value::Boolean(false), ())) - ])), - () - ) + Value::Object(Object::from_vec(vec![ + Entry::new("a".into(), Value::Boolean(true)), + Entry::new("b".into(), Value::Boolean(false)) + ])) ) } #[test] fn macro_12() { - let keys = [Meta(Key::from("a"), ()), Meta(Key::from("c"), ())]; + let keys = [Key::from("a"), Key::from("c")]; let values = [json! { true }, json! { false }]; - let value: Meta, ()> = json! { + let value = json! { { keys[0].clone(): values[0].clone(), "b": {}, keys[1].clone(): values[1].clone() } }; assert_eq!( value, - Meta( - Value::Object(Object::from_vec(vec![ - Entry::new(Meta("a".into(), ()), Meta(Value::Boolean(true), ())), - Entry::new( - Meta("b".into(), ()), - Meta(Value::Object(Object::default()), ()) - ), - Entry::new(Meta("c".into(), ()), Meta(Value::Boolean(false), ())) - ])), - () - ) + Value::Object(Object::from_vec(vec![ + Entry::new("a".into(), Value::Boolean(true)), + Entry::new("b".into(), Value::Object(Object::default())), + Entry::new("c".into(), Value::Boolean(false)) + ])) ) } #[test] fn macro_13() { - let keys = [Meta(Key::from("a"), 1), Meta(Key::from("c"), 5)]; - let values = [json! { true @ 2 }, json! { false @ 6 }]; + let keys = [Key::from("a"), Key::from("c")]; + let values = [json! { true }, json! { false }]; - let value: Meta, u32> = json! { - { keys[0].clone(): values[0].clone(), ("b" @ 3): {} @ 4, keys[1].clone(): values[1].clone() } @ 7 + let value = json! { + { keys[0].clone(): values[0].clone(), ("b"): {}, keys[1].clone(): values[1].clone() } }; assert_eq!( value, - Meta( - Value::Object(Object::from_vec(vec![ - Entry::new(Meta("a".into(), 1), Meta(Value::Boolean(true), 2)), - Entry::new( - Meta("b".into(), 3), - Meta(Value::Object(Object::default()), 4) - ), - Entry::new(Meta("c".into(), 5), Meta(Value::Boolean(false), 6)) - ])), - 7 - ) + Value::Object(Object::from_vec(vec![ + Entry::new("a".into(), Value::Boolean(true)), + Entry::new("b".into(), Value::Object(Object::default())), + Entry::new("c".into(), Value::Boolean(false)) + ])) ) } #[test] fn macro_14() { - let value: Meta, ()> = json! { + let value = json! { { "a": 0.1f32, "b": 1.1e10f32 } }; assert_eq!( value, - Meta( - Value::Object(Object::from_vec(vec![ - Entry::new( - Meta("a".into(), ()), - Meta(Value::Number(0.1f32.try_into().unwrap()), ()) - ), - Entry::new( - Meta("b".into(), ()), - Meta(Value::Number(1.1e10f32.try_into().unwrap()), ()) - ) - ])), - () - ) + Value::Object(Object::from_vec(vec![ + Entry::new("a".into(), Value::Number(0.1f32.try_into().unwrap())), + Entry::new("b".into(), Value::Number(1.1e10f32.try_into().unwrap())) + ])) ) } diff --git a/tests/parse.rs b/tests/parse.rs index 95e9f00..37568b6 100644 --- a/tests/parse.rs +++ b/tests/parse.rs @@ -11,7 +11,7 @@ fn test + Debug>(filename: P, options: Options) { std::borrow::Cow::Borrowed(std::str::from_utf8(&buffer).unwrap()) }; - Value::parse_str_with(&input, options, |span| span).expect("parse error"); + Value::parse_str_with(&input, options).expect("parse error"); } #[test] diff --git a/tests/print.rs b/tests/print.rs index e248dcc..53c4eb0 100644 --- a/tests/print.rs +++ b/tests/print.rs @@ -1,75 +1,74 @@ -use json_syntax::{json, Print, Value}; -use locspan::Meta; +use json_syntax::{json, Print}; #[test] fn print_01() { - let value: Meta, ()> = json! { null }; + let value = json! { null }; assert_eq!(value.pretty_print().to_string(), "null") } #[test] fn print_02() { - let value: Meta, ()> = json! { true }; + let value = json! { true }; assert_eq!(value.pretty_print().to_string(), "true") } #[test] fn print_03() { - let value: Meta, ()> = json! { false }; + let value = json! { false }; assert_eq!(value.pretty_print().to_string(), "false") } #[test] fn print_04() { - let value: Meta, ()> = json! { "foo" }; + let value = json! { "foo" }; assert_eq!(value.pretty_print().to_string(), "\"foo\"") } #[test] fn print_05() { - let value: Meta, ()> = json! { 1 }; + let value = json! { 1 }; assert_eq!(value.pretty_print().to_string(), "1") } #[test] fn print_06() { - let value: Meta, ()> = json! { [] }; + let value = json! { [] }; assert_eq!(value.pretty_print().to_string(), "[]") } #[test] fn print_07() { - let value: Meta, ()> = json! { [ null ] }; + let value = json! { [ null ] }; assert_eq!(value.pretty_print().to_string(), "[ null ]") } #[test] fn print_08() { - let value: Meta, ()> = json! { [ "azertyuiop" ] }; + let value = json! { [ "azertyuiop" ] }; assert_eq!(value.pretty_print().to_string(), "[ \"azertyuiop\" ]") } #[test] fn print_09() { - let value: Meta, ()> = json! { [ "azertyuiopq" ] }; + let value = json! { [ "azertyuiopq" ] }; assert_eq!(value.pretty_print().to_string(), "[\n \"azertyuiopq\"\n]") } #[test] fn print_10() { - let value: Meta, ()> = json! { [ true, false ] }; + let value = json! { [ true, false ] }; assert_eq!(value.pretty_print().to_string(), "[\n true,\n false\n]") } #[test] fn print_11() { - let value: Meta, ()> = json! { { "a": null } }; + let value = json! { { "a": null } }; assert_eq!(value.pretty_print().to_string(), "{ \"a\": null }") } #[test] fn print_12() { - let value: Meta, ()> = json! { { "a": null, "b": 12 } }; + let value = json! { { "a": null, "b": 12 } }; assert_eq!( value.pretty_print().to_string(), "{\n \"a\": null,\n \"b\": 12\n}" @@ -78,7 +77,7 @@ fn print_12() { #[test] fn print_13() { - let value: Meta, ()> = json! { { "a": [ null ], "b": [ 13 ] } }; + let value = json! { { "a": [ null ], "b": [ 13 ] } }; assert_eq!( value.pretty_print().to_string(), "{\n \"a\": [ null ],\n \"b\": [ 13 ]\n}" @@ -87,7 +86,7 @@ fn print_13() { #[test] fn print_14() { - let value: Meta, ()> = json! { { "a": [ null, [] ], "b": [ 14 ] } }; + let value = json! { { "a": [ null, [] ], "b": [ 14 ] } }; assert_eq!( value.pretty_print().to_string(), "{\n \"a\": [\n null,\n []\n ],\n \"b\": [ 14 ]\n}"