1use 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; mod schema; mod validate; mod report; #[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 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
50pub 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
95pub 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}