use std::sync::{Arc, RwLock, Weak};
use super::errors::Result;
use super::flags::Flags;
#[derive(Debug, Clone)]
pub struct Metadata {
pub ref_type: String,
pub object_type: Option<String>,
pub optional: bool,
pub key: Option<NodeKey>,
pub flags: Flags,
pub flags_root: bool,
}
impl Default for Metadata {
fn default() -> Self {
Self {
ref_type: "Any".to_string(),
object_type: None,
optional: true,
key: None,
flags: Flags::new(),
flags_root: false,
}
}
}
impl Metadata {
pub fn new() -> Self {
Self::default()
}
pub fn with_key(mut self, key: NodeKey) -> Self {
self.key = Some(key);
self
}
pub fn with_ref_type(mut self, ref_type: impl Into<String>) -> Self {
self.ref_type = ref_type.into();
self
}
pub fn with_optional(mut self, optional: bool) -> Self {
self.optional = optional;
self
}
}
#[derive(Debug, Clone)]
pub struct ContainerMetadata {
pub base: Metadata,
pub key_type: Option<String>,
pub element_type: Option<String>,
}
impl Default for ContainerMetadata {
fn default() -> Self {
Self {
base: Metadata::default(),
key_type: None,
element_type: None,
}
}
}
impl ContainerMetadata {
pub fn new() -> Self {
Self::default()
}
pub fn with_key_type(mut self, key_type: impl Into<String>) -> Self {
self.key_type = Some(key_type.into());
self
}
pub fn with_element_type(mut self, element_type: impl Into<String>) -> Self {
self.element_type = Some(element_type.into());
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum NodeKey {
String(String),
Int(i64),
}
impl NodeKey {
pub fn as_str(&self) -> Option<&str> {
match self {
NodeKey::String(s) => Some(s),
NodeKey::Int(_) => None,
}
}
pub fn as_int(&self) -> Option<i64> {
match self {
NodeKey::Int(i) => Some(*i),
NodeKey::String(_) => None,
}
}
}
impl From<String> for NodeKey {
fn from(s: String) -> Self {
NodeKey::String(s)
}
}
impl From<&str> for NodeKey {
fn from(s: &str) -> Self {
NodeKey::String(s.to_string())
}
}
impl From<i64> for NodeKey {
fn from(i: i64) -> Self {
NodeKey::Int(i)
}
}
impl From<i32> for NodeKey {
fn from(i: i32) -> Self {
NodeKey::Int(i as i64)
}
}
impl From<usize> for NodeKey {
fn from(i: usize) -> Self {
NodeKey::Int(i as i64)
}
}
impl std::fmt::Display for NodeKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NodeKey::String(s) => write!(f, "{}", s),
NodeKey::Int(i) => write!(f, "{}", i),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum NodeContent {
Value(NodeValue),
None,
Missing,
Interpolation(String),
}
#[derive(Debug, Clone, PartialEq)]
pub enum NodeValue {
Bool(bool),
Int(i64),
Float(f64),
String(String),
Bytes(Vec<u8>),
}
impl NodeValue {
pub fn as_bool(&self) -> Option<bool> {
match self {
NodeValue::Bool(b) => Some(*b),
_ => None,
}
}
pub fn as_int(&self) -> Option<i64> {
match self {
NodeValue::Int(i) => Some(*i),
_ => None,
}
}
pub fn as_float(&self) -> Option<f64> {
match self {
NodeValue::Float(f) => Some(*f),
NodeValue::Int(i) => Some(*i as f64),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
NodeValue::String(s) => Some(s),
_ => None,
}
}
}
impl NodeContent {
pub fn is_none(&self) -> bool {
matches!(self, NodeContent::None)
}
pub fn is_missing(&self) -> bool {
matches!(self, NodeContent::Missing)
}
pub fn is_interpolation(&self) -> bool {
matches!(self, NodeContent::Interpolation(_))
}
pub fn is_special(&self) -> bool {
matches!(
self,
NodeContent::None | NodeContent::Missing | NodeContent::Interpolation(_)
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeType {
Value,
Dict,
List,
}
pub trait Node: Send + Sync + std::fmt::Debug {
fn node_type(&self) -> NodeType;
fn as_any(&self) -> &dyn std::any::Any;
fn metadata(&self) -> &Metadata;
fn metadata_mut(&mut self) -> &mut Metadata;
fn parent(&self) -> Option<Arc<RwLock<dyn Node>>>;
fn set_parent(&mut self, parent: Option<Weak<RwLock<dyn Node>>>);
fn get_flag(&self, name: &str) -> Option<bool> {
if let Some(value) = self.metadata().flags.get(name) {
return Some(value);
}
if self.metadata().flags_root {
return None;
}
if let Some(parent) = self.parent() {
if let Ok(parent) = parent.read() {
return parent.get_flag(name);
}
}
None
}
fn set_flag(&mut self, name: &str, value: Option<bool>) {
self.metadata_mut().flags.set(name, value);
}
fn key(&self) -> Option<&NodeKey> {
self.metadata().key.as_ref()
}
fn set_key(&mut self, key: Option<NodeKey>) {
self.metadata_mut().key = key;
}
fn is_optional(&self) -> bool {
self.metadata().optional
}
fn get_full_key(&self) -> String {
let mut parts = Vec::new();
if let Some(key) = self.key() {
parts.push(key.to_string());
}
let mut current_parent = self.parent();
while let Some(parent_arc) = current_parent {
if let Ok(parent) = parent_arc.read() {
if let Some(key) = parent.key() {
parts.push(key.to_string());
}
current_parent = parent.parent();
} else {
break;
}
}
parts.reverse();
parts.join(".")
}
fn is_readonly(&self) -> bool {
self.get_flag("readonly").unwrap_or(false)
}
fn is_struct(&self) -> bool {
self.get_flag("struct").unwrap_or(false)
}
fn content(&self) -> &NodeContent;
fn set_content(&mut self, content: NodeContent) -> Result<()>;
fn is_none(&self) -> bool {
self.content().is_none()
}
fn is_missing(&self) -> bool {
self.content().is_missing()
}
fn is_interpolation(&self) -> bool {
self.content().is_interpolation()
}
}
pub trait Box: Node {
fn re_parent(&mut self);
}
pub trait Container: Box {
fn container_metadata(&self) -> &ContainerMetadata;
fn container_metadata_mut(&mut self) -> &mut ContainerMetadata;
fn get_child(&self, key: &NodeKey) -> Option<Arc<RwLock<dyn Node>>>;
fn set_child(&mut self, key: NodeKey, value: Arc<RwLock<dyn Node>>) -> Result<()>;
fn delete_child(&mut self, key: &NodeKey) -> Result<()>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn keys(&self) -> Vec<NodeKey>;
fn validate_get(&self, key: &NodeKey) -> Result<()>;
fn validate_set(&self, key: &NodeKey, value: &dyn Node) -> Result<()>;
fn merge_with(&mut self, other: &dyn Container) -> Result<()>;
}