pub mod cmp;
#[cfg(feature = "conformance")]
pub mod conformance;
pub mod numeric;
#[cfg(feature = "serde_json")]
pub mod numeric_check;
pub mod types;
pub mod unique;
#[cfg(feature = "magnus")]
mod magnus;
#[cfg(feature = "pyo3")]
mod pyo3;
#[cfg(feature = "serde_json")]
mod serde_json;
#[cfg(feature = "magnus")]
pub use magnus::{
child as magnus_child, invalidate_members_cache as magnus_invalidate_members_cache,
is_object as magnus_is_object, probe_root as magnus_probe_root,
take_pending_error as magnus_take_pending_error, Magnus, PendingError,
PendingErrorScope as MagnusPendingErrorScope, RbNode,
};
#[cfg(feature = "pyo3")]
pub use pyo3::{probe_root, take_pending_error, PendingErrorScope, Pyo3};
#[cfg(feature = "serde_json")]
pub use serde_json::SerdeJson;
use std::borrow::Cow;
use ::serde_json::Value;
use crate::types::JsonType;
pub trait Json: Sized + Send + Sync + 'static {
type Node<'a>: Node<'a, Self>;
type PreparedKey: Send + Sync;
type StringBuffer: Default;
fn prepare_key(key: &str) -> Self::PreparedKey;
fn with_string_node<T>(
buffer: &mut Self::StringBuffer,
string: &str,
f: impl FnOnce(Self::Node<'_>) -> T,
) -> T;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NodeIdentity {
address: usize,
tag: u32,
}
impl NodeIdentity {
#[must_use]
pub fn new(address: usize) -> Self {
Self { address, tag: 0 }
}
#[must_use]
pub fn tagged(address: usize, tag: u32) -> Self {
Self { address, tag }
}
}
pub trait JsonNumber {
fn as_u64(&self) -> Option<u64>;
fn as_i64(&self) -> Option<i64>;
fn as_f64(&self) -> Option<f64>;
fn as_str(&self) -> Cow<'_, str>;
fn to_number(&self) -> Cow<'_, ::serde_json::Number>;
fn is_integer(&self) -> bool {
crate::types::number_is_integer(&self.to_number())
}
}
pub trait Node<'a, F: Json>: Clone {
type Object: Object<'a, F, Node = Self>;
type Array: Array<'a, F, Node = Self>;
type Number: JsonNumber;
fn as_object(&self) -> Option<Self::Object>;
fn as_array(&self) -> Option<Self::Array>;
fn as_string(&self) -> Option<Cow<'a, str>>;
fn as_number(&self) -> Option<Self::Number>;
fn as_boolean(&self) -> Option<bool>;
fn is_null(&self) -> bool;
fn is_number(&self) -> bool {
self.as_number().is_some()
}
fn is_string(&self) -> bool {
self.json_type() == JsonType::String
}
fn json_type(&self) -> JsonType;
fn string_length(&self) -> Option<u64> {
self.as_string().map(|string| string.chars().count() as u64)
}
fn equals_value(&self, expected: &Value) -> bool {
crate::cmp::equal(&self.to_value(), expected)
}
fn to_value(&self) -> Cow<'a, Value>;
fn identity(&self) -> Option<NodeIdentity>;
fn container_identity(&self) -> Option<NodeIdentity> {
if matches!(self.json_type(), JsonType::Object | JsonType::Array) {
self.identity()
} else {
None
}
}
}
pub trait Object<'a, F: Json> {
type Node: Node<'a, F>;
type MemberName: AsRef<str> + Into<Cow<'a, str>>;
type MembersIter: Iterator<Item = (Self::MemberName, Self::Node)>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn get(&self, key: &F::PreparedKey) -> Option<Self::Node>;
fn members(&self) -> Self::MembersIter;
}
#[allow(clippy::len_without_is_empty)]
pub trait Array<'a, F: Json> {
type Node: Node<'a, F>;
type ElementsIter: Iterator<Item = Self::Node>;
fn len(&self) -> usize;
fn elements(&self) -> Self::ElementsIter;
fn is_unique(&self) -> bool {
let values: Vec<Cow<'a, Value>> =
self.elements().map(|element| element.to_value()).collect();
crate::unique::is_unique(&values)
}
}