pub use json_number::Number;
use locspan::Meta;
use locspan_derive::*;
pub mod object;
pub mod parse;
mod unordered;
pub use parse::Parse;
pub mod print;
pub use print::Print;
mod macros;
pub use unordered::*;
pub const SMALL_STRING_CAPACITY: usize = 16;
pub type String = smallstr::SmallString<[u8; SMALL_STRING_CAPACITY]>;
pub type Array<M> = Vec<Meta<Value<M>, M>>;
pub use object::Object;
pub const NUMBER_CAPACITY: usize = SMALL_STRING_CAPACITY;
pub type NumberBuf = json_number::SmallNumberBuf<NUMBER_CAPACITY>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Kind {
Null,
Boolean,
Number,
String,
Array,
Object,
}
#[derive(
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Debug,
StrippedPartialEq,
StrippedEq,
StrippedPartialOrd,
StrippedOrd,
StrippedHash,
)]
#[stripped_ignore(M)]
pub enum Value<M> {
Null,
Boolean(#[stripped] bool),
Number(#[stripped] NumberBuf),
String(#[stripped] String),
Array(Array<M>),
Object(Object<M>),
}
impl<M> Value<M> {
#[inline]
pub fn kind(&self) -> Kind {
match self {
Self::Null => Kind::Null,
Self::Boolean(_) => Kind::Boolean,
Self::Number(_) => Kind::Number,
Self::String(_) => Kind::String,
Self::Array(_) => Kind::Array,
Self::Object(_) => Kind::Object,
}
}
#[inline]
pub fn is_kind(&self, kind: Kind) -> bool {
self.kind() == kind
}
#[inline]
pub fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
#[inline]
pub fn is_boolean(&self) -> bool {
matches!(self, Self::Boolean(_))
}
#[inline]
pub fn is_number(&self) -> bool {
matches!(self, Self::Number(_))
}
#[inline]
pub fn is_string(&self) -> bool {
matches!(self, Self::String(_))
}
#[inline]
pub fn is_array(&self) -> bool {
matches!(self, Self::Array(_))
}
#[inline]
pub fn is_object(&self) -> bool {
matches!(self, Self::Object(_))
}
#[inline]
pub fn as_boolean(&self) -> Option<bool> {
match self {
Self::Boolean(b) => Some(*b),
_ => None,
}
}
#[inline]
pub fn as_boolean_mut(&mut self) -> Option<&mut bool> {
match self {
Self::Boolean(b) => Some(b),
_ => None,
}
}
#[inline]
pub fn as_number(&self) -> Option<&Number> {
match self {
Self::Number(n) => Some(n),
_ => None,
}
}
#[inline]
pub fn as_number_mut(&mut self) -> Option<&mut NumberBuf> {
match self {
Self::Number(n) => Some(n),
_ => None,
}
}
#[inline]
pub fn as_string(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
#[inline]
pub fn as_string_mut(&mut self) -> Option<&mut String> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
#[inline]
pub fn as_array(&self) -> Option<&[Meta<Self, M>]> {
match self {
Self::Array(a) => Some(a),
_ => None,
}
}
#[inline]
pub fn as_array_mut(&mut self) -> Option<&mut Array<M>> {
match self {
Self::Array(a) => Some(a),
_ => None,
}
}
#[inline]
pub fn as_object(&self) -> Option<&Object<M>> {
match self {
Self::Object(o) => Some(o),
_ => None,
}
}
#[inline]
pub fn as_object_mut(&mut self) -> Option<&mut Object<M>> {
match self {
Self::Object(o) => Some(o),
_ => None,
}
}
#[inline]
pub fn into_boolean(self) -> Option<bool> {
match self {
Self::Boolean(b) => Some(b),
_ => None,
}
}
#[inline]
pub fn into_number(self) -> Option<NumberBuf> {
match self {
Self::Number(n) => Some(n),
_ => None,
}
}
#[inline]
pub fn into_string(self) -> Option<String> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
#[inline]
pub fn into_array(self) -> Option<Array<M>> {
match self {
Self::Array(a) => Some(a),
_ => None,
}
}
#[inline]
pub fn into_object(self) -> Option<Object<M>> {
match self {
Self::Object(o) => Some(o),
_ => None,
}
}
pub fn count(&self, f: impl Clone + Fn(&Self) -> bool) -> usize {
let mut result = if f(self) { 1 } else { 0 };
match self {
Self::Array(array) => {
for item in array {
result += item.count(f.clone())
}
}
Self::Object(object) => {
for entry in object {
result += entry.value.count(f.clone())
}
}
_ => (),
}
result
}
pub fn volume(&self) -> usize {
self.count(|_| true)
}
pub fn map_metadata<N>(self, mut f: impl FnMut(M) -> N) -> Value<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 f), f(meta)))
.collect(),
),
Self::Object(o) => Value::Object(o.map_metadata(f)),
}
}
pub fn try_map_metadata<N, E>(
self,
mut f: impl FnMut(M) -> Result<N, E>,
) -> Result<Value<N>, E> {
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 {
items.push(item.try_map_metadata_recursively(&mut f)?)
}
Ok(Value::Array(items))
}
Self::Object(o) => Ok(Value::Object(o.try_map_metadata(f)?)),
}
}
}
impl<M, N> locspan::MapMetadataRecursively<M, N> for Value<M> {
type Output = Value<N>;
fn map_metadata_recursively<F: FnMut(M) -> N>(self, f: F) -> Value<N> {
self.map_metadata(f)
}
}
impl<M, N, E> locspan::TryMapMetadataRecursively<M, N, E> for Value<M> {
type Output = Value<N>;
fn try_map_metadata_recursively<F: FnMut(M) -> Result<N, E>>(
self,
f: F,
) -> Result<Value<N>, E> {
self.try_map_metadata(f)
}
}
impl<M> From<bool> for Value<M> {
fn from(b: bool) -> Self {
Self::Boolean(b)
}
}
impl<M> From<NumberBuf> for Value<M> {
fn from(n: NumberBuf) -> Self {
Self::Number(n)
}
}
impl<'n, M> From<&'n Number> for Value<M> {
fn from(n: &'n Number) -> Self {
Self::Number(unsafe { NumberBuf::new_unchecked(n.as_bytes().into()) })
}
}
impl<M> From<String> for Value<M> {
fn from(s: String) -> Self {
Self::String(s)
}
}
impl<M> From<::std::string::String> for Value<M> {
fn from(s: ::std::string::String) -> Self {
Self::String(s.into())
}
}
impl<'s, M> From<&'s str> for Value<M> {
fn from(s: &'s str) -> Self {
Self::String(s.into())
}
}
impl<M> From<Array<M>> for Value<M> {
fn from(a: Array<M>) -> Self {
Self::Array(a)
}
}
impl<M> From<Object<M>> for Value<M> {
fn from(o: Object<M>) -> Self {
Self::Object(o)
}
}
macro_rules! from_integer {
($($ty:ident),*) => {
$(
impl<M> From<$ty> for Value<M> {
fn from(n: $ty) -> Self {
Value::Number(n.into())
}
}
)*
};
}
from_integer! {
u8,
u16,
u32,
u64,
i8,
i16,
i32,
i64
}
macro_rules! try_from_float {
($($ty:ident),*) => {
$(
impl<M> TryFrom<$ty> for Value<M> {
type Error = json_number::TryFromFloatError;
fn try_from(n: $ty) -> Result<Self, Self::Error> {
Ok(Value::Number(n.try_into()?))
}
}
)*
};
}
try_from_float! {
f32,
f64
}