use std::{
fmt::Debug,
hash::{Hash, Hasher},
ops::Index,
};
use deepsize::DeepSizeOf;
use ordered_float::NotNan;
use super::{key_e::KeyE, slim_boxed_slice::SlimBoxedSlice, val_ref::ValRef, Map, ValE};
pub struct Val(pub(crate) f64);
impl Val {
#[inline]
pub fn str(s: &str) -> Val {
ValE::str(s).into()
}
#[inline]
pub fn string(s: String) -> Val {
ValE::string(s).into()
}
#[inline]
pub fn number(n: f64) -> Val {
ValE::Number(NotNan::new(n).unwrap()).into()
}
#[inline]
pub fn bool(b: bool) -> Val {
ValE::Bool(b).into()
}
#[inline]
pub fn null() -> Val {
ValE::Null.into()
}
#[inline]
pub fn array<V: Into<Val>, I: IntoIterator<Item = V>>(items: I) -> Val {
ValE::Array(SlimBoxedSlice::from_vec(
items.into_iter().map(Into::into).collect::<Vec<_>>(),
))
.into()
}
#[inline]
pub fn object<K: ToString, V: Into<Val>, I: IntoIterator<Item = (K, V)>>(items: I) -> Val {
ValE::Object(Map::new(
items
.into_iter()
.map(|(k, v)| (KeyE::string(k.to_string()).into(), v.into()))
.collect::<Vec<_>>(),
))
.into()
}
#[inline]
pub fn as_str(&self) -> Option<&str> {
self.direct_ref().as_str()
}
#[inline]
pub fn is_null(&self) -> bool {
matches!(self.direct_ref(), ValRef::Null)
}
#[inline]
pub fn get<S: AsRef<str>>(&self, key: S) -> Option<&Val> {
self.direct_ref().get(key)
}
}
impl PartialEq for Val {
fn eq(&self, other: &Self) -> bool {
self.direct_ref() == other.direct_ref()
}
}
impl Eq for Val {}
impl PartialOrd for Val {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.direct_ref().partial_cmp(&other.direct_ref())
}
}
impl Ord for Val {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.direct_ref().cmp(&other.direct_ref())
}
}
impl Debug for Val {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.direct_ref().fmt(f)
}
}
impl Clone for Val {
#[inline]
fn clone(&self) -> Self {
match self.direct_ref() {
ValRef::Null => ValE::Null,
ValRef::Bool(b) => ValE::Bool(b),
ValRef::Number(n) => ValE::Number(n),
ValRef::String(s) => ValE::str(s),
ValRef::Array(a) => ValE::Array(SlimBoxedSlice::from_vec(a.to_vec())),
ValRef::Object(o) => ValE::Object(Map::clone_from_ref(&o)),
}
.into()
}
}
impl Hash for Val {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.direct_ref().hash(state)
}
}
impl Index<usize> for Val {
type Output = Val;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
match self.direct_ref() {
ValRef::Array(a) => &a[index],
_ => panic!("Tried to index into Val that is not an array"),
}
}
}
impl DeepSizeOf for Val {
fn deep_size_of_children(&self, context: &mut deepsize::Context) -> usize {
let unsafe_clone = Val(self.0).into();
let size = match &unsafe_clone {
ValE::Bool(_) => 8,
ValE::Null => 8,
ValE::Number(_) => 8,
ValE::ShortString(_) => 8,
ValE::LongString(s) => s.deep_size_of_children(context),
ValE::Array(a) => a.deep_size_of_children(context),
ValE::Object(o) => o.deep_size_of_children(context),
};
std::mem::forget(unsafe_clone);
size
}
}