Files
hakorune/plugins/nyash-json-plugin/src/doc_box.rs
nyash-codex cdf826cbe7 public: publish selfhost snapshot to public repo (SSOT using + AST merge + JSON VM fixes)
- 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.
2025-09-26 14:34:42 +09:00

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,
}
}
}