1use std::ffi::c_void;
5
6use indexmap::IndexMap;
7use mumu::parser::interpreter::Interpreter;
8use mumu::parser::types::Value;
9use serde_json::{Map as JsonMap, Number as JsonNumber, Value as JsonVal};
10
11mod codec; mod validate; mod report; #[cfg(not(target_arch = "wasm32"))]
17mod schema;
18
19pub fn register_all(interpreter: &mut Interpreter) {
23 codec::register_json_decode(interpreter);
24 codec::register_json_encode(interpreter);
25 validate::register_json_validate(interpreter);
26 report::register_json_report(interpreter);
27
28 #[cfg(not(target_arch = "wasm32"))]
29 {
30 schema::register_json_schema(interpreter);
31 }
32}
33
34#[cfg(not(target_arch = "wasm32"))]
36#[no_mangle]
37pub unsafe extern "C" fn Cargo_lock(
38 interp_ptr: *mut c_void,
39 extra_str: *const c_void,
40) -> i32 {
41 use std::ffi::CStr;
42
43 if interp_ptr.is_null() {
44 eprintln!("[json plugin] null interpreter pointer");
45 return 1;
46 }
47 let interpreter = &mut *(interp_ptr as *mut Interpreter);
48
49 if interpreter.is_verbose() {
50 if !extra_str.is_null() {
51 let extra = CStr::from_ptr(extra_str as *const i8).to_string_lossy();
52 eprintln!("[json plugin] loading (extra = \"{extra}\")");
53 } else {
54 eprintln!("[json plugin] loading");
55 }
56 }
57
58 register_all(interpreter);
59
60 if interpreter.is_verbose() {
61 eprintln!("[json plugin] ready");
62 }
63 0
64}
65
66pub fn jsonval_to_mumu(jv: &JsonVal) -> Value {
69 match jv {
70 JsonVal::Null => Value::Placeholder,
71 JsonVal::Bool(b) => Value::Bool(*b),
72 JsonVal::Number(n) => {
73 if let Some(i) = n.as_i64() {
74 if (i32::MIN as i64..=i32::MAX as i64).contains(&i) {
75 Value::Int(i as i32)
76 } else {
77 Value::Long(i)
78 }
79 } else if let Some(f) = n.as_f64() {
80 Value::Float(f)
81 } else {
82 Value::Placeholder
83 }
84 }
85 JsonVal::String(s) => Value::SingleString(s.clone()),
86 JsonVal::Array(arr) => {
87 if arr.iter().all(|v| v.is_i64()) {
88 Value::IntArray(arr.iter().map(|v| v.as_i64().unwrap() as i32).collect())
89 } else if arr.iter().all(|v| v.is_f64()) {
90 Value::FloatArray(arr.iter().map(|v| v.as_f64().unwrap()).collect())
91 } else if arr.iter().all(|v| v.is_string()) {
92 Value::StrArray(arr.iter().map(|v| v.as_str().unwrap().to_string()).collect())
93 } else {
94 let mut items = Vec::with_capacity(arr.len());
95 for sub in arr {
96 items.push(jsonval_to_mumu(sub));
97 }
98 Value::MixedArray(items)
99 }
100 }
101 JsonVal::Object(obj) => {
102 let mut map = IndexMap::new();
103 for (k, v) in obj {
104 map.insert(k.clone(), jsonval_to_mumu(v));
105 }
106 Value::KeyedArray(map)
107 }
108 }
109}
110
111pub fn mumu_value_to_json(v: &Value) -> JsonVal {
113 match v {
114 Value::Placeholder => JsonVal::Null,
115 Value::Bool(b) => JsonVal::Bool(*b),
116 Value::Int(i) => JsonVal::Number((*i).into()),
117 Value::Long(l) => JsonVal::Number((*l).into()),
118 Value::Float(f) => {
119 if let Some(n) = JsonNumber::from_f64(*f) {
120 JsonVal::Number(n)
121 } else {
122 JsonVal::Null
123 }
124 }
125 Value::SingleString(s) => JsonVal::String(s.clone()),
126 Value::IntArray(xs) => {
127 JsonVal::Array(xs.iter().map(|n| JsonVal::Number((*n).into())).collect())
128 }
129 Value::FloatArray(fs) => {
130 JsonVal::Array(
131 fs.iter()
132 .map(|f| {
133 if let Some(n) = JsonNumber::from_f64(*f) {
134 JsonVal::Number(n)
135 } else {
136 JsonVal::Null
137 }
138 })
139 .collect(),
140 )
141 }
142 Value::BoolArray(bs) => JsonVal::Array(bs.iter().map(|b| JsonVal::Bool(*b)).collect()),
143 Value::StrArray(ss) => {
144 JsonVal::Array(ss.iter().map(|s| JsonVal::String(s.clone())).collect())
145 }
146 Value::Int2DArray(rows) => JsonVal::Array(
147 rows.iter()
148 .map(|r| {
149 JsonVal::Array(
150 r.iter()
151 .map(|n| JsonVal::Number((*n).into()))
152 .collect::<Vec<_>>(),
153 )
154 })
155 .collect(),
156 ),
157 Value::Float2DArray(rows) => JsonVal::Array(
158 rows.iter()
159 .map(|r| {
160 JsonVal::Array(
161 r.iter()
162 .map(|f| {
163 if let Some(n) = JsonNumber::from_f64(*f) {
164 JsonVal::Number(n)
165 } else {
166 JsonVal::Null
167 }
168 })
169 .collect::<Vec<_>>(),
170 )
171 })
172 .collect(),
173 ),
174 Value::KeyedArray(map) => {
175 let mut obj = JsonMap::new();
176 for (k, v) in map {
177 obj.insert(k.clone(), mumu_value_to_json(v));
178 }
179 JsonVal::Object(obj)
180 }
181 Value::MixedArray(items) => {
182 JsonVal::Array(items.iter().map(|it| mumu_value_to_json(it)).collect())
183 }
184 _ => JsonVal::Null,
185 }
186}