Skip to main content

mumujson/
lib.rs

1// FILE: json/src/lib.rs
2
3use std::ffi::c_void;
4
5use indexmap::IndexMap;
6use mumu::parser::interpreter::Interpreter;
7use mumu::parser::types::Value;
8use serde_json::{Map as JsonMap, Value as JsonVal};
9
10mod codec;     // json:encode / json:decode
11mod schema;    // json:schema (schema-based validation)
12mod validate;  // json:validate  (returns Bool)
13mod report;    // json:report    (returns Bool | StrArray)
14
15/* ───────────────────────── Plugin entry-point ─────────────────────────── */
16#[export_name = "Cargo_lock"]
17pub unsafe extern "C" fn cargo_lock(
18    interp_ptr: *mut c_void,
19    extra_str: *const c_void,
20) -> i32 {
21    if interp_ptr.is_null() {
22        eprintln!("[json plugin] null interpreter pointer");
23        return 1;
24    }
25    let interpreter = &mut *(interp_ptr as *mut Interpreter);
26
27    if interpreter.is_verbose() {
28        if !extra_str.is_null() {
29            use std::ffi::CStr;
30            let extra = CStr::from_ptr(extra_str as *const i8).to_string_lossy();
31            eprintln!("[json plugin] loading (extra = \"{extra}\")");
32        } else {
33            eprintln!("[json plugin] loading");
34        }
35    }
36
37    /* register every public symbol */
38    codec::register_json_decode(interpreter);
39    codec::register_json_encode(interpreter);
40    schema::register_json_schema(interpreter);
41    validate::register_json_validate(interpreter);
42    report::register_json_report(interpreter);
43
44    if interpreter.is_verbose() {
45        eprintln!("[json plugin] ready");
46    }
47    0
48}
49
50/* ═══════════════════ shared helpers (used across modules) ═══════════════ */
51/// serde_json → mumu::Value
52pub fn jsonval_to_mumu(jv: &JsonVal) -> Value {
53    match jv {
54        JsonVal::Null => Value::Placeholder,
55        JsonVal::Bool(b) => Value::Bool(*b),
56        JsonVal::Number(n) => {
57            if let Some(i) = n.as_i64() {
58                if (i32::MIN as i64..=i32::MAX as i64).contains(&i) {
59                    Value::Int(i as i32)
60                } else {
61                    Value::Long(i)
62                }
63            } else if let Some(f) = n.as_f64() {
64                Value::Float(f)
65            } else {
66                Value::Placeholder
67            }
68        }
69        JsonVal::String(s) => Value::SingleString(s.clone()),
70        JsonVal::Array(arr) => {
71            if arr.iter().all(|v| v.is_i64()) {
72                Value::IntArray(arr.iter().map(|v| v.as_i64().unwrap() as i32).collect())
73            } else if arr.iter().all(|v| v.is_f64()) {
74                Value::FloatArray(arr.iter().map(|v| v.as_f64().unwrap()).collect())
75            } else if arr.iter().all(|v| v.is_string()) {
76                Value::StrArray(arr.iter().map(|v| v.as_str().unwrap().to_string()).collect())
77            } else {
78                let mut map = IndexMap::new();
79                for (i, sub) in arr.iter().enumerate() {
80                    map.insert(i.to_string(), jsonval_to_mumu(sub));
81                }
82                Value::KeyedArray(map)
83            }
84        }
85        JsonVal::Object(obj) => {
86            let mut map = IndexMap::new();
87            for (k, v) in obj {
88                map.insert(k.clone(), jsonval_to_mumu(v));
89            }
90            Value::KeyedArray(map)
91        }
92    }
93}
94
95/// mumu::Value → serde_json
96pub fn mumu_value_to_json(v: &Value) -> JsonVal {
97    match v {
98        Value::Placeholder => JsonVal::Null,
99        Value::Bool(b) => JsonVal::Bool(*b),
100        Value::Int(i) => JsonVal::Number((*i).into()),
101        Value::Long(l) => JsonVal::Number((*l).into()),
102        Value::Float(f) => JsonVal::Number(
103            serde_json::Number::from_f64(*f).unwrap_or_else(|| 0.into())
104        ),
105        Value::SingleString(s) => JsonVal::String(s.clone()),
106        Value::IntArray(xs) => JsonVal::Array(
107            xs.iter().map(|n| JsonVal::Number((*n).into())).collect()
108        ),
109        Value::FloatArray(fs) => JsonVal::Array(
110            fs.iter()
111                .map(|f| JsonVal::Number(
112                    serde_json::Number::from_f64(*f).unwrap_or_else(|| 0.into())
113                ))
114                .collect(),
115        ),
116        Value::BoolArray(bs) => JsonVal::Array(bs.iter().map(|b| JsonVal::Bool(*b)).collect()),
117        Value::StrArray(ss) => JsonVal::Array(ss.iter().map(|s| JsonVal::String(s.clone())).collect()),
118        Value::Int2DArray(rows) => JsonVal::Array(rows.iter().map(|r|
119            JsonVal::Array(r.iter().map(|n| JsonVal::Number((*n).into())).collect())
120        ).collect()),
121        Value::Float2DArray(rows) => JsonVal::Array(rows.iter().map(|r|
122            JsonVal::Array(r.iter().map(|f|
123                JsonVal::Number(serde_json::Number::from_f64(*f).unwrap_or_else(|| 0.into()))
124            ).collect())
125        ).collect()),
126        Value::KeyedArray(map) => {
127            let mut obj = JsonMap::new();
128            for (k, v) in map {
129                obj.insert(k.clone(), mumu_value_to_json(v));
130            }
131            JsonVal::Object(obj)
132        }
133        _ => JsonVal::Null,
134    }
135}