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