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