Skip to main content

Mountain/Track/Effect/CreateEffectForRequest/Utilities/
Params.rs

1//! Positional and named scalar extractors for `Parameters: Value` arguments
2//! in `CreateEffectForRequest` domain handlers. `Parameters` is a single
3//! `serde_json::Value` that may be a JSON array (positional) or object
4//! (named). The `str_obj_or_pos` helper handles the 7 sites that accept both
5//! shapes.
6
7use serde_json::{Value, json};
8
9pub fn str_at(p:&Value, n:usize) -> &str { p.get(n).and_then(Value::as_str).unwrap_or("") }
10
11pub fn string_at(p:&Value, n:usize) -> String { str_at(p, n).to_string() }
12
13pub fn string_at_or(p:&Value, n:usize, default:&str) -> String {
14	p.get(n).and_then(Value::as_str).unwrap_or(default).to_string()
15}
16
17pub fn val_at(p:&Value, n:usize) -> Value { p.get(n).cloned().unwrap_or(Value::Null) }
18
19pub fn u64_at(p:&Value, n:usize) -> u64 { p.get(n).and_then(Value::as_u64).unwrap_or(0) }
20
21pub fn bool_at(p:&Value, n:usize) -> bool { p.get(n).and_then(Value::as_bool).unwrap_or(false) }
22
23pub fn bool_at_true(p:&Value, n:usize) -> bool { p.get(n).and_then(Value::as_bool).unwrap_or(true) }
24
25pub fn i64_at(p:&Value, n:usize) -> i64 { p.get(n).and_then(Value::as_i64).unwrap_or(0) }
26
27pub fn i64_at_or(p:&Value, n:usize, default:i64) -> i64 { p.get(n).and_then(Value::as_i64).unwrap_or(default) }
28
29pub fn u64_at_or(p:&Value, n:usize, default:u64) -> u64 { p.get(n).and_then(Value::as_u64).unwrap_or(default) }
30
31pub fn obj_str<'a>(p:&'a Value, key:&str) -> &'a str { p.get(key).and_then(Value::as_str).unwrap_or("") }
32
33pub fn obj_val(p:&Value, key:&str) -> Value { p.get(key).cloned().unwrap_or(Value::Null) }
34
35pub fn obj_bool(p:&Value, key:&str) -> bool { p.get(key).and_then(Value::as_bool).unwrap_or(false) }
36
37pub fn obj_f64(p:&Value, key:&str) -> Option<f64> { p.get(key).and_then(Value::as_f64) }
38
39pub fn str_obj_or_pos<'a>(p:&'a Value, key:&str, n:usize) -> &'a str {
40	if let Some(obj) = p.as_object() {
41		obj.get(key).and_then(Value::as_str).unwrap_or("")
42	} else {
43		p.get(n).and_then(Value::as_str).unwrap_or("")
44	}
45}
46
47/// Unwrap one level of outer array: `[payload]` → `payload`, else identity.
48/// Handles callers that always wrap in an array vs those that send the value
49/// directly.
50pub fn array_unwrap(p:Value) -> Value { if p.is_array() { p.get(0).cloned().unwrap_or_default() } else { p } }
51
52/// Extract a URI parameter that may arrive as `[uri]`, `{uri:…}`, or bare.
53pub fn uri_from_params(p:Value) -> Value {
54	if p.is_array() {
55		p.get(0).cloned().unwrap_or_default()
56	} else {
57		p.get("uri").cloned().unwrap_or(p)
58	}
59}
60
61/// Ensure the value is a JSON array; wraps non-arrays in `[value]`.
62pub fn ensure_array(p:Value) -> Value { if p.is_array() { p } else { json!([p]) } }
63
64/// Strip a leading `file://` or `file:///` scheme. Handles the
65/// `file://localhost/...` form by removing the host segment.
66pub fn strip_file_uri(input:&str) -> &str {
67	if let Some(rest) = input.strip_prefix("file://") {
68		if rest.starts_with('/') {
69			return rest;
70		}
71		if let Some(idx) = rest.find('/') {
72			return &rest[idx..];
73		}
74	}
75	input
76}