1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use bitflags::bitflags;
use jansson_sys;
use std::error::Error;
use std::fmt;
use std::ffi::{CStr, CString};
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::slice;
use std::str;
use crate::utils::LibcString;
pub type RawJanssonValue = jansson_sys::json_t;
bitflags! {
pub struct JanssonDecodingFlags: usize {
const JSON_REJECT_DUPLICATES = 0x0001;
const JSON_DISABLE_EOF_CHECK = 0x0002;
const JSON_DECODE_ANY = 0x0004;
const JSON_DECODE_INT_AS_REAL = 0x0008;
const JSON_ALLOW_NUL = 0x0010;
}
}
bitflags! {
pub struct JanssonEncodingFlags: usize {
const JSON_COMPACT = 0x0020;
const JSON_ENSURE_ASCII = 0x0040;
const JSON_SORT_KEYS = 0x0080;
const JSON_PRESERVE_ORDER = 0x0100;
const JSON_ENCODE_ANY = 0x0200;
const JSON_ESCAPE_SLASH = 0x0400;
const JSON_EMBED = 0x0800;
}
}
pub struct JanssonValue {
ptr: *mut RawJanssonValue,
}
impl JanssonValue {
pub unsafe fn from_and_incref(ptr: *mut RawJanssonValue) -> Option<Self> {
jansson_sys::json_incref(ptr);
Self::from_raw(ptr)
}
pub unsafe fn from_raw(ptr: *mut RawJanssonValue) -> Option<Self> {
ptr.as_mut().map(|p| Self { ptr: p })
}
pub fn into_raw(self) -> *mut RawJanssonValue {
unsafe { jansson_sys::json_incref(self.ptr) };
self.ptr
}
pub fn as_mut_ref(&mut self) -> &mut RawJanssonValue {
unsafe { self.ptr.as_mut().unwrap() }
}
pub fn from_str(input: &str, decoding_flags: JanssonDecodingFlags) -> Result<Self, Box<dyn Error + Send + Sync>> {
Self::from_cstr(&CString::new(input)?, decoding_flags)
}
pub fn from_cstr(input: &CStr, decoding_flags: JanssonDecodingFlags) -> Result<Self, Box<dyn Error + Send + Sync>> {
unsafe {
let mut error = MaybeUninit::<jansson_sys::json_error_t>::uninit();
let result = jansson_sys::json_loads(input.as_ptr(), decoding_flags.bits(), error.as_mut_ptr());
match Self::from_raw(result) {
Some(val) => Ok(val),
None => {
let ptr = &error.assume_init().text as *const _;
let len = libc::strlen(ptr);
let sli = slice::from_raw_parts(ptr as *mut u8, len);
Err(From::from(str::from_utf8(sli)?))
}
}
}
}
pub fn to_libcstring(&self, encoding_flags: JanssonEncodingFlags) -> LibcString {
unsafe {
let json = jansson_sys::json_dumps(self.ptr, encoding_flags.bits());
LibcString::from_chars(json).expect("Error writing JSON output from Jansson value :(")
}
}
}
impl fmt::Debug for JanssonValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "JanssonValue {{ {} }}", self.to_libcstring(JanssonEncodingFlags::empty()).to_string_lossy())
}
}
impl Deref for JanssonValue {
type Target = RawJanssonValue;
fn deref(&self) -> &RawJanssonValue {
unsafe { &*self.ptr }
}
}
impl Clone for JanssonValue {
fn clone(&self) -> Self {
unsafe { jansson_sys::json_incref(self.ptr) };
Self { ptr: self.ptr }
}
}
impl Drop for JanssonValue {
fn drop(&mut self) {
unsafe { jansson_sys::json_decref(self.ptr) }
}
}
unsafe impl Send for JanssonValue {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trip() {
let json = r#"{"a": "alpha", "b": true, "c": false, "d": 42, "e": 1.25, "f": null, "g": [1, 2, 3]}"#;
let result = JanssonValue::from_str(json, JanssonDecodingFlags::empty()).unwrap();
assert_eq!(json, result.to_libcstring(JanssonEncodingFlags::JSON_SORT_KEYS).to_str().unwrap());
}
#[test]
fn produce_jansson_errors() {
let json = r#"{"a":"#;
let result = JanssonValue::from_str(json, JanssonDecodingFlags::empty());
assert!(result.is_err());
}
}