use ref_cast::RefCast;
use serde_json::{Map, Value as Json};
use valuable::{Listable, Mappable, Valuable, Value, Visit};
#[derive(RefCast)]
#[repr(transparent)]
pub struct JsonValuable(pub Json);
impl JsonValuable {
fn new(json: &Json) -> &JsonValuable {
JsonValuable::ref_cast(json)
}
}
#[cfg(tracing_unstable)]
impl Valuable for JsonValuable {
fn as_value(&self) -> Value<'_> {
match self.0 {
Json::Array(ref array) => JsonValuableArray::new(array).as_value(),
Json::Bool(ref value) => value.as_value(),
Json::Number(ref num) => {
if num.is_f64()
&& let Some(num) = num.as_f64()
{
Value::F64(num)
} else if num.is_i64()
&& let Some(num) = num.as_i64()
{
Value::I64(num)
} else {
unreachable!()
}
}
Json::Null => Value::Unit,
Json::String(ref s) => s.as_value(),
Json::Object(ref object) => JsonValuableMap::new(object).as_value(),
}
}
fn visit(&self, visit: &mut dyn Visit) {
match self.0 {
Json::Array(ref array) => JsonValuableArray::new(array).visit(visit),
Json::Bool(ref value) => value.visit(visit),
Json::Number(ref num) => {
if num.is_f64()
&& let Some(num) = num.as_f64()
{
num.visit(visit);
} else if num.is_i64()
&& let Some(num) = num.as_i64()
{
num.visit(visit);
} else {
unreachable!()
}
}
Json::Null => Value::Unit.visit(visit),
Json::String(ref s) => s.visit(visit),
Json::Object(ref object) => JsonValuableMap::new(object).visit(visit),
}
}
}
#[derive(RefCast)]
#[repr(transparent)]
pub struct JsonValuableMap(pub Map<String, Json>);
impl JsonValuableMap {
fn new(map: &Map<String, Json>) -> &JsonValuableMap {
JsonValuableMap::ref_cast(map)
}
}
#[cfg(tracing_unstable)]
impl Valuable for JsonValuableMap {
fn as_value(&self) -> Value<'_> {
Value::Mappable(self)
}
fn visit(&self, visit: &mut dyn Visit) {
for (k, v) in &self.0 {
visit.visit_entry(k.as_value(), JsonValuable::new(v).as_value());
}
}
}
#[cfg(tracing_unstable)]
impl Mappable for JsonValuableMap {
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.0.len();
(len, Some(len))
}
}
#[derive(RefCast)]
#[repr(transparent)]
pub struct JsonValuableArray(pub Vec<Json>);
impl JsonValuableArray {
fn new(arr: &Vec<Json>) -> &JsonValuableArray {
JsonValuableArray::ref_cast(arr)
}
}
#[cfg(tracing_unstable)]
impl Valuable for JsonValuableArray {
fn as_value(&self) -> Value<'_> {
Value::Listable(self)
}
fn visit(&self, visit: &mut dyn Visit) {
for v in &self.0 {
visit.visit_value(JsonValuable::new(v).as_value());
}
}
}
#[cfg(tracing_unstable)]
impl Listable for JsonValuableArray {
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.0.len();
(len, Some(len))
}
}