use serde::Serialize;
pub fn error_response(code: &str, message: &str) -> String {
serde_json::to_string(&serde_json::json!({
"success": false,
"error": {
"code": code,
"message": message
}
}))
.unwrap_or_else(|e| {
let escaped_code = code.replace('"', "\\\"");
let escaped_message = e.to_string().replace('"', "\\\"");
format!(
r#"{{"success":false,"error":{{"code":"{}","message":"{}"}}}}"#,
escaped_code, escaped_message
)
})
}
pub fn success_response<T: Serialize>(data: &T) -> String {
serde_json::to_string(&serde_json::json!({
"success": true,
"data": data
}))
.unwrap_or_else(|e| error_response("SERIALIZATION_ERROR", &e.to_string()))
}
pub fn paginated_response<T: Serialize>(
items: &[T],
page: u32,
page_size: u32,
total_items: u32,
) -> String {
let total_pages = if page_size > 0 {
total_items.div_ceil(page_size)
} else {
0
};
serde_json::to_string(&serde_json::json!({
"success": true,
"data": {
"items": items,
"pagination": {
"page": page,
"page_size": page_size,
"total_items": total_items,
"total_pages": total_pages,
"has_next": page < total_pages,
"has_previous": page > 1
}
}
}))
.unwrap_or_else(|e| error_response("SERIALIZATION_ERROR", &e.to_string()))
}
pub fn api_metadata_response(name: &str, version: &str, description: &str) -> String {
serde_json::to_string(&serde_json::json!({
"success": true,
"api": {
"name": name,
"version": version,
"description": description
}
}))
.unwrap_or_else(|e| error_response("SERIALIZATION_ERROR", &e.to_string()))
}
#[cfg(feature = "simd-json")]
pub fn simd_to_string<T: Serialize>(value: &T) -> Result<String, String> {
use simd_json::serde::to_string;
to_string(value).map_err(|e| format!("JSON serialization failed: {}", e))
}
#[cfg(feature = "simd-json")]
pub fn simd_from_slice<T: serde::de::DeserializeOwned>(slice: &[u8]) -> Result<T, String> {
use simd_json::serde::from_slice;
let mut owned = slice.to_vec();
from_slice(&mut owned).map_err(|e| format!("JSON deserialization failed: {}", e))
}
#[cfg(feature = "simd-json")]
pub fn simd_from_str<T: serde::de::DeserializeOwned>(s: &str) -> Result<T, String> {
use simd_json::serde::from_slice;
let mut owned = s.as_bytes().to_vec();
from_slice(&mut owned).map_err(|e| format!("JSON deserialization failed: {}", e))
}
#[cfg(not(feature = "simd-json"))]
pub fn simd_to_string<T: Serialize>(value: &T) -> Result<String, String> {
serde_json::to_string(value).map_err(|e| format!("JSON serialization failed: {}", e))
}
#[cfg(not(feature = "simd-json"))]
pub fn simd_from_slice<T: serde::de::DeserializeOwned>(slice: &[u8]) -> Result<T, String> {
serde_json::from_slice(slice).map_err(|e| format!("JSON deserialization failed: {}", e))
}
#[cfg(not(feature = "simd-json"))]
pub fn simd_from_str<T: serde::de::DeserializeOwned>(s: &str) -> Result<T, String> {
serde_json::from_str(s).map_err(|e| format!("JSON deserialization failed: {}", e))
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
struct TestData {
name: String,
value: i32,
}
#[test]
fn test_error_response_structure() {
let json = error_response("NOT_FOUND", "Resource not found");
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], false);
assert_eq!(parsed["error"]["code"], "NOT_FOUND");
assert_eq!(parsed["error"]["message"], "Resource not found");
}
#[test]
fn test_success_response_with_data() {
let data = TestData {
name: "test".to_string(),
value: 42,
};
let json = success_response(&data);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["data"]["name"], "test");
assert_eq!(parsed["data"]["value"], 42);
}
#[test]
fn test_paginated_response_basic() {
let items = vec!["item1", "item2", "item3"];
let json = paginated_response(&items, 1, 2, 5);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["data"]["pagination"]["page"], 1);
assert_eq!(parsed["data"]["pagination"]["page_size"], 2);
assert_eq!(parsed["data"]["pagination"]["total_items"], 5);
assert_eq!(parsed["data"]["pagination"]["total_pages"], 3);
assert_eq!(parsed["data"]["pagination"]["has_next"], true);
assert_eq!(parsed["data"]["pagination"]["has_previous"], false);
}
#[test]
fn test_paginated_response_last_page() {
let items = vec!["item5"];
let json = paginated_response(&items, 3, 2, 5);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["has_next"], false);
assert_eq!(parsed["data"]["pagination"]["has_previous"], true);
}
#[test]
fn test_paginated_response_zero_page_size() {
let items: Vec<&str> = vec![];
let json = paginated_response(&items, 1, 0, 0);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["total_pages"], 0);
}
#[test]
fn test_api_metadata_response_structure() {
let json = api_metadata_response("users", "v1", "User management API");
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["api"]["name"], "users");
assert_eq!(parsed["api"]["version"], "v1");
assert_eq!(parsed["api"]["description"], "User management API");
}
#[test]
fn test_simd_to_string_basic() {
let data = TestData {
name: "simd".to_string(),
value: 100,
};
let result = simd_to_string(&data);
assert!(result.is_ok());
let json = result.unwrap();
assert!(json.contains("simd"));
}
#[test]
fn test_simd_from_slice_basic() {
let json = br#"{"name":"test","value":42}"#;
let result: Result<TestData, _> = simd_from_slice(json);
assert!(result.is_ok());
let data = result.unwrap();
assert_eq!(data.name, "test");
assert_eq!(data.value, 42);
}
#[test]
fn test_simd_from_slice_invalid() {
let result: Result<serde_json::Value, _> = simd_from_slice(b"not json");
assert!(result.is_err());
}
#[test]
fn test_simd_from_str_basic() {
let json = r#"{"name":"str-test","value":99}"#;
let result: Result<TestData, _> = simd_from_str(json);
assert!(result.is_ok());
assert_eq!(result.unwrap().name, "str-test");
}
#[test]
fn test_simd_from_str_invalid() {
let result: Result<serde_json::Value, _> = simd_from_str("not json");
assert!(result.is_err());
}
#[test]
fn test_simd_roundtrip() {
let original = TestData {
name: "roundtrip".to_string(),
value: 777,
};
let json = simd_to_string(&original).unwrap();
let restored: TestData = simd_from_str(&json).unwrap();
assert_eq!(original, restored);
}
#[test]
fn test_simd_roundtrip_via_slice() {
let original = vec![1, 2, 3];
let json = simd_to_string(&original).unwrap();
let restored: Vec<i32> = simd_from_slice(json.as_bytes()).unwrap();
assert_eq!(original, restored);
}
struct FailingSerialize;
impl serde::Serialize for FailingSerialize {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Err(serde::ser::Error::custom(
"intentional serialization failure",
))
}
}
#[test]
fn test_simd_to_string_serialization_error() {
let result = simd_to_string(&FailingSerialize);
assert!(result.is_err());
let err_msg = result.unwrap_err();
assert!(
err_msg.contains("JSON serialization failed"),
"Error message should describe the failure, got: {}",
err_msg
);
}
#[test]
fn test_simd_from_slice_deserialization_error_type_mismatch() {
let result: Result<TestData, _> = simd_from_slice(br#"{"name":123}"#);
assert!(result.is_err());
assert!(result.unwrap_err().contains("JSON deserialization failed"));
}
#[test]
fn test_simd_from_str_deserialization_error_type_mismatch() {
let result: Result<TestData, _> = simd_from_str(r#"{"name":true}"#);
assert!(result.is_err());
assert!(result.unwrap_err().contains("JSON deserialization failed"));
}
#[test]
fn test_paginated_response_single_page() {
let items = vec!["only"];
let json = paginated_response(&items, 1, 10, 1);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["total_pages"], 1);
assert_eq!(parsed["data"]["pagination"]["has_next"], false);
assert_eq!(parsed["data"]["pagination"]["has_previous"], false);
}
#[test]
fn test_paginated_response_exact_multiple() {
let items = vec!["a", "b"];
let json = paginated_response(&items, 1, 2, 4);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["total_pages"], 2);
assert_eq!(parsed["data"]["pagination"]["has_next"], true);
}
#[test]
fn test_error_response_empty_strings() {
let json = error_response("", "");
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], false);
assert_eq!(parsed["error"]["code"], "");
assert_eq!(parsed["error"]["message"], "");
}
#[test]
fn test_error_response_special_characters() {
let json = error_response("ERR_\"QUOTE\"", "Message with \"quotes\" and \\backslash");
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["error"]["code"], "ERR_\"QUOTE\"");
assert_eq!(
parsed["error"]["message"],
"Message with \"quotes\" and \\backslash"
);
}
#[test]
fn test_success_response_with_nested_data() {
#[derive(serde::Serialize)]
struct Nested {
inner: InnerData,
}
#[derive(serde::Serialize)]
struct InnerData {
value: i32,
}
let data = Nested {
inner: InnerData { value: 99 },
};
let json = success_response(&data);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["data"]["inner"]["value"], 99);
}
#[test]
fn test_success_response_with_empty_vec() {
let empty: Vec<i32> = vec![];
let json = success_response(&empty);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["data"], serde_json::json!([]));
}
#[test]
fn test_api_metadata_response_empty_description() {
let json = api_metadata_response("api", "v2", "");
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["api"]["description"], "");
}
#[test]
fn test_paginated_response_empty_items() {
let items: Vec<&str> = vec![];
let json = paginated_response(&items, 1, 10, 100);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["items"], serde_json::json!([]));
assert_eq!(parsed["data"]["pagination"]["total_pages"], 10);
assert_eq!(parsed["data"]["pagination"]["has_next"], true);
}
#[test]
fn test_simd_to_string_simple_value() {
let result = simd_to_string(&42i32);
assert!(result.is_ok());
assert_eq!(result.unwrap(), "42");
}
#[test]
fn test_simd_to_string_string_value() {
let result = simd_to_string(&"hello world".to_string());
assert!(result.is_ok());
assert!(result.unwrap().contains("hello world"));
}
#[test]
fn test_simd_from_slice_empty_json() {
let result: Result<serde_json::Value, _> = simd_from_slice(b"{}");
assert!(result.is_ok());
assert_eq!(result.unwrap(), serde_json::json!({}));
}
#[test]
fn test_simd_from_str_empty_object() {
let result: Result<serde_json::Value, _> = simd_from_str("{}");
assert!(result.is_ok());
}
#[test]
#[should_panic]
fn test_success_response_panics_on_unserializable_data() {
let _ = success_response(&FailingSerialize);
}
#[test]
#[should_panic]
fn test_paginated_response_panics_on_unserializable_data() {
let items = [FailingSerialize];
let _ = paginated_response(&items, 1, 1, 1);
}
#[test]
fn test_error_response_unicode_characters() {
let json = error_response("错误", "资源未找到:用户");
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], false);
assert_eq!(parsed["error"]["code"], "错误");
assert_eq!(parsed["error"]["message"], "资源未找到:用户");
}
#[test]
fn test_success_response_with_boolean() {
let json = success_response(&true);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["data"], true);
}
#[test]
fn test_success_response_with_none() {
let json = success_response(&None::<i32>);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["success"], true);
assert_eq!(parsed["data"], serde_json::Value::Null);
}
#[test]
fn test_paginated_response_non_exact_multiple() {
let items = vec!["a"];
let json = paginated_response(&items, 1, 3, 7);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["total_pages"], 3);
assert_eq!(parsed["data"]["pagination"]["has_next"], true);
}
#[test]
fn test_paginated_response_last_page_non_exact() {
let items = vec!["c"];
let json = paginated_response(&items, 3, 3, 7);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["has_next"], false);
assert_eq!(parsed["data"]["pagination"]["has_previous"], true);
}
#[test]
fn test_api_metadata_response_special_characters() {
let json = api_metadata_response(
"api/v1",
"2.0.0-beta",
"Handles \"quotes\", backslashes \\, and unicode 世界",
);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["api"]["name"], "api/v1");
assert_eq!(parsed["api"]["version"], "2.0.0-beta");
assert!(parsed["api"]["description"]
.as_str()
.unwrap()
.contains("世界"));
}
#[test]
fn test_paginated_response_page_size_one() {
let items = vec!["only"];
let json = paginated_response(&items, 1, 1, 5);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["data"]["pagination"]["total_pages"], 5);
assert_eq!(parsed["data"]["pagination"]["has_next"], true);
assert_eq!(parsed["data"]["pagination"]["has_previous"], false);
}
#[test]
fn test_simd_to_string_with_vec() {
let data = vec![1, 2, 3, 4, 5];
let result = simd_to_string(&data);
assert!(result.is_ok());
let json = result.unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed, serde_json::json!([1, 2, 3, 4, 5]));
}
#[test]
fn test_simd_from_slice_array() {
let json = br#"[1, 2, 3]"#;
let result: Result<Vec<i32>, _> = simd_from_slice(json);
assert!(result.is_ok());
assert_eq!(result.unwrap(), vec![1, 2, 3]);
}
#[test]
fn test_simd_from_str_boolean() {
let result: Result<bool, _> = simd_from_str("true");
assert!(result.is_ok());
assert!(result.unwrap());
}
}