- SSOT using profiles (aliases/packages via nyash.toml), AST prelude merge - Parser/member guards; Builder pin/PHI and instance→function rewrite (dev on) - VM refactors (handlers split) and JSON roundtrip/nested stabilization - CURRENT_TASK.md updated with scope and acceptance criteria Notes: dev-only guards remain togglable via env; no default behavior changes for prod.
169 lines
6.8 KiB
Rust
169 lines
6.8 KiB
Rust
//! JsonDocBox implementation
|
|
|
|
use crate::constants::*;
|
|
use crate::ffi;
|
|
use crate::provider::{
|
|
provider_kind, provider_parse, DocInst, NodeRep, ProviderKind, DOCS, NEXT_ID, NODES,
|
|
};
|
|
use crate::tlv_helpers::*;
|
|
use serde_json::Value;
|
|
use std::ffi::{CStr, CString};
|
|
use std::os::raw::{c_char, c_void};
|
|
use std::sync::{atomic::Ordering, Arc};
|
|
|
|
pub extern "C" fn jsondoc_resolve(name: *const c_char) -> u32 {
|
|
if name.is_null() {
|
|
return 0;
|
|
}
|
|
let s = unsafe { CStr::from_ptr(name) }.to_string_lossy();
|
|
match s.as_ref() {
|
|
"birth" => JD_BIRTH,
|
|
"parse" => JD_PARSE,
|
|
"root" => JD_ROOT,
|
|
"error" => JD_ERROR,
|
|
_ => 0,
|
|
}
|
|
}
|
|
|
|
pub extern "C" fn jsondoc_invoke_id(
|
|
instance_id: u32,
|
|
method_id: u32,
|
|
args: *const u8,
|
|
args_len: usize,
|
|
result: *mut u8,
|
|
result_len: *mut usize,
|
|
) -> i32 {
|
|
unsafe {
|
|
match method_id {
|
|
JD_BIRTH => {
|
|
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
|
if let Ok(mut m) = DOCS.lock() {
|
|
m.insert(id, DocInst::new());
|
|
} else {
|
|
return E_PLUGIN;
|
|
}
|
|
return write_u32(id, result, result_len);
|
|
}
|
|
JD_PARSE => {
|
|
let text = match read_arg_string(args, args_len, 0) {
|
|
Some(s) => s,
|
|
None => return E_ARGS,
|
|
};
|
|
if let Ok(mut m) = DOCS.lock() {
|
|
if let Some(doc) = m.get_mut(&instance_id) {
|
|
match provider_kind() {
|
|
ProviderKind::Serde => {
|
|
match provider_parse(&text) {
|
|
Ok(v) => {
|
|
doc.root = Some(Arc::new(v));
|
|
doc.doc_ptr = None;
|
|
doc.last_err = None;
|
|
}
|
|
Err(e) => {
|
|
doc.root = None;
|
|
doc.doc_ptr = None;
|
|
doc.last_err = Some(e.to_string());
|
|
}
|
|
}
|
|
return write_tlv_void(result, result_len);
|
|
}
|
|
ProviderKind::Yyjson => {
|
|
let c = CString::new(text.as_bytes()).unwrap_or_default();
|
|
let mut ec: i32 = -1;
|
|
let p = ffi::nyjson_parse_doc(
|
|
c.as_ptr(),
|
|
text.len(),
|
|
&mut ec as *mut i32,
|
|
);
|
|
if p.is_null() {
|
|
doc.root = None;
|
|
doc.doc_ptr = None;
|
|
doc.last_err = Some(format!("E{}", ec));
|
|
} else {
|
|
doc.root = None;
|
|
doc.doc_ptr = Some(p as usize);
|
|
doc.last_err = None;
|
|
}
|
|
return write_tlv_void(result, result_len);
|
|
}
|
|
}
|
|
} else {
|
|
return E_HANDLE;
|
|
}
|
|
} else {
|
|
return E_PLUGIN;
|
|
}
|
|
}
|
|
JD_ROOT => {
|
|
if let Ok(m) = DOCS.lock() {
|
|
if let Some(doc) = m.get(&instance_id) {
|
|
match provider_kind() {
|
|
ProviderKind::Serde => {
|
|
if let Some(root_arc) = doc.root.as_ref().map(|r| Arc::clone(r)) {
|
|
let node_id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
|
if let Ok(mut nn) = NODES.lock() {
|
|
nn.insert(node_id, NodeRep::Serde(root_arc));
|
|
}
|
|
return write_tlv_handle(
|
|
T_JSON_NODE,
|
|
node_id,
|
|
result,
|
|
result_len,
|
|
);
|
|
}
|
|
return E_PLUGIN;
|
|
}
|
|
ProviderKind::Yyjson => {
|
|
if let Some(dp) = doc.doc_ptr {
|
|
let vp = ffi::nyjson_doc_root(dp as *mut std::os::raw::c_void);
|
|
let node_id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
|
if let Ok(mut nn) = NODES.lock() {
|
|
nn.insert(
|
|
node_id,
|
|
NodeRep::Yy {
|
|
doc_id: instance_id,
|
|
ptr: vp as usize,
|
|
},
|
|
);
|
|
}
|
|
return write_tlv_handle(
|
|
T_JSON_NODE,
|
|
node_id,
|
|
result,
|
|
result_len,
|
|
);
|
|
}
|
|
return E_PLUGIN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return E_PLUGIN;
|
|
}
|
|
JD_ERROR => {
|
|
if let Ok(m) = DOCS.lock() {
|
|
if let Some(doc) = m.get(&instance_id) {
|
|
let s = doc.last_err.clone().unwrap_or_default();
|
|
return write_tlv_string(&s, result, result_len);
|
|
} else {
|
|
return E_HANDLE;
|
|
}
|
|
} else {
|
|
return E_PLUGIN;
|
|
}
|
|
}
|
|
JD_FINI => {
|
|
if let Ok(mut m) = DOCS.lock() {
|
|
if let Some(mut di) = m.remove(&instance_id) {
|
|
if let Some(dp) = di.doc_ptr.take() {
|
|
ffi::nyjson_doc_free(dp as *mut std::os::raw::c_void);
|
|
}
|
|
}
|
|
}
|
|
return write_tlv_void(result, result_len);
|
|
}
|
|
_ => E_METHOD,
|
|
}
|
|
}
|
|
}
|