Add fleshed-out Jansson bindings

This commit is contained in:
Marshall Quander 2017-09-25 15:46:59 -07:00
Родитель a0635a99fc
Коммит c76c18ba24
5 изменённых файлов: 186 добавлений и 0 удалений

3
jansson-sys/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
/target/
**/*.rs.bk
Cargo.lock

8
jansson-sys/Cargo.toml Normal file
Просмотреть файл

@ -0,0 +1,8 @@
[package]
name = "jansson-sys"
version = "0.1.0"
authors = ["Marshall Quander <marshall@quander.me>"]
description = "Native bindings for Jansson, the C JSON library."
[dev-dependencies]
cstr-macro = "0.1.0"

3
jansson-sys/build.rs Normal file
Просмотреть файл

@ -0,0 +1,3 @@
fn main() {
println!("cargo:rustc-link-lib=jansson");
}

1
jansson-sys/rustfmt.toml Normal file
Просмотреть файл

@ -0,0 +1 @@
max_width = 140

171
jansson-sys/src/lib.rs Normal file
Просмотреть файл

@ -0,0 +1,171 @@
#![allow(non_camel_case_types)]
// See https://jansson.readthedocs.io/ for API documentation.
use std::os::raw::{c_char, c_int, c_void, c_longlong};
/// The type of a JSON value.
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum json_type {
JSON_OBJECT = 0,
JSON_ARRAY = 1,
JSON_STRING = 2,
JSON_INTEGER = 3,
JSON_REAL = 4,
JSON_TRUE = 5,
JSON_FALSE = 6,
JSON_NULL = 7,
}
/// A JSON value.
#[repr(C)]
#[derive(Debug)]
pub struct json_t {
pub type_: json_type,
pub refcount: usize,
}
/// An error that occurred during JSON processing.
#[repr(C)]
pub struct json_error_t {
pub line: c_int,
pub column: c_int,
pub position: c_int,
pub source: [c_char; 80usize],
pub text: [c_char; 160usize],
}
pub type json_load_callback_t = unsafe extern "C" fn(buffer: *mut c_void, buflen: usize, data: *mut c_void) -> usize;
pub type json_dump_callback_t = unsafe extern "C" fn(buffer: *const c_char, size: usize, data: *mut c_void) -> c_int;
pub type json_malloc_t = unsafe extern "C" fn(arg1: usize) -> *mut c_void;
pub type json_free_t = unsafe extern "C" fn(arg1: *mut c_void);
pub type json_int_t = c_longlong;
extern "C" {
pub fn json_object() -> *mut json_t;
pub fn json_array() -> *mut json_t;
pub fn json_string(value: *const c_char) -> *mut json_t;
pub fn json_stringn(value: *const c_char, len: usize) -> *mut json_t;
pub fn json_string_nocheck(value: *const c_char) -> *mut json_t;
pub fn json_stringn_nocheck(value: *const c_char, len: usize) -> *mut json_t;
pub fn json_integer(value: json_int_t) -> *mut json_t;
pub fn json_real(value: f64) -> *mut json_t;
pub fn json_true() -> *mut json_t;
pub fn json_false() -> *mut json_t;
pub fn json_null() -> *mut json_t;
pub fn json_delete(json: *mut json_t);
pub fn json_object_seed(seed: usize);
pub fn json_object_size(object: *const json_t) -> usize;
pub fn json_object_get(object: *const json_t, key: *const c_char) -> *mut json_t;
pub fn json_object_set_new(object: *mut json_t, key: *const c_char, value: *mut json_t) -> c_int;
pub fn json_object_set_new_nocheck(object: *mut json_t, key: *const c_char, value: *mut json_t) -> c_int;
pub fn json_object_del(object: *mut json_t, key: *const c_char) -> c_int;
pub fn json_object_clear(object: *mut json_t) -> c_int;
pub fn json_object_update(object: *mut json_t, other: *mut json_t) -> c_int;
pub fn json_object_update_existing(object: *mut json_t, other: *mut json_t) -> c_int;
pub fn json_object_update_missing(object: *mut json_t, other: *mut json_t) -> c_int;
pub fn json_object_iter(object: *mut json_t) -> *mut c_void;
pub fn json_object_iter_at(object: *mut json_t, key: *const c_char) -> *mut c_void;
pub fn json_object_key_to_iter(key: *const c_char) -> *mut c_void;
pub fn json_object_iter_next(object: *mut json_t, iter: *mut c_void) -> *mut c_void;
pub fn json_object_iter_key(iter: *mut c_void) -> *const c_char;
pub fn json_object_iter_value(iter: *mut c_void) -> *mut json_t;
pub fn json_object_iter_set_new(object: *mut json_t, iter: *mut c_void, value: *mut json_t) -> c_int;
pub fn json_array_size(array: *const json_t) -> usize;
pub fn json_array_get(array: *const json_t, index: usize) -> *mut json_t;
pub fn json_array_set_new(array: *mut json_t, index: usize, value: *mut json_t) -> c_int;
pub fn json_array_append_new(array: *mut json_t, value: *mut json_t) -> c_int;
pub fn json_array_insert_new(array: *mut json_t, index: usize, value: *mut json_t) -> c_int;
pub fn json_array_remove(array: *mut json_t, index: usize) -> c_int;
pub fn json_array_clear(array: *mut json_t) -> c_int;
pub fn json_array_extend(array: *mut json_t, other: *mut json_t) -> c_int;
pub fn json_string_value(string: *const json_t) -> *const c_char;
pub fn json_string_length(string: *const json_t) -> usize;
pub fn json_integer_value(integer: *const json_t) -> json_int_t;
pub fn json_real_value(real: *const json_t) -> f64;
pub fn json_number_value(json: *const json_t) -> f64;
pub fn json_string_set(string: *mut json_t, value: *const c_char) -> c_int;
pub fn json_string_setn(string: *mut json_t, value: *const c_char, len: usize) -> c_int;
pub fn json_string_set_nocheck(string: *mut json_t, value: *const c_char) -> c_int;
pub fn json_string_setn_nocheck(string: *mut json_t, value: *const c_char, len: usize) -> c_int;
pub fn json_integer_set(integer: *mut json_t, value: json_int_t) -> c_int;
pub fn json_real_set(real: *mut json_t, value: f64) -> c_int;
pub fn json_pack(fmt: *const c_char, ...) -> *mut json_t;
pub fn json_pack_ex(error: *mut json_error_t, flags: usize, fmt: *const c_char, ...) -> *mut json_t;
pub fn json_unpack(root: *mut json_t, fmt: *const c_char, ...) -> c_int;
pub fn json_unpack_ex(root: *mut json_t, error: *mut json_error_t, flags: usize, fmt: *const c_char, ...) -> c_int;
pub fn json_equal(value1: *mut json_t, value2: *mut json_t) -> c_int;
pub fn json_copy(value: *mut json_t) -> *mut json_t;
pub fn json_deep_copy(value: *const json_t) -> *mut json_t;
pub fn json_loads(input: *const c_char, flags: usize, error: *mut json_error_t) -> *mut json_t;
pub fn json_loadb(buffer: *const c_char, buflen: usize, flags: usize, error: *mut json_error_t) -> *mut json_t;
pub fn json_loadfd(input: c_int, flags: usize, error: *mut json_error_t) -> *mut json_t;
pub fn json_load_file(path: *const c_char, flags: usize, error: *mut json_error_t) -> *mut json_t;
pub fn json_load_callback(callback: json_load_callback_t, data: *mut c_void, flags: usize, error: *mut json_error_t) -> *mut json_t;
pub fn json_dumps(json: *const json_t, flags: usize) -> *mut c_char;
pub fn json_dumpb(json: *const json_t, buffer: *mut c_char, size: usize, flags: usize) -> usize;
pub fn json_dumpfd(json: *const json_t, output: c_int, flags: usize) -> c_int;
pub fn json_dump_file(json: *const json_t, path: *const c_char, flags: usize) -> c_int;
pub fn json_dump_callback(json: *const json_t, callback: json_dump_callback_t, data: *mut c_void, flags: usize) -> c_int;
pub fn json_set_alloc_funcs(malloc_fn: json_malloc_t, free_fn: json_free_t);
pub fn json_get_alloc_funcs(malloc_fn: *mut json_malloc_t, free_fn: *mut json_free_t);
}
#[cfg(test)]
#[macro_use]
extern crate cstr_macro;
#[cfg(test)]
mod tests {
use std::ptr;
use std::ffi::CStr;
use super::*;
#[test]
fn object_encoding() {
unsafe {
let x = json_object();
json_object_set_new(x, cstr!("a"), json_string(cstr!("alpha")));
json_object_set_new(x, cstr!("b"), json_true());
json_object_set_new(x, cstr!("c"), json_false());
json_object_set_new(x, cstr!("d"), json_integer(42));
json_object_set_new(x, cstr!("e"), json_real(1.25));
json_object_set_new(x, cstr!("f"), json_null());
let ys = json_array();
json_array_append_new(ys, json_integer(1));
json_array_append_new(ys, json_integer(3));
json_array_insert_new(ys, 1, json_integer(2));
json_object_set_new(x, cstr!("g"), ys);
let json = r#"{"a": "alpha", "b": true, "c": false, "d": 42, "e": 1.25, "f": null, "g": [1, 2, 3]}"#;
assert_eq!(json, CStr::from_ptr(json_dumps(x, 0)).to_str().unwrap());
}
}
#[test]
fn object_decoding() {
unsafe {
let json = cstr!(r#"{"a": {"aa": [true, false], "ab": null}, "b": {}, "c": "charlie", "d": 8.75}"#);
let root = json_loads(json, 0, ptr::null_mut());
assert!((*root).type_ == json_type::JSON_OBJECT);
let a = json_object_get(root, cstr!("a"));
assert!((*a).type_ == json_type::JSON_OBJECT);
let aa = json_object_get(a, cstr!("aa"));
assert!((*aa).type_ == json_type::JSON_ARRAY);
assert_eq!(json_array_size(aa), 2);
assert!((*json_array_get(aa, 0)).type_ == json_type::JSON_TRUE);
assert!((*json_array_get(aa, 1)).type_ == json_type::JSON_FALSE);
let ab = json_object_get(a, cstr!("ab"));
assert!((*ab).type_ == json_type::JSON_NULL);
let b = json_object_get(root, cstr!("b"));
assert!((*b).type_ == json_type::JSON_OBJECT);
assert_eq!(json_object_size(b), 0);
let c = json_object_get(root, cstr!("c"));
assert!((*c).type_ == json_type::JSON_STRING);
assert_eq!("charlie", CStr::from_ptr(json_string_value(c)).to_str().unwrap());
let d = json_object_get(root, cstr!("d"));
assert!((*d).type_ == json_type::JSON_REAL);
assert_eq!(8.75, json_real_value(d));
}
}
}