Skip to main content

rustapi_core/
json.rs

1//! JSON utilities with optional SIMD acceleration
2//!
3//! This module provides JSON parsing and serialization utilities that can use
4//! SIMD-accelerated parsing when the `simd-json` feature is enabled.
5//!
6//! # Performance
7//!
8//! When the `simd-json` feature is enabled, JSON parsing can be 2-4x faster
9//! for large payloads. This is particularly beneficial for API servers that
10//! handle large JSON request bodies.
11//!
12//! # Usage
13//!
14//! The module provides drop-in replacements for `serde_json` functions:
15//!
16//! ```rust,ignore
17//! use rustapi_core::json;
18//!
19//! // Deserialize from bytes (uses simd-json if available)
20//! let value: MyStruct = json::from_slice(&bytes)?;
21//!
22//! // Serialize to bytes
23//! let bytes = json::to_vec(&value)?;
24//! ```
25
26use serde::{de::DeserializeOwned, Serialize};
27
28/// Deserialize JSON from a byte slice.
29///
30/// When the `simd-json` feature is enabled, this uses SIMD-accelerated parsing.
31/// Otherwise, it falls back to standard `serde_json`.
32#[cfg(feature = "simd-json")]
33pub fn from_slice<T: DeserializeOwned>(slice: &[u8]) -> Result<T, JsonError> {
34    // simd-json requires mutable access for in-place parsing
35    let mut slice_copy = slice.to_vec();
36    simd_json::from_slice(&mut slice_copy).map_err(JsonError::SimdJson)
37}
38
39/// Deserialize JSON from a byte slice.
40///
41/// Standard `serde_json` implementation when `simd-json` feature is disabled.
42#[cfg(not(feature = "simd-json"))]
43pub fn from_slice<T: DeserializeOwned>(slice: &[u8]) -> Result<T, JsonError> {
44    serde_json::from_slice(slice).map_err(JsonError::SerdeJson)
45}
46
47/// Deserialize JSON from a mutable byte slice (zero-copy with simd-json).
48///
49/// This variant allows simd-json to parse in-place without copying,
50/// providing maximum performance.
51#[cfg(feature = "simd-json")]
52pub fn from_slice_mut<T: DeserializeOwned>(slice: &mut [u8]) -> Result<T, JsonError> {
53    simd_json::from_slice(slice).map_err(JsonError::SimdJson)
54}
55
56/// Deserialize JSON from a mutable byte slice.
57///
58/// Falls back to standard implementation when simd-json is disabled.
59#[cfg(not(feature = "simd-json"))]
60pub fn from_slice_mut<T: DeserializeOwned>(slice: &mut [u8]) -> Result<T, JsonError> {
61    serde_json::from_slice(slice).map_err(JsonError::SerdeJson)
62}
63
64/// Serialize a value to a JSON byte vector.
65///
66/// Uses pre-allocated buffer with estimated capacity for better performance.
67#[cfg(feature = "simd-json")]
68pub fn to_vec<T: Serialize>(value: &T) -> Result<Vec<u8>, JsonError> {
69    simd_json::to_vec(value).map_err(JsonError::SimdJson)
70}
71
72/// Serialize a value to a JSON byte vector.
73///
74/// Uses pre-allocated buffer with estimated capacity for better performance.
75#[cfg(not(feature = "simd-json"))]
76pub fn to_vec<T: Serialize>(value: &T) -> Result<Vec<u8>, JsonError> {
77    serde_json::to_vec(value).map_err(JsonError::SerdeJson)
78}
79
80/// Serialize a value to a JSON byte vector with pre-allocated capacity.
81///
82/// Use this when you have a good estimate of the output size to avoid
83/// reallocations.
84#[cfg(feature = "simd-json")]
85pub fn to_vec_with_capacity<T: Serialize>(
86    value: &T,
87    capacity: usize,
88) -> Result<Vec<u8>, JsonError> {
89    let mut buf = Vec::with_capacity(capacity);
90    simd_json::to_writer(&mut buf, value).map_err(JsonError::SimdJson)?;
91    Ok(buf)
92}
93
94/// Serialize a value to a JSON byte vector with pre-allocated capacity.
95///
96/// Use this when you have a good estimate of the output size to avoid
97/// reallocations.
98#[cfg(not(feature = "simd-json"))]
99pub fn to_vec_with_capacity<T: Serialize>(
100    value: &T,
101    capacity: usize,
102) -> Result<Vec<u8>, JsonError> {
103    let mut buf = Vec::with_capacity(capacity);
104    serde_json::to_writer(&mut buf, value).map_err(JsonError::SerdeJson)?;
105    Ok(buf)
106}
107
108/// Serialize a value to a pretty-printed JSON byte vector.
109pub fn to_vec_pretty<T: Serialize>(value: &T) -> Result<Vec<u8>, JsonError> {
110    serde_json::to_vec_pretty(value).map_err(JsonError::SerdeJson)
111}
112
113/// JSON error type that wraps both serde_json and simd-json errors.
114#[derive(Debug)]
115pub enum JsonError {
116    SerdeJson(serde_json::Error),
117    #[cfg(feature = "simd-json")]
118    SimdJson(simd_json::Error),
119}
120
121impl std::fmt::Display for JsonError {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        match self {
124            JsonError::SerdeJson(e) => write!(f, "{}", e),
125            #[cfg(feature = "simd-json")]
126            JsonError::SimdJson(e) => write!(f, "{}", e),
127        }
128    }
129}
130
131impl std::error::Error for JsonError {
132    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
133        match self {
134            JsonError::SerdeJson(e) => Some(e),
135            #[cfg(feature = "simd-json")]
136            JsonError::SimdJson(e) => Some(e),
137        }
138    }
139}
140
141impl From<serde_json::Error> for JsonError {
142    fn from(e: serde_json::Error) -> Self {
143        JsonError::SerdeJson(e)
144    }
145}
146
147#[cfg(feature = "simd-json")]
148impl From<simd_json::Error> for JsonError {
149    fn from(e: simd_json::Error) -> Self {
150        JsonError::SimdJson(e)
151    }
152}