ordinary-utils 0.6.0-pre.1

Utils for Ordinary
Documentation
// taken from https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=54ac52636f7b7bbd839b9ca9ddf33612

use serde_json::{Map, Value as Json};
use valuable::{Listable, Mappable, Valuable, Value, Visit};

#[derive(Clone)]
pub struct JsonValuable(pub Json);

impl JsonValuable {
    fn new(json: &Json) -> &JsonValuable {
        // SAFETY: we can cast a &Json to a &JsonValuable because they
        // have the same layout (thanks to #[repr(transparent)]) and the
        // function signature ensures they have the same lifetime
        unsafe { &*(json as *const _ as *const JsonValuable) }
    }
}

#[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() {
                    Value::F64(num.as_f64().unwrap())
                } else if num.is_i64() {
                    Value::I64(num.as_i64().unwrap())
                } 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() {
                    num.as_f64().unwrap().visit(visit)
                } else if num.is_i64() {
                    num.as_i64().unwrap().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),
        }
    }
}

#[repr(transparent)]
pub struct JsonValuableMap(pub Map<String, Json>);

impl JsonValuableMap {
    fn new(map: &Map<String, Json>) -> &JsonValuableMap {
        // SAFETY: we can cast a &Map to a &JsonValuableMap because they
        // have the same layout (thanks to #[repr(transparent)]) and the
        // function signature ensures they have the same lifetime
        unsafe { &*(map as *const _ as *const JsonValuableMap) }
    }
}

#[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.iter() {
            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))
    }
}

#[repr(transparent)]
pub struct JsonValuableArray(pub Vec<Json>);

impl JsonValuableArray {
    fn new(arr: &Vec<Json>) -> &JsonValuableArray {
        // SAFETY: we can cast a &Vec to a &JsonValuableArray because they
        // have the same layout (thanks to #[repr(transparent)]) and the
        // function signature ensures they have the same lifetime
        unsafe { &*(arr as *const _ as *const JsonValuableArray) }
    }
}

#[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.iter() {
            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))
    }
}