#[cxx::bridge(namespace = "simdjson_sys::dom")]
pub mod dom_ffi {
struct TapeView<'a> {
tape: &'a [u64],
string_buf: &'a [u8],
}
unsafe extern "C++" {
include!("simdjson.h");
include!("simdjson_dom_bridge.h");
#[namespace = "simdjson::dom"]
type parser;
fn parser_new(max_capacity: usize) -> UniquePtr<parser>;
#[allow(clippy::missing_safety_doc)]
unsafe fn parser_parse(
parser: Pin<&mut parser>,
json: &[u8],
realloc_if_needed: bool,
) -> i32;
#[allow(clippy::missing_safety_doc)]
unsafe fn parser_get_tape_view(parser: &parser) -> TapeView<'_>;
}
}
pub const SIMDJSON_PADDING: usize = 64;
pub const SIMDJSON_MAXSIZE_BYTES: usize = 0xFFFFFFFF;
pub const DEFAULT_BATCH_SIZE: usize = 1000000;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parser_parses_string_and_exposes_tape_view() {
let mut parser = dom_ffi::parser_new(SIMDJSON_MAXSIZE_BYTES);
let json = String::from(r#"{"answer":42,"message":"ok"}"#);
assert_eq!(
unsafe { dom_ffi::parser_parse(parser.pin_mut(), json.as_bytes(), true) },
0
);
let view = unsafe { dom_ffi::parser_get_tape_view(parser.as_ref().unwrap()) };
assert!(!view.tape.is_empty());
assert_eq!(view.tape[0] >> 56, u64::from(b'r'));
assert!(!view.string_buf.is_empty());
}
#[test]
fn string_view_contains_only_initialized_prefix() {
let mut parser = dom_ffi::parser_new(SIMDJSON_MAXSIZE_BYTES);
for (json, expected) in [
(r#"["longer string", "x"]"#, 24),
("[2449958197289549824]", 0),
(r#""x""#, 6),
("null", 0),
] {
assert_eq!(
unsafe { dom_ffi::parser_parse(parser.pin_mut(), json.as_bytes(), true) },
0
);
let view = unsafe { dom_ffi::parser_get_tape_view(parser.as_ref().unwrap()) };
assert_eq!(view.string_buf.len(), expected, "{json}");
}
}
}