Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/kreuzberg-ffi/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ pub fn to_c_extraction_result(result: ExtractionResult) -> std::result::Result<*
let metadata_json_guard = {
let json =
serde_json::to_string(&metadata).map_err(|e| format!("Failed to serialize metadata to JSON: {}", e))?;

Some(CStringGuard::new(CString::new(json).map_err(|e| {
format!("Failed to convert metadata JSON to C string: {}", e)
})?))
Expand Down
36 changes: 1 addition & 35 deletions crates/kreuzberg-node/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
use crate::config::JsExtractionConfig;
use kreuzberg::{
Chunk as RustChunk, ChunkMetadata as RustChunkMetadata, ExtractionConfig, ExtractionResult as RustExtractionResult,
ProcessingWarning as RustProcessingWarning,
ProcessingWarning as RustProcessingWarning, utils::snake_to_camel,
};
use napi::bindgen_prelude::*;
use napi_derive::napi;
use serde_json::Value;

Check failure on line 9 in crates/kreuzberg-node/src/result.rs

View workflow job for this annotation

GitHub Actions / Node Build + Smoke (x86_64-unknown-linux-gnu)

unused import: `serde_json::Value`

#[napi(object)]
#[derive(serde::Serialize, serde::Deserialize)]
Expand Down Expand Up @@ -781,37 +781,3 @@
})
}
}

/// Recursively convert snake_case keys in a JSON Value to camelCase.
fn snake_to_camel(val: Value) -> Value {
match val {
Value::Object(map) => {
let mut new_map = serde_json::Map::with_capacity(map.len());
for (key, value) in map {
let new_key = to_camel_case(&key);
new_map.insert(new_key, snake_to_camel(value));
}
Value::Object(new_map)
}
Value::Array(arr) => Value::Array(arr.into_iter().map(snake_to_camel).collect()),
_ => val,
}
}

/// Simple snake_case to camelCase converter for keys.
fn to_camel_case(s: &str) -> String {
let mut camel = String::with_capacity(s.len());
let mut capitalize_next = false;

for c in s.chars() {
if c == '_' {
capitalize_next = true;
} else if capitalize_next {
camel.push(c.to_ascii_uppercase());
capitalize_next = false;
} else {
camel.push(c);
}
}
camel
}
73 changes: 73 additions & 0 deletions crates/kreuzberg/src/utils/json_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use serde_json::Value;

/// Recursively convert snake_case keys in a JSON Value to camelCase.
///
/// This is used by language bindings (Node.js, Go, Java, C#, etc.) to provide
/// a consistent camelCase API for consumers even though the Rust core uses snake_case.
pub fn snake_to_camel(val: Value) -> Value {
match val {
Value::Object(map) => {
let mut new_map = serde_json::Map::with_capacity(map.len());
for (key, value) in map {
let new_key = to_camel_case(&key);
new_map.insert(new_key, snake_to_camel(value));
}
Value::Object(new_map)
}
Value::Array(arr) => Value::Array(arr.into_iter().map(snake_to_camel).collect()),
_ => val,
}
}

/// snake_case to camelCase converter for keys.
fn to_camel_case(s: &str) -> String {
let mut camel = String::with_capacity(s.len());
let mut capitalize_next = false;

for c in s.chars() {
if c == '_' {
capitalize_next = true;
} else if capitalize_next {
camel.push(c.to_ascii_uppercase());
capitalize_next = false;
} else {
camel.push(c);
}
}
camel
}

#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;

#[test]
fn test_snake_to_camel_basic() {
let input = json!({
"first_name": "John",
"last_name": "Doe",
"nested_object": {
"street_address": "123 Main St"
},
"array_of_objects": [
{ "item_id": 1 },
{ "item_name": "item 2" }
]
});

let expected = json!({
"firstName": "John",
"lastName": "Doe",
"nestedObject": {
"streetAddress": "123 Main St"
},
"arrayOfObjects": [
{ "itemId": 1 },
{ "itemName": "item 2" }
]
});

assert_eq!(snake_to_camel(input), expected);
}
}
4 changes: 3 additions & 1 deletion crates/kreuzberg/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod quality;
#[cfg(feature = "quality")]
pub mod string_utils;

pub mod json_utils;
pub mod pool;
pub mod pool_sizing;
pub mod string_pool;
Expand All @@ -28,4 +29,5 @@ pub use pool::{

pub use pool_sizing::{PoolSizeHint, estimate_pool_size};

pub use string_pool::{InternedString, intern_language_code, intern_mime_type};

pub use json_utils::snake_to_camel;
Loading