1 use std::ffi::{CStr, CString};
2 use std::os::raw::{c_char, c_void};
3 
4 use {parser, select, select_as_str};
5 
6 const INVALID_PATH: &str = "invalid path";
7 const INVALID_JSON: &str = "invalud json";
8 
to_str(v: *const c_char, err_msg: &str) -> &str9 fn to_str(v: *const c_char, err_msg: &str) -> &str {
10     unsafe { CStr::from_ptr(v) }.to_str().expect(err_msg)
11 }
12 
to_char_ptr(v: &str) -> *const c_char13 fn to_char_ptr(v: &str) -> *const c_char {
14     let s = CString::new(v).unwrap_or_else(|_| panic!("invalid string: {}", v));
15     let ptr = s.as_ptr();
16     std::mem::forget(s);
17     ptr
18 }
19 
20 #[no_mangle]
ffi_select(json_str: *const c_char, path: *const c_char) -> *const c_char21 pub extern "C" fn ffi_select(json_str: *const c_char, path: *const c_char) -> *const c_char {
22     let json_str = to_str(json_str, INVALID_JSON);
23     let path = to_str(path, INVALID_PATH);
24     match select_as_str(json_str, path) {
25         Ok(v) => to_char_ptr(v.as_str()),
26         Err(e) => {
27             panic!("{:?}", e);
28         }
29     }
30 }
31 
32 #[no_mangle]
33 #[allow(clippy::forget_copy)]
ffi_path_compile(path: *const c_char) -> *mut c_void34 pub extern "C" fn ffi_path_compile(path: *const c_char) -> *mut c_void {
35     let path = to_str(path, INVALID_PATH);
36     let ref_node = Box::into_raw(Box::new(parser::Parser::compile(path).unwrap()));
37     let ptr = ref_node as *mut c_void;
38     std::mem::forget(ref_node);
39     ptr
40 }
41 
42 #[no_mangle]
ffi_select_with_compiled_path( path_ptr: *mut c_void, json_ptr: *const c_char, ) -> *const c_char43 pub extern "C" fn ffi_select_with_compiled_path(
44     path_ptr: *mut c_void,
45     json_ptr: *const c_char,
46 ) -> *const c_char {
47     let node = unsafe { Box::from_raw(path_ptr as *mut parser::Node) };
48     let json_str = to_str(json_ptr, INVALID_JSON);
49     let json = serde_json::from_str(json_str)
50         .unwrap_or_else(|_| panic!("invalid json string: {}", json_str));
51 
52     let mut selector = select::Selector::default();
53     let found = selector.compiled_path(&node).value(&json).select().unwrap();
54     std::mem::forget(node);
55 
56     let result = serde_json::to_string(&found)
57         .unwrap_or_else(|_| panic!("json serialize error: {:?}", found));
58     to_char_ptr(result.as_str())
59 }
60