1#![allow(non_camel_case_types)]
2use std::os::raw::{c_char, c_int, c_longlong, c_void};
5
6#[repr(u32)]
8#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
9pub enum json_type {
10 JSON_OBJECT = 0,
11 JSON_ARRAY = 1,
12 JSON_STRING = 2,
13 JSON_INTEGER = 3,
14 JSON_REAL = 4,
15 JSON_TRUE = 5,
16 JSON_FALSE = 6,
17 JSON_NULL = 7,
18}
19
20pub const JSON_MAX_INDENT: u32 = 31;
22
23#[repr(C)]
25#[derive(Debug)]
26pub struct json_t {
27 pub type_: json_type,
28 pub refcount: usize,
29}
30
31#[repr(C)]
33pub struct json_error_t {
34 pub line: c_int,
35 pub column: c_int,
36 pub position: c_int,
37 pub source: [c_char; 80usize],
38 pub text: [c_char; 160usize],
39}
40
41pub type json_load_callback_t = unsafe extern "C" fn(buffer: *mut c_void, buflen: usize, data: *mut c_void) -> usize;
42pub type json_dump_callback_t = unsafe extern "C" fn(buffer: *const c_char, size: usize, data: *mut c_void) -> c_int;
43pub type json_malloc_t = unsafe extern "C" fn(arg1: usize) -> *mut c_void;
44pub type json_free_t = unsafe extern "C" fn(arg1: *mut c_void);
45pub type json_int_t = c_longlong;
46
47extern "C" {
48 pub fn json_object() -> *mut json_t;
49 pub fn json_array() -> *mut json_t;
50 pub fn json_string(value: *const c_char) -> *mut json_t;
51 pub fn json_stringn(value: *const c_char, len: usize) -> *mut json_t;
52 pub fn json_string_nocheck(value: *const c_char) -> *mut json_t;
53 pub fn json_stringn_nocheck(value: *const c_char, len: usize) -> *mut json_t;
54 pub fn json_integer(value: json_int_t) -> *mut json_t;
55 pub fn json_real(value: f64) -> *mut json_t;
56 pub fn json_true() -> *mut json_t;
57 pub fn json_false() -> *mut json_t;
58 pub fn json_null() -> *mut json_t;
59 pub fn json_delete(json: *mut json_t);
60 pub fn json_object_seed(seed: usize);
61 pub fn json_object_size(object: *const json_t) -> usize;
62 pub fn json_object_get(object: *const json_t, key: *const c_char) -> *mut json_t;
63 pub fn json_object_set_new(object: *mut json_t, key: *const c_char, value: *mut json_t) -> c_int;
64 pub fn json_object_set_new_nocheck(object: *mut json_t, key: *const c_char, value: *mut json_t) -> c_int;
65 pub fn json_object_del(object: *mut json_t, key: *const c_char) -> c_int;
66 pub fn json_object_clear(object: *mut json_t) -> c_int;
67 pub fn json_object_update(object: *mut json_t, other: *mut json_t) -> c_int;
68 pub fn json_object_update_existing(object: *mut json_t, other: *mut json_t) -> c_int;
69 pub fn json_object_update_missing(object: *mut json_t, other: *mut json_t) -> c_int;
70 pub fn json_object_iter(object: *mut json_t) -> *mut c_void;
71 pub fn json_object_iter_at(object: *mut json_t, key: *const c_char) -> *mut c_void;
72 pub fn json_object_key_to_iter(key: *const c_char) -> *mut c_void;
73 pub fn json_object_iter_next(object: *mut json_t, iter: *mut c_void) -> *mut c_void;
74 pub fn json_object_iter_key(iter: *mut c_void) -> *const c_char;
75 pub fn json_object_iter_value(iter: *mut c_void) -> *mut json_t;
76 pub fn json_object_iter_set_new(object: *mut json_t, iter: *mut c_void, value: *mut json_t) -> c_int;
77 pub fn json_array_size(array: *const json_t) -> usize;
78 pub fn json_array_get(array: *const json_t, index: usize) -> *mut json_t;
79 pub fn json_array_set_new(array: *mut json_t, index: usize, value: *mut json_t) -> c_int;
80 pub fn json_array_append_new(array: *mut json_t, value: *mut json_t) -> c_int;
81 pub fn json_array_insert_new(array: *mut json_t, index: usize, value: *mut json_t) -> c_int;
82 pub fn json_array_remove(array: *mut json_t, index: usize) -> c_int;
83 pub fn json_array_clear(array: *mut json_t) -> c_int;
84 pub fn json_array_extend(array: *mut json_t, other: *mut json_t) -> c_int;
85 pub fn json_string_value(string: *const json_t) -> *const c_char;
86 pub fn json_string_length(string: *const json_t) -> usize;
87 pub fn json_integer_value(integer: *const json_t) -> json_int_t;
88 pub fn json_real_value(real: *const json_t) -> f64;
89 pub fn json_number_value(json: *const json_t) -> f64;
90 pub fn json_string_set(string: *mut json_t, value: *const c_char) -> c_int;
91 pub fn json_string_setn(string: *mut json_t, value: *const c_char, len: usize) -> c_int;
92 pub fn json_string_set_nocheck(string: *mut json_t, value: *const c_char) -> c_int;
93 pub fn json_string_setn_nocheck(string: *mut json_t, value: *const c_char, len: usize) -> c_int;
94 pub fn json_integer_set(integer: *mut json_t, value: json_int_t) -> c_int;
95 pub fn json_real_set(real: *mut json_t, value: f64) -> c_int;
96 pub fn json_pack(fmt: *const c_char, ...) -> *mut json_t;
97 pub fn json_pack_ex(error: *mut json_error_t, flags: usize, fmt: *const c_char, ...) -> *mut json_t;
98 pub fn json_unpack(root: *mut json_t, fmt: *const c_char, ...) -> c_int;
99 pub fn json_unpack_ex(root: *mut json_t, error: *mut json_error_t, flags: usize, fmt: *const c_char, ...) -> c_int;
100 pub fn json_equal(value1: *mut json_t, value2: *mut json_t) -> c_int;
101 pub fn json_copy(value: *mut json_t) -> *mut json_t;
102 pub fn json_deep_copy(value: *const json_t) -> *mut json_t;
103 pub fn json_loads(input: *const c_char, flags: usize, error: *mut json_error_t) -> *mut json_t;
104 pub fn json_loadb(buffer: *const c_char, buflen: usize, flags: usize, error: *mut json_error_t) -> *mut json_t;
105 pub fn json_loadfd(input: c_int, flags: usize, error: *mut json_error_t) -> *mut json_t;
106 pub fn json_load_file(path: *const c_char, flags: usize, error: *mut json_error_t) -> *mut json_t;
107 pub fn json_load_callback(callback: json_load_callback_t, data: *mut c_void, flags: usize, error: *mut json_error_t) -> *mut json_t;
108 pub fn json_dumps(json: *const json_t, flags: usize) -> *mut c_char;
109 pub fn json_dumpb(json: *const json_t, buffer: *mut c_char, size: usize, flags: usize) -> usize;
110 pub fn json_dumpfd(json: *const json_t, output: c_int, flags: usize) -> c_int;
111 pub fn json_dump_file(json: *const json_t, path: *const c_char, flags: usize) -> c_int;
112 pub fn json_dump_callback(json: *const json_t, callback: json_dump_callback_t, data: *mut c_void, flags: usize) -> c_int;
113 pub fn json_set_alloc_funcs(malloc_fn: json_malloc_t, free_fn: json_free_t);
114 pub fn json_get_alloc_funcs(malloc_fn: *mut json_malloc_t, free_fn: *mut json_free_t);
115}
116
117pub unsafe fn json_incref(json: *mut json_t) -> *mut json_t {
118 if !json.is_null() && (*json).refcount != usize::max_value() {
119 (*json).refcount += 1;
120 }
121 json
122}
123
124pub unsafe fn json_decref(json: *mut json_t) {
125 if !json.is_null() && (*json).refcount != usize::max_value() {
126 (*json).refcount -= 1;
127 if (*json).refcount == 0 {
128 json_delete(json);
129 }
130 }
131}
132
133#[cfg(test)]
134#[macro_use]
135extern crate cstr_macro;
136
137#[cfg(test)]
138mod tests {
139
140 use super::*;
141 use std::ffi::CStr;
142 use std::ptr;
143
144 #[test]
145 fn object_encoding() {
146 unsafe {
147 let x = json_object();
148 json_object_set_new(x, cstr!("a"), json_string(cstr!("alpha")));
149 json_object_set_new(x, cstr!("b"), json_true());
150 json_object_set_new(x, cstr!("c"), json_false());
151 json_object_set_new(x, cstr!("d"), json_integer(42));
152 json_object_set_new(x, cstr!("e"), json_real(1.25));
153 json_object_set_new(x, cstr!("f"), json_null());
154 let ys = json_array();
155 json_array_append_new(ys, json_integer(1));
156 json_array_append_new(ys, json_integer(3));
157 json_array_insert_new(ys, 1, json_integer(2));
158 json_object_set_new(x, cstr!("g"), ys);
159 let json = r#"{"a": "alpha", "b": true, "c": false, "d": 42, "e": 1.25, "f": null, "g": [1, 2, 3]}"#;
160 assert_eq!(json, CStr::from_ptr(json_dumps(x, 0)).to_str().unwrap());
161 }
162 }
163
164 #[test]
165 fn object_decoding() {
166 unsafe {
167 let json = cstr!(r#"{"a": {"aa": [true, false], "ab": null}, "b": {}, "c": "charlie", "d": 8.75}"#);
168 let root = json_loads(json, 0, ptr::null_mut());
169 assert!((*root).type_ == json_type::JSON_OBJECT);
170 let a = json_object_get(root, cstr!("a"));
171 assert!((*a).type_ == json_type::JSON_OBJECT);
172 let aa = json_object_get(a, cstr!("aa"));
173 assert!((*aa).type_ == json_type::JSON_ARRAY);
174 assert_eq!(json_array_size(aa), 2);
175 assert!((*json_array_get(aa, 0)).type_ == json_type::JSON_TRUE);
176 assert!((*json_array_get(aa, 1)).type_ == json_type::JSON_FALSE);
177 let ab = json_object_get(a, cstr!("ab"));
178 assert!((*ab).type_ == json_type::JSON_NULL);
179 let b = json_object_get(root, cstr!("b"));
180 assert!((*b).type_ == json_type::JSON_OBJECT);
181 assert_eq!(json_object_size(b), 0);
182 let c = json_object_get(root, cstr!("c"));
183 assert!((*c).type_ == json_type::JSON_STRING);
184 assert_eq!("charlie", CStr::from_ptr(json_string_value(c)).to_str().unwrap());
185 let d = json_object_get(root, cstr!("d"));
186 assert!((*d).type_ == json_type::JSON_REAL);
187 assert_eq!(8.75, json_real_value(d));
188 }
189 }
190}