1use std::collections::HashMap;
4
5#[derive(Clone, PartialEq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[cfg_attr(feature = "serde", serde(untagged))]
9pub enum Value {
10 String(std::string::String),
11 Int(i64),
12 Float(f64),
13 Bool(bool),
14 Null,
15 Array(Vec<Value>),
16 Object(HashMap<std::string::String, Value>),
17 Secret(std::string::String),
19}
20
21impl std::fmt::Debug for Value {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 Value::String(s) => f.debug_tuple("String").field(s).finish(),
26 Value::Int(i) => f.debug_tuple("Int").field(i).finish(),
27 Value::Float(x) => f.debug_tuple("Float").field(x).finish(),
28 Value::Bool(b) => f.debug_tuple("Bool").field(b).finish(),
29 Value::Null => f.write_str("Null"),
30 Value::Array(a) => f.debug_tuple("Array").field(a).finish(),
31 Value::Object(o) => f.debug_tuple("Object").field(o).finish(),
32 Value::Secret(_) => f.write_str("Secret([SECRET])"),
33 }
34 }
35}
36
37impl Value {
38 pub fn as_str(&self) -> Option<&str> {
39 match self {
40 Value::String(s) | Value::Secret(s) => Some(s),
41 _ => None,
42 }
43 }
44
45 pub fn as_int(&self) -> Option<i64> {
46 match self {
47 Value::Int(n) => Some(*n),
48 _ => None,
49 }
50 }
51
52 pub fn as_float(&self) -> Option<f64> {
53 match self {
54 Value::Float(f) => Some(*f),
55 Value::Int(n) => Some(*n as f64),
56 _ => None,
57 }
58 }
59
60 pub fn as_bool(&self) -> Option<bool> {
61 match self {
62 Value::Bool(b) => Some(*b),
63 _ => None,
64 }
65 }
66
67 pub fn as_object(&self) -> Option<&HashMap<std::string::String, Value>> {
68 match self {
69 Value::Object(m) => Some(m),
70 _ => None,
71 }
72 }
73
74 pub fn as_object_mut(&mut self) -> Option<&mut HashMap<std::string::String, Value>> {
75 match self {
76 Value::Object(m) => Some(m),
77 _ => None,
78 }
79 }
80
81 pub fn as_array(&self) -> Option<&Vec<Value>> {
82 match self {
83 Value::Array(a) => Some(a),
84 _ => None,
85 }
86 }
87
88 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
89 match self {
90 Value::Array(a) => Some(a),
91 _ => None,
92 }
93 }
94
95 pub fn as_secret(&self) -> Option<&str> {
96 match self {
97 Value::Secret(s) => Some(s),
98 _ => None,
99 }
100 }
101
102 pub fn is_null(&self) -> bool {
103 matches!(self, Value::Null)
104 }
105
106 pub fn as_number_f64(&self) -> Option<f64> {
107 match self {
108 Value::Int(n) => Some(*n as f64),
109 Value::Float(f) => Some(*f),
110 _ => None,
111 }
112 }
113}
114
115impl std::fmt::Display for Value {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 match self {
118 Value::String(s) | Value::Secret(s) => write!(f, "{}", s),
119 Value::Int(n) => write!(f, "{}", n),
120 Value::Float(fl) => {
121 let s = fl.to_string();
122 if s.contains('.') { write!(f, "{}", s) } else { write!(f, "{}.0", s) }
123 }
124 Value::Bool(b) => write!(f, "{}", b),
125 Value::Null => write!(f, "null"),
126 Value::Array(arr) => {
127 write!(f, "[")?;
128 for (i, item) in arr.iter().enumerate() {
129 if i > 0 { write!(f, ", ")?; }
130 write!(f, "{}", item)?;
131 }
132 write!(f, "]")
133 }
134 Value::Object(_) => write!(f, "[Object]"),
135 }
136 }
137}
138
139impl std::ops::Index<&str> for Value {
140 type Output = Value;
141 fn index(&self, key: &str) -> &Value {
142 match self {
143 Value::Object(map) => map.get(key).expect("key not found"),
144 _ => panic!("not an object"),
145 }
146 }
147}
148
149#[derive(Debug, Clone, Copy, PartialEq, Eq)]
151pub enum Mode {
152 Static,
153 Active,
154}
155
156#[derive(Debug, Clone, PartialEq)]
158pub struct Meta {
159 pub markers: Vec<String>,
160 pub args: Vec<String>,
161 pub type_hint: Option<String>,
162 pub constraints: Option<Constraints>,
163}
164
165#[derive(Debug, Clone, Default, PartialEq)]
167pub struct Constraints {
168 pub min: Option<f64>,
169 pub max: Option<f64>,
170 pub type_name: Option<String>,
171 pub required: bool,
172 pub readonly: bool,
173 pub pattern: Option<String>,
174 pub enum_values: Option<Vec<String>>,
175}
176
177pub type MetaMap = HashMap<String, Meta>;
179
180#[derive(Debug, Clone)]
182pub struct IncludeDirective {
183 pub path: String,
184 pub alias: String,
185}
186
187#[derive(Debug, Clone)]
189pub struct UseDirective {
190 pub package: String,
192 pub alias: String,
194}
195
196#[derive(Debug)]
198pub struct ParseResult {
199 pub root: Value,
200 pub mode: Mode,
201 pub locked: bool,
202 pub tool: bool,
204 pub schema: bool,
206 pub llm: bool,
208 pub metadata: HashMap<String, MetaMap>,
211 pub includes: Vec<IncludeDirective>,
213 pub uses: Vec<UseDirective>,
215 pub truncated: bool,
222}
223
224#[derive(Debug, Clone, Default)]
226pub struct Options {
227 pub env: Option<HashMap<String, String>>,
228 pub region: Option<String>,
229 pub lang: Option<String>,
230 pub base_path: Option<String>,
231 pub max_include_depth: Option<usize>,
233 pub _include_depth: usize,
235 pub packages_path: Option<String>,
237 #[cfg(feature = "wasm")]
239 pub wasm_runtime: Option<std::sync::Arc<crate::wasm::WasmMarkerRuntime>>,
240}