Skip to main content

synx_core/
value.rs

1//! SYNX value types, metadata, and options.
2
3use std::collections::HashMap;
4
5/// SYNX value types.
6#[derive(Debug, Clone, PartialEq)]
7pub enum Value {
8    String(std::string::String),
9    Int(i64),
10    Float(f64),
11    Bool(bool),
12    Null,
13    Array(Vec<Value>),
14    Object(HashMap<std::string::String, Value>),
15    /// Secret value — displays as [SECRET], real value accessible via as_secret()
16    Secret(std::string::String),
17}
18
19impl Value {
20    pub fn as_str(&self) -> Option<&str> {
21        match self {
22            Value::String(s) | Value::Secret(s) => Some(s),
23            _ => None,
24        }
25    }
26
27    pub fn as_int(&self) -> Option<i64> {
28        match self {
29            Value::Int(n) => Some(*n),
30            _ => None,
31        }
32    }
33
34    pub fn as_float(&self) -> Option<f64> {
35        match self {
36            Value::Float(f) => Some(*f),
37            Value::Int(n) => Some(*n as f64),
38            _ => None,
39        }
40    }
41
42    pub fn as_bool(&self) -> Option<bool> {
43        match self {
44            Value::Bool(b) => Some(*b),
45            _ => None,
46        }
47    }
48
49    pub fn as_object(&self) -> Option<&HashMap<std::string::String, Value>> {
50        match self {
51            Value::Object(m) => Some(m),
52            _ => None,
53        }
54    }
55
56    pub fn as_object_mut(&mut self) -> Option<&mut HashMap<std::string::String, Value>> {
57        match self {
58            Value::Object(m) => Some(m),
59            _ => None,
60        }
61    }
62
63    pub fn as_array(&self) -> Option<&Vec<Value>> {
64        match self {
65            Value::Array(a) => Some(a),
66            _ => None,
67        }
68    }
69
70    pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
71        match self {
72            Value::Array(a) => Some(a),
73            _ => None,
74        }
75    }
76
77    pub fn as_secret(&self) -> Option<&str> {
78        match self {
79            Value::Secret(s) => Some(s),
80            _ => None,
81        }
82    }
83
84    pub fn is_null(&self) -> bool {
85        matches!(self, Value::Null)
86    }
87
88    pub fn as_number_f64(&self) -> Option<f64> {
89        match self {
90            Value::Int(n) => Some(*n as f64),
91            Value::Float(f) => Some(*f),
92            _ => None,
93        }
94    }
95}
96
97impl std::fmt::Display for Value {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        match self {
100            Value::String(s) | Value::Secret(s) => write!(f, "{}", s),
101            Value::Int(n) => write!(f, "{}", n),
102            Value::Float(fl) => {
103                let s = fl.to_string();
104                if s.contains('.') { write!(f, "{}", s) } else { write!(f, "{}.0", s) }
105            }
106            Value::Bool(b) => write!(f, "{}", b),
107            Value::Null => write!(f, "null"),
108            Value::Array(arr) => {
109                write!(f, "[")?;
110                for (i, item) in arr.iter().enumerate() {
111                    if i > 0 { write!(f, ", ")?; }
112                    write!(f, "{}", item)?;
113                }
114                write!(f, "]")
115            }
116            Value::Object(_) => write!(f, "[Object]"),
117        }
118    }
119}
120
121impl std::ops::Index<&str> for Value {
122    type Output = Value;
123    fn index(&self, key: &str) -> &Value {
124        match self {
125            Value::Object(map) => map.get(key).expect("key not found"),
126            _ => panic!("not an object"),
127        }
128    }
129}
130
131/// File mode.
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub enum Mode {
134    Static,
135    Active,
136}
137
138/// Metadata for a single key (markers, args, constraints).
139#[derive(Debug, Clone, PartialEq)]
140pub struct Meta {
141    pub markers: Vec<String>,
142    pub args: Vec<String>,
143    pub type_hint: Option<String>,
144    pub constraints: Option<Constraints>,
145}
146
147/// Constraints from [min:3, max:30, required, type:int].
148#[derive(Debug, Clone, Default, PartialEq)]
149pub struct Constraints {
150    pub min: Option<f64>,
151    pub max: Option<f64>,
152    pub type_name: Option<String>,
153    pub required: bool,
154    pub readonly: bool,
155    pub pattern: Option<String>,
156    pub enum_values: Option<Vec<String>>,
157}
158
159/// Map of key → metadata for one object level.
160pub type MetaMap = HashMap<String, Meta>;
161
162/// Full parse result with metadata.
163#[derive(Debug)]
164pub struct ParseResult {
165    pub root: Value,
166    pub mode: Mode,
167    pub locked: bool,
168    /// Metadata for each nesting level, keyed by dot-path prefix.
169    /// "" = root level, "server" = server sub-object, etc.
170    pub metadata: HashMap<String, MetaMap>,
171}
172
173/// Options for active mode resolution.
174#[derive(Debug, Clone, Default)]
175pub struct Options {
176    pub env: Option<HashMap<String, String>>,
177    pub region: Option<String>,
178    pub base_path: Option<String>,
179}