tawasuyu/llimphi
Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.
1//! Extractor de **paths con puntos** sobre `serde_json::Value` — lo que deja
2//! que el mapeo campo→JSON viva en un descriptor de texto. Gemelo del de
3//! `shared/foreign-platform`: deliberadamente mínimo (no es JSONPath).
4//!
5//! Sintaxis: segmentos separados por `.`; segmento numérico ⇒ índice de array;
6//! segmento de texto ⇒ clave de objeto; path vacío `""` ⇒ el propio valor.
7
8use serde_json::Value;
9
10/// Navega `root` siguiendo `path`. `None` si algún segmento no existe.
11pub fn get<'a>(root: &'a Value, path: &str) -> Option<&'a Value> {
12 if path.is_empty() {
13 return Some(root);
14 }
15 let mut cur = root;
16 for seg in path.split('.') {
17 cur = match cur {
18 Value::Object(map) => map.get(seg)?,
19 Value::Array(arr) => arr.get(seg.parse::<usize>().ok()?)?,
20 _ => return None,
21 };
22 }
23 Some(cur)
24}
25
26/// Extrae un `String` desde `path` (coerciona número a texto).
27pub fn get_string(root: &Value, path: &str) -> Option<String> {
28 match get(root, path)? {
29 Value::String(s) => Some(s.clone()),
30 Value::Number(n) => Some(n.to_string()),
31 _ => None,
32 }
33}
34
35/// El array que vive en `path`. `""` ⇒ la raíz debe ser un array.
36pub fn get_array<'a>(root: &'a Value, path: &str) -> Option<&'a [Value]> {
37 match get(root, path)? {
38 Value::Array(arr) => Some(arr.as_slice()),
39 _ => None,
40 }
41}