use std::collections::HashSet;
use std::sync::Arc;
use indexmap::IndexMap;
use serde_json::json;
use crate::parser::{Entry, Expr, TypeExpr};
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CapturedScope {
pub values: IndexMap<String, Value>,
pub declared: HashSet<String>,
pub body_members: HashSet<String>,
pub module_identities: IndexMap<String, String>,
pub type_aliases: IndexMap<String, TypeExpr>,
pub type_namespace: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ObjectSource {
pub entries: Vec<Entry>,
pub scope: IndexMap<String, Value>,
pub(crate) scope_declared: HashSet<String>,
pub(crate) body_members: HashSet<String>,
pub is_open: bool,
pub type_name: Option<String>,
pub(crate) type_identity: Option<String>,
pub parent_type_names: Vec<String>,
pub(crate) parent_type_identities: Vec<String>,
pub(crate) scope_module_identities: IndexMap<String, String>,
pub(crate) scope_type_aliases: IndexMap<String, TypeExpr>,
pub(crate) entry_scopes: Vec<Option<Arc<CapturedScope>>>,
pub(crate) evaluated_properties: Vec<String>,
pub mapping_value_types: Vec<String>,
pub(crate) deprecated: IndexMap<String, Option<String>>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub enum Value {
#[default]
Null,
Bool(bool),
Int(i64),
Float(f64),
String(String),
Object(Arc<IndexMap<String, Value>>, Option<Arc<ObjectSource>>),
List(Vec<Value>),
Lambda(Vec<String>, Expr, Arc<IndexMap<String, Value>>),
}
impl Value {
pub fn to_json(&self) -> serde_json::Value {
match self {
Value::Null => serde_json::Value::Null,
Value::Bool(b) => json!(b),
Value::Int(n) => json!(n),
Value::Float(f) => json!(f),
Value::String(s) => json!(s),
Value::Object(map, _) => {
let mut obj = serde_json::Map::new();
for (k, v) in map.iter() {
obj.insert(k.clone(), v.to_json());
}
serde_json::Value::Object(obj)
}
Value::List(items) => {
serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
}
Value::Lambda(..) => json!("<lambda>"),
}
}
pub fn as_str(&self) -> Option<&str> {
if let Value::String(s) = self {
Some(s)
} else {
None
}
}
pub fn as_object_mut(&mut self) -> Option<&mut IndexMap<String, Value>> {
if let Value::Object(m, _) = self {
Some(Arc::make_mut(m))
} else {
None
}
}
pub fn merge(&mut self, other: Value) {
match (self, other) {
(Value::Object(base, _), Value::Object(overlay, _)) => {
let base_map = Arc::make_mut(base);
for (k, v) in overlay.iter() {
base_map.insert(k.clone(), v.clone());
}
}
(s, other) => *s = other,
}
}
}
impl From<serde_json::Value> for Value {
fn from(v: serde_json::Value) -> Self {
match v {
serde_json::Value::Null => Value::Null,
serde_json::Value::Bool(b) => Value::Bool(b),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Value::Int(i)
} else {
Value::Float(n.as_f64().unwrap_or(f64::NAN))
}
}
serde_json::Value::String(s) => Value::String(s),
serde_json::Value::Array(a) => Value::List(a.into_iter().map(Value::from).collect()),
serde_json::Value::Object(o) => {
let mut map = IndexMap::new();
for (k, v) in o {
map.insert(k, Value::from(v));
}
Value::Object(Arc::new(map), None)
}
}
}
}