1mod functions;
2mod generator;
3mod io;
4mod methods;
5mod structs;
6
7pub use functions::{
8 LambdaFunction, NativeFn, NativeFunction, NativeFuture, Parameter, ParameterKind, UserFunction,
9};
10pub use generator::{Generator, GeneratorMessage, StreamIterator};
11pub use io::{HttpResponse, ProcessResult};
12pub use structs::{StructField, StructInstance, StructType, TypeAnnotation};
13
14use std::fmt;
15use std::hash::{Hash, Hasher};
16use std::sync::Arc;
17
18use indexmap::{IndexMap, IndexSet};
19use tokio::sync::RwLock;
20
21use crate::error::{BlueprintError, Result};
22
23#[derive(Clone)]
24pub enum Value {
25 None,
26 Bool(bool),
27 Int(i64),
28 Float(f64),
29 String(Arc<String>),
30 List(Arc<RwLock<Vec<Value>>>),
31 Dict(Arc<RwLock<IndexMap<String, Value>>>),
32 Set(Arc<RwLock<IndexSet<Value>>>),
33 Tuple(Arc<Vec<Value>>),
34 Function(Arc<UserFunction>),
35 Lambda(Arc<LambdaFunction>),
36 NativeFunction(Arc<NativeFunction>),
37 Response(Arc<HttpResponse>),
38 ProcessResult(Arc<ProcessResult>),
39 Iterator(Arc<StreamIterator>),
40 Generator(Arc<Generator>),
41 StructType(Arc<StructType>),
42 StructInstance(Arc<StructInstance>),
43}
44
45impl fmt::Debug for Value {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 match self {
48 Value::None => write!(f, "None"),
49 Value::Bool(b) => write!(f, "Bool({b})"),
50 Value::Int(i) => write!(f, "Int({i})"),
51 Value::Float(fl) => write!(f, "Float({fl})"),
52 Value::String(s) => write!(f, "String({s:?})"),
53 Value::List(_) => write!(f, "List([...])"),
54 Value::Dict(_) => write!(f, "Dict({{...}})"),
55 Value::Set(_) => write!(f, "Set({{...}})"),
56 Value::Tuple(t) => write!(f, "Tuple({:?})", t.as_ref()),
57 Value::Function(func) => write!(f, "Function({})", func.name),
58 Value::Lambda(_) => write!(f, "Lambda"),
59 Value::NativeFunction(func) => write!(f, "NativeFunction({})", func.name),
60 Value::Response(r) => write!(f, "Response(status={})", r.status),
61 Value::ProcessResult(r) => write!(f, "ProcessResult(code={})", r.code),
62 Value::Iterator(_) => write!(f, "Iterator"),
63 Value::Generator(_) => write!(f, "Generator"),
64 Value::StructType(s) => write!(f, "StructType({})", s.name),
65 Value::StructInstance(s) => write!(f, "StructInstance({})", s.struct_type.name),
66 }
67 }
68}
69
70impl Value {
71 pub fn type_name(&self) -> &'static str {
72 match self {
73 Value::None => "NoneType",
74 Value::Bool(_) => "bool",
75 Value::Int(_) => "int",
76 Value::Float(_) => "float",
77 Value::String(_) => "string",
78 Value::List(_) => "list",
79 Value::Dict(_) => "dict",
80 Value::Set(_) => "set",
81 Value::Tuple(_) => "tuple",
82 Value::Function(_) => "function",
83 Value::Lambda(_) => "function",
84 Value::NativeFunction(_) => "builtin_function",
85 Value::Response(_) => "Response",
86 Value::ProcessResult(_) => "Result",
87 Value::Iterator(_) => "iterator",
88 Value::Generator(_) => "generator",
89 Value::StructType(_) => "type",
90 Value::StructInstance(_) => "struct",
91 }
92 }
93
94 pub fn is_truthy(&self) -> bool {
95 match self {
96 Value::None => false,
97 Value::Bool(b) => *b,
98 Value::Int(i) => *i != 0,
99 Value::Float(f) => *f != 0.0,
100 Value::String(s) => !s.is_empty(),
101 Value::List(l) => {
102 if let Ok(guard) = l.try_read() {
103 !guard.is_empty()
104 } else {
105 true
106 }
107 }
108 Value::Dict(d) => {
109 if let Ok(guard) = d.try_read() {
110 !guard.is_empty()
111 } else {
112 true
113 }
114 }
115 Value::Set(s) => {
116 if let Ok(guard) = s.try_read() {
117 !guard.is_empty()
118 } else {
119 true
120 }
121 }
122 Value::Tuple(t) => !t.is_empty(),
123 _ => true,
124 }
125 }
126
127 pub async fn is_truthy_async(&self) -> bool {
128 match self {
129 Value::None => false,
130 Value::Bool(b) => *b,
131 Value::Int(i) => *i != 0,
132 Value::Float(f) => *f != 0.0,
133 Value::String(s) => !s.is_empty(),
134 Value::List(l) => {
135 let guard = l.read().await;
136 !guard.is_empty()
137 }
138 Value::Dict(d) => {
139 let guard = d.read().await;
140 !guard.is_empty()
141 }
142 Value::Set(s) => {
143 let guard = s.read().await;
144 !guard.is_empty()
145 }
146 Value::Tuple(t) => !t.is_empty(),
147 _ => true,
148 }
149 }
150
151 pub fn is_none(&self) -> bool {
152 matches!(self, Value::None)
153 }
154
155 pub async fn deep_copy(&self) -> Value {
156 match self {
157 Value::List(l) => {
158 let items = l.read().await;
159 let mut copied = Vec::with_capacity(items.len());
160 for item in items.iter() {
161 copied.push(Box::pin(item.deep_copy()).await);
162 }
163 Value::List(Arc::new(RwLock::new(copied)))
164 }
165 Value::Dict(d) => {
166 let map = d.read().await;
167 let mut copied = IndexMap::with_capacity(map.len());
168 for (k, v) in map.iter() {
169 copied.insert(k.clone(), Box::pin(v.deep_copy()).await);
170 }
171 Value::Dict(Arc::new(RwLock::new(copied)))
172 }
173 Value::Tuple(t) => {
174 let mut copied = Vec::with_capacity(t.len());
175 for item in t.iter() {
176 copied.push(Box::pin(item.deep_copy()).await);
177 }
178 Value::Tuple(Arc::new(copied))
179 }
180 other => other.clone(),
181 }
182 }
183
184 pub fn as_bool(&self) -> Result<bool> {
185 match self {
186 Value::Bool(b) => Ok(*b),
187 _ => Err(BlueprintError::TypeError {
188 expected: "bool".into(),
189 actual: self.type_name().into(),
190 }),
191 }
192 }
193
194 pub fn as_int(&self) -> Result<i64> {
195 match self {
196 Value::Int(i) => Ok(*i),
197 _ => Err(BlueprintError::TypeError {
198 expected: "int".into(),
199 actual: self.type_name().into(),
200 }),
201 }
202 }
203
204 pub fn as_float(&self) -> Result<f64> {
205 match self {
206 Value::Float(f) => Ok(*f),
207 Value::Int(i) => Ok(*i as f64),
208 _ => Err(BlueprintError::TypeError {
209 expected: "float".into(),
210 actual: self.type_name().into(),
211 }),
212 }
213 }
214
215 pub fn as_string(&self) -> Result<String> {
216 match self {
217 Value::String(s) => Ok(s.as_ref().clone()),
218 _ => Err(BlueprintError::TypeError {
219 expected: "string".into(),
220 actual: self.type_name().into(),
221 }),
222 }
223 }
224
225 pub fn as_str(&self) -> Result<&str> {
226 match self {
227 Value::String(s) => Ok(s.as_ref()),
228 _ => Err(BlueprintError::TypeError {
229 expected: "string".into(),
230 actual: self.type_name().into(),
231 }),
232 }
233 }
234
235 pub fn to_display_string(&self) -> String {
236 match self {
237 Value::None => "None".into(),
238 Value::Bool(b) => if *b { "True" } else { "False" }.into(),
239 Value::Int(i) => i.to_string(),
240 Value::Float(f) => {
241 if f.fract() == 0.0 {
242 format!("{f:.1}")
243 } else {
244 f.to_string()
245 }
246 }
247 Value::String(s) => s.as_ref().clone(),
248 Value::List(l) => match l.try_read() {
249 Ok(guard) => {
250 let items: Vec<String> = guard.iter().map(|v| v.repr()).collect();
251 format!("[{}]", items.join(", "))
252 }
253 Err(_) => "[<locked>]".into(),
254 },
255 Value::Dict(d) => match d.try_read() {
256 Ok(guard) => {
257 let items: Vec<String> = guard
258 .iter()
259 .map(|(k, v)| format!("{:?}: {}", k, v.repr()))
260 .collect();
261 format!("{{{}}}", items.join(", "))
262 }
263 Err(_) => "{<locked>}".into(),
264 },
265 Value::Set(s) => match s.try_read() {
266 Ok(guard) => {
267 let items: Vec<String> = guard.iter().map(|v| v.repr()).collect();
268 format!("{{{}}}", items.join(", "))
269 }
270 Err(_) => "{<locked>}".into(),
271 },
272 Value::Tuple(t) => {
273 let items: Vec<String> = t.iter().map(|v| v.repr()).collect();
274 if t.len() == 1 {
275 format!("({},)", items[0])
276 } else {
277 format!("({})", items.join(", "))
278 }
279 }
280 Value::Function(f) => format!("<function {}>", f.name),
281 Value::Lambda(_) => "<lambda>".into(),
282 Value::NativeFunction(f) => format!("<builtin_function {}>", f.name),
283 Value::Response(r) => format!("<Response status={}>", r.status),
284 Value::ProcessResult(r) => format!("<Result code={}>", r.code),
285 Value::Iterator(_) => "<iterator>".into(),
286 Value::Generator(_) => "<generator>".into(),
287 Value::StructType(s) => format!("<type {}>", s.name),
288 Value::StructInstance(s) => s.to_display_string(),
289 }
290 }
291
292 pub fn repr(&self) -> String {
293 match self {
294 Value::String(s) => format!("{:?}", s.as_ref()),
295 _ => self.to_display_string(),
296 }
297 }
298
299 pub fn get_attr(&self, name: &str) -> Option<Value> {
300 match self {
301 Value::Response(r) => r.get_attr(name),
302 Value::ProcessResult(r) => r.get_attr(name),
303 Value::String(s) => methods::get_string_method(s.clone(), name),
304 Value::List(l) => methods::get_list_method(l.clone(), name),
305 Value::Dict(d) => methods::get_dict_method(d.clone(), name),
306 Value::Set(s) => methods::get_set_method(s.clone(), name),
307 Value::Iterator(it) => it.get_attr(name),
308 Value::StructInstance(s) => s.get_field(name),
309 _ => None,
310 }
311 }
312
313 pub fn has_attr(&self, name: &str) -> bool {
314 self.get_attr(name).is_some()
315 }
316}
317
318impl PartialEq for Value {
319 fn eq(&self, other: &Self) -> bool {
320 match (self, other) {
321 (Value::None, Value::None) => true,
322 (Value::Bool(a), Value::Bool(b)) => a == b,
323 (Value::Int(a), Value::Int(b)) => a == b,
324 (Value::Float(a), Value::Float(b)) => a == b,
325 (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
326 (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
327 (Value::String(a), Value::String(b)) => a == b,
328 (Value::Tuple(a), Value::Tuple(b)) => a == b,
329 _ => false,
330 }
331 }
332}
333
334impl Eq for Value {}
335
336impl Hash for Value {
337 fn hash<H: Hasher>(&self, state: &mut H) {
338 std::mem::discriminant(self).hash(state);
339 match self {
340 Value::None => {}
341 Value::Bool(b) => b.hash(state),
342 Value::Int(i) => i.hash(state),
343 Value::Float(f) => f.to_bits().hash(state),
344 Value::String(s) => s.hash(state),
345 Value::Tuple(t) => t.hash(state),
346 _ => {}
347 }
348 }
349}