use crate::ir::Node;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueKind {
Null,
Bool,
Number,
String,
Array,
Object,
}
pub trait ParseValue {
fn kind(&self) -> ValueKind;
fn as_coerced_str(&self) -> Option<String>;
fn as_array(&self) -> Option<Vec<Self>>
where
Self: Sized;
fn as_object(&self) -> Option<Vec<(String, Self)>>
where
Self: Sized;
fn as_integer(&self) -> Option<i64>;
fn describe_scalar(&self) -> String;
fn scalar_node(&self) -> Node;
fn is_object(&self) -> bool {
self.kind() == ValueKind::Object
}
fn is_null(&self) -> bool {
self.kind() == ValueKind::Null
}
fn single_key(&self) -> Option<(String, Self)>
where
Self: Sized,
{
let entries = self.as_object()?;
if entries.len() == 1 { entries.into_iter().next() } else { None }
}
fn describe(&self) -> String
where
Self: Sized,
{
describe_value(self)
}
}
pub fn describe_value<V: ParseValue>(val: &V) -> String {
match val.kind() {
ValueKind::Array => {
let items = val.as_array().unwrap_or_default();
let rendered: Vec<String> = items.iter().map(describe_value).collect();
format!("[{}]", rendered.join(", "))
}
ValueKind::Object => {
let entries = val.as_object().unwrap_or_default();
let rendered: Vec<String> =
entries.iter().map(|(k, v)| format!("'{}': {}", k, describe_value(v))).collect();
format!("{{{}}}", rendered.join(", "))
}
_ => val.describe_scalar(),
}
}