Skip to main content

cjson_binding/
lib.rs

1/***************************************************************************
2 *
3 * cJSON FFI BINDING FOR RUST
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 ***************************************************************************/
19
20#![cfg_attr(not(any(test, feature = "std")), no_std)]
21
22extern crate alloc;
23
24#[cfg(feature = "disable_panic")]
25extern crate osal_rs;
26
27#[cfg(feature = "disable_panic")]
28extern crate osal_rs_serde;
29
30pub(crate) mod cjson_ffi;
31mod cjson;
32
33pub(crate) mod cjson_utils_ffi;
34mod cjson_utils;
35
36#[cfg(feature = "osal_rs")]
37pub mod ser;
38
39#[cfg(feature = "osal_rs")]
40pub mod de;
41
42// Re-export main types for convenience
43pub use cjson::{CJson, CJsonRef, CJsonResult, CJsonError};
44pub use cjson_utils::{JsonPointer, JsonPatch, JsonMergePatch, JsonUtils};
45#[cfg(feature = "osal_rs")]
46use osal_rs_serde::{Deserialize, Result, Serialize};
47
48#[cfg(feature = "osal_rs")]
49use alloc::string::String;
50
51
52
53// Global allocator for no_std environments (disabled when disable_panic is enabled)
54#[cfg(all(not(any(test, feature = "std")), not(feature = "disable_panic")))]
55use core::alloc::Layout;
56
57#[cfg(all(not(any(test, feature = "std")), not(feature = "disable_panic")))]
58struct CJsonAllocator;
59
60#[cfg(all(not(any(test, feature = "std")), not(feature = "disable_panic")))]
61unsafe impl core::alloc::GlobalAlloc for CJsonAllocator {
62    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
63        unsafe extern "C" {
64            fn malloc(size: usize) -> *mut u8;
65        }
66        unsafe { malloc(layout.size()) }
67    }
68
69    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
70        unsafe extern "C" {
71            fn free(ptr: *mut u8);
72        }
73        unsafe { free(ptr) }
74    }
75}
76
77#[cfg(all(not(any(test, feature = "std")), not(feature = "disable_panic")))]
78#[global_allocator]
79static ALLOCATOR: CJsonAllocator = CJsonAllocator;
80
81// Panic handler for no_std environments (can be disabled with disable_panic feature)
82#[cfg(all(not(any(test, feature = "std")), not(feature = "disable_panic")))]
83#[panic_handler]
84fn panic(_info: &core::panic::PanicInfo) -> ! {
85    loop {}
86}
87
88#[cfg(feature = "osal_rs")]
89#[allow(unused)]
90const APP_TAG: &str = "cJSON-RS";
91
92#[cfg(feature = "osal_rs")]
93pub fn to_json<T>(value: &T) -> Result<String> 
94where 
95    T: Serialize
96{
97    use crate::ser::JsonSerializer;
98    use osal_rs::log_error;
99    
100
101    let mut serializer = JsonSerializer::new();
102
103    value.serialize("", &mut serializer).map_err(|e| {
104        log_error!(APP_TAG, "Serialization error: {}", e);
105        osal_rs_serde::Error::InvalidData
106    })?;
107    
108    let json = serializer.print_unformatted().map_err(|e| {
109        log_error!(APP_TAG, "Failed to print JSON: {}", e);
110        osal_rs_serde::Error::InvalidData
111    })?;
112    
113    Ok(json)
114}
115
116#[cfg(feature = "osal_rs")]
117pub fn from_json<T>(json: &String) -> Result<T> 
118where 
119    T: Deserialize + Default
120{
121    use crate::de::JsonDeserializer;
122    use osal_rs::log_error;
123
124    let mut deserializer = JsonDeserializer::parse(json).map_err(|e| {
125        log_error!(APP_TAG, "Failed to parse JSON: {}", e);
126        osal_rs_serde::Error::InvalidData
127    })?;
128
129    let ret = T::deserialize(&mut deserializer, "").map_err(|e| {
130        log_error!(APP_TAG, "Failed to deserialize JSON: {}", e);
131        osal_rs_serde::Error::InvalidData
132    })?;
133
134    deserializer.drop();
135
136    Ok(ret)
137}
138