Skip to main content

gojsonnet_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
5
6extern "C" {
7    // Declare functions defined in libjsonnet.cpp helper, not in c-bindings.go
8    pub fn jsonnet_realloc(
9        vm: *mut JsonnetVm,
10        str_: *mut std::os::raw::c_char,
11        sz: size_t,
12    ) -> ::std::os::raw::c_int;
13}
14
15#[cfg(test)]
16mod tests {
17    #[test]
18    fn library_version() {
19        let cstr = unsafe { std::ffi::CStr::from_ptr(super::jsonnet_version()) };
20        assert_eq!(cstr.to_str().unwrap(), "v0.17.0 (go-jsonnet)");
21    }
22
23    #[test]
24    fn evaluate_snippet() {
25        let filename = std::ffi::CString::new("evaluate_snippet.jsonnet")
26            .unwrap()
27            .into_raw();
28        let code = std::ffi::CString::new("{foo: 1+2, bar: std.isBoolean(false)}")
29            .unwrap()
30            .into_raw();
31        let result = unsafe {
32            let vm = super::jsonnet_make();
33            let mut err = 0;
34            let result_ptr = super::jsonnet_evaluate_snippet(vm, filename, code, &mut err);
35            let result = std::ffi::CStr::from_ptr(result_ptr)
36                .to_string_lossy()
37                .into_owned();
38            super::jsonnet_realloc(vm, result_ptr, 0);
39            super::jsonnet_destroy(vm);
40            if err == 0 {
41                Ok(result)
42            } else {
43                Err(result)
44            }
45        };
46        assert!(result.is_ok());
47        #[derive(Debug, PartialEq, serde::Deserialize)]
48        struct S {
49            foo: i32,
50            bar: bool,
51        }
52        let s: S = serde_json::from_str(&result.unwrap()).unwrap();
53        assert_eq!(s, S { foo: 3, bar: true });
54    }
55
56    #[test]
57    fn evaluate_snippet_syntax_error() {
58        let filename = std::ffi::CString::new("evaluate_snippet.jsonnet")
59            .unwrap()
60            .into_raw();
61        let code = std::ffi::CString::new("{foo: 1+}").unwrap().into_raw();
62        let result = unsafe {
63            let vm = super::jsonnet_make();
64            let mut err = 0;
65            let result_ptr = super::jsonnet_evaluate_snippet(vm, filename, code, &mut err);
66            let result = std::ffi::CStr::from_ptr(result_ptr)
67                .to_string_lossy()
68                .into_owned();
69            super::jsonnet_realloc(vm, result_ptr, 0);
70            super::jsonnet_destroy(vm);
71            if err == 0 {
72                Ok(result)
73            } else {
74                Err(result)
75            }
76        };
77        assert!(result.is_err());
78        assert!(result
79            .unwrap_err()
80            .starts_with("evaluate_snippet.jsonnet:1:"));
81    }
82
83    #[test]
84    fn native_callback() {
85        let filename = std::ffi::CString::new("native_callback.jsonnet")
86            .unwrap()
87            .into_raw();
88        let code = std::ffi::CString::new(
89            r#"
90            local hello = std.native("hello");
91            { message: hello("world") }
92        "#,
93        )
94        .unwrap()
95        .into_raw();
96        let name = std::ffi::CString::new("hello").unwrap().into_raw();
97        unsafe extern "C" fn callback(
98            ctx: *mut std::ffi::c_void,
99            argv: *const *const super::JsonnetJsonValue,
100            success: *mut i32,
101        ) -> *mut super::JsonnetJsonValue {
102            let vm = ctx as *mut super::JsonnetVm;
103            let arg_c =
104                super::jsonnet_json_extract_string(vm, *argv as *mut super::JsonnetJsonValue);
105            let arg = std::ffi::CStr::from_ptr(arg_c).to_str().unwrap();
106            let s = super::jsonnet_json_make_string(
107                vm,
108                std::ffi::CString::new(format!("hello {}", arg))
109                    .unwrap()
110                    .into_raw(),
111            );
112            *success = 1;
113            s
114        }
115        let mut params = vec![
116            std::ffi::CString::new("s").unwrap().into_raw(),
117            std::ptr::null_mut(),
118        ];
119        let result = unsafe {
120            let vm = super::jsonnet_make();
121            super::jsonnet_native_callback(
122                vm,
123                name,
124                Some(callback),
125                vm as *mut std::ffi::c_void,
126                params.as_mut_ptr(),
127            );
128            let mut err = 0;
129            let result_ptr = super::jsonnet_evaluate_snippet(vm, filename, code, &mut err);
130            let result = std::ffi::CStr::from_ptr(result_ptr)
131                .to_string_lossy()
132                .into_owned();
133            super::jsonnet_realloc(vm, result_ptr, 0);
134            super::jsonnet_destroy(vm);
135            if err == 0 {
136                Ok(result)
137            } else {
138                Err(result)
139            }
140        };
141        assert!(result.is_ok());
142        #[derive(Debug, PartialEq, serde::Deserialize)]
143        struct S {
144            message: String,
145        }
146        let s: S = serde_json::from_str(&result.unwrap()).unwrap();
147        assert_eq!(
148            s,
149            S {
150                message: "hello world".to_owned()
151            }
152        );
153    }
154}