diff --git a/Cargo.toml b/Cargo.toml index 8cdf611..7cae392 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,14 @@ [package] name = "simdjson-rust" -version = "0.3.0" +version = "0.3.0-alpha" authors = ["SunDoge <384813529@qq.com>"] edition = "2021" license = "Apache-2.0" +description = "Rust bindings for the simdjson project." +homepage = "https://crates.io/crates/simdjson-rust" +documentation = "https://docs.rs/simdjson-rust" +repository = "https://github.com/SunDoge/simdjson-rust" +readme = "README.md" exclude = [".github/", "examples/"] diff --git a/README.md b/README.md index 316a077..58e4c03 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ This crate currently uses `simdjson 3.2.3`. You can have a try and give feedback. +If you + +- find certain APIs are missing +- encounter memory errors +- experience performance degradation + +Please submit an issue. + ## Usage Add this to your `Cargo.toml` @@ -16,9 +24,9 @@ simdjson-rust = {git = "https://github.com/SunDoge/simdjson-rust"} Then, get started. ```rust -use simdjson_rust::{error::Result, ondemand::parser::Parser, padded_string::make_padded_string}; +use simdjson_rust::{ondemand::Parser, prelude::*}; -fn main() -> Result<()> { +fn main() -> simdjson_rust::Result<()> { let mut parser = Parser::default(); let ps = make_padded_string("[0,1,2,3]"); let mut doc = parser.iterate(&ps)?; diff --git a/examples/simple.rs b/examples/simple.rs index 138d270..6c6a4e5 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,7 +1,7 @@ -use simdjson_rust::{ondemand::Parser, prelude::*}; +use simdjson_rust::prelude::*; fn main() -> simdjson_rust::Result<()> { - let mut parser = Parser::default(); + let mut parser = ondemand::Parser::default(); let ps = make_padded_string("[0,1,2,3]"); let mut doc = parser.iterate(&ps)?; let mut array = doc.get_array()?; diff --git a/simdjson-sys/src/simdjson_c_api.cpp b/simdjson-sys/src/simdjson_c_api.cpp index 07cfecf..f2aabed 100644 --- a/simdjson-sys/src/simdjson_c_api.cpp +++ b/simdjson-sys/src/simdjson_c_api.cpp @@ -12,6 +12,15 @@ template inline U object_to_pointer(T &&t) { return reinterpret_cast(new T(std::move(t))); } +// template +// inline int enum_result_to_number_result(simdjson_result&& enum_result) { +// T inner; +// auto error = std::move(enum_result).get(inner); +// if (error == error_code::SUCCESS) { + +// } +// } + } // namespace #define IMPL_CLASS(name, type) \ @@ -41,10 +50,9 @@ template inline U object_to_pointer(T &&t) { } #define IMPL_AT_POINTER(self, type) \ - SJ_OD_value_result *self##_at_pointer(self *self, const char *s, \ - size_t len) { \ + SJ_OD_value_result *self##_at_pointer(self *r, const char *s, size_t len) { \ auto result = \ - reinterpret_cast(self)->at_pointer(std::string_view(s, len)); \ + reinterpret_cast(r)->at_pointer(std::string_view(s, len)); \ return object_to_pointer(std::move(result)); \ } @@ -69,12 +77,15 @@ IMPL_CLASS(SJ_OD_object_iterator, ondemand::object_iterator) IMPL_RESULT(SJ_OD_object_iterator, ondemand::object_iterator) IMPL_CLASS(SJ_OD_field, ondemand::field) IMPL_RESULT(SJ_OD_field, ondemand::field) +IMPL_CLASS(SJ_OD_number, ondemand::number) +IMPL_RESULT(SJ_OD_number, ondemand::number) IMPL_PRIMITIVE_RESULT(uint64_t) IMPL_PRIMITIVE_RESULT(int64_t) IMPL_PRIMITIVE_RESULT(double) IMPL_PRIMITIVE_RESULT(bool) IMPL_PRIMITIVE_RESULT(size_t) +IMPL_PRIMITIVE_RESULT(int) // SJ_padded_string *SJ_padded_string_new(const char *s, size_t len) { // return object_to_pointer(padded_string(s, len)); @@ -134,6 +145,9 @@ IMPL_GET(SJ_OD_value, ondemand::value, double, get_double) IMPL_GET(SJ_OD_value, ondemand::value, SJ_OD_raw_json_string, get_raw_json_string) IMPL_GET(SJ_OD_value, ondemand::value, STD_string_view, get_wobbly_string) +IMPL_GET(SJ_OD_value, ondemand::value, bool, is_null) +IMPL_GET(SJ_OD_value, ondemand::value, int, type) +IMPL_GET(SJ_OD_value, ondemand::value, SJ_OD_number, get_number) IMPL_AT_POINTER(SJ_OD_value, ondemand::value) // ondemand::document @@ -145,6 +159,9 @@ IMPL_GET(SJ_OD_document, ondemand::document, double, get_double) IMPL_GET(SJ_OD_document, ondemand::document, SJ_OD_raw_json_string, get_raw_json_string) IMPL_GET(SJ_OD_document, ondemand::document, STD_string_view, get_wobbly_string) +IMPL_GET(SJ_OD_document, ondemand::document, bool, is_null) +IMPL_GET(SJ_OD_document, ondemand::document, int, type) +IMPL_GET(SJ_OD_document, ondemand::document, SJ_OD_number, get_number) IMPL_AT_POINTER(SJ_OD_document, ondemand::document) STD_string_view_result *SJ_OD_value_get_string(SJ_OD_value *self, @@ -252,3 +269,18 @@ SJ_OD_value *SJ_OD_field_take_value(SJ_OD_field *self) { auto value = std::move(*field).value(); return object_to_pointer(std::move(value)); } + +// ondemand::number +#define IMPL_GET_PRIMITIVE(self, real_name, value, method) \ + value self##_##method(self *r) { \ + return reinterpret_cast(r)->method(); \ + } + +IMPL_GET_PRIMITIVE(SJ_OD_number, ondemand::number, uint64_t, get_uint64) +IMPL_GET_PRIMITIVE(SJ_OD_number, ondemand::number, int64_t, get_int64) +IMPL_GET_PRIMITIVE(SJ_OD_number, ondemand::number, double, get_double) + +int SJ_OD_number_get_number_type(SJ_OD_number *self) { + return static_cast( + reinterpret_cast(self)->get_number_type()); +} \ No newline at end of file diff --git a/simdjson-sys/src/simdjson_c_api.h b/simdjson-sys/src/simdjson_c_api.h index c87b9c2..4110a5b 100644 --- a/simdjson-sys/src/simdjson_c_api.h +++ b/simdjson-sys/src/simdjson_c_api.h @@ -24,7 +24,10 @@ value##_result *self##_##method(self *r); #define DEFINE_AT_POINTER(self) \ - SJ_OD_value_result *self##_at_pointer(self *self, const char *s, size_t len); + SJ_OD_value_result *self##_at_pointer(self *r, const char *s, size_t len); + +#define DEFINE_GET_PRIMITIVE(self, value, method) \ + value self##_##method(self *r); #ifdef __cplusplus extern "C" { @@ -52,19 +55,22 @@ DEFINE_CLASS(SJ_OD_object_iterator) DEFINE_RESULT(SJ_OD_object_iterator) DEFINE_CLASS(SJ_OD_field) DEFINE_RESULT(SJ_OD_field) +DEFINE_CLASS(SJ_OD_number) +DEFINE_RESULT(SJ_OD_number) DEFINE_PRIMITIVE_RESULT(uint64_t) DEFINE_PRIMITIVE_RESULT(int64_t) DEFINE_PRIMITIVE_RESULT(double) DEFINE_PRIMITIVE_RESULT(bool) DEFINE_PRIMITIVE_RESULT(size_t) +DEFINE_PRIMITIVE_RESULT(int) // padded_string -SJ_padded_string *SJ_padded_string_new(const char *s, size_t len); -SJ_padded_string_result * -SJ_padded_string_load(const char *path); // null terminated string. -size_t SJ_padded_string_length(const SJ_padded_string *ps); -const uint8_t *SJ_padded_string_u8data(const SJ_padded_string *ps); +// SJ_padded_string *SJ_padded_string_new(const char *s, size_t len); +// SJ_padded_string_result * +// SJ_padded_string_load(const char *path); // null terminated string. +// size_t SJ_padded_string_length(const SJ_padded_string *ps); +// const uint8_t *SJ_padded_string_u8data(const SJ_padded_string *ps); // ondemand::parser SJ_OD_parser *SJ_OD_parser_new(size_t max_capacity); @@ -84,6 +90,9 @@ DEFINE_GET(SJ_OD_value, SJ_OD_array, get_array) DEFINE_GET(SJ_OD_value, SJ_OD_object, get_object) DEFINE_GET(SJ_OD_value, SJ_OD_raw_json_string, get_raw_json_string) DEFINE_GET(SJ_OD_value, STD_string_view, get_wobbly_string) +DEFINE_GET(SJ_OD_value, bool, is_null) +DEFINE_GET(SJ_OD_value, int, type) +DEFINE_GET(SJ_OD_value, SJ_OD_number, get_number) DEFINE_AT_POINTER(SJ_OD_value) // ondemand::document @@ -96,6 +105,9 @@ DEFINE_GET(SJ_OD_document, SJ_OD_array, get_array) DEFINE_GET(SJ_OD_document, SJ_OD_object, get_object) DEFINE_GET(SJ_OD_document, SJ_OD_raw_json_string, get_raw_json_string) DEFINE_GET(SJ_OD_document, STD_string_view, get_wobbly_string) +DEFINE_GET(SJ_OD_document, bool, is_null) +DEFINE_GET(SJ_OD_document, int, type) +DEFINE_GET(SJ_OD_document, SJ_OD_number, get_number) DEFINE_AT_POINTER(SJ_OD_document) // get_string is special. @@ -151,6 +163,12 @@ STD_string_view_result *SJ_OD_field_unescaped_key(SJ_OD_field *self, SJ_OD_value *SJ_OD_field_value(SJ_OD_field *self); SJ_OD_value *SJ_OD_field_take_value(SJ_OD_field *self); +// ondemand::number +DEFINE_GET_PRIMITIVE(SJ_OD_number, int, get_number_type) +DEFINE_GET_PRIMITIVE(SJ_OD_number, uint64_t, get_uint64) +DEFINE_GET_PRIMITIVE(SJ_OD_number, int64_t, get_int64) +DEFINE_GET_PRIMITIVE(SJ_OD_number, double, get_double) + #ifdef __cplusplus } #endif diff --git a/src/ondemand/document.rs b/src/ondemand/document.rs index 22f6d00..5f4562c 100644 --- a/src/ondemand/document.rs +++ b/src/ondemand/document.rs @@ -2,7 +2,7 @@ use std::{marker::PhantomData, ptr::NonNull}; use simdjson_sys as ffi; -use super::{array::Array, object::Object, parser::Parser, value::Value}; +use super::{array::Array, number::Number, object::Object, parser::Parser, value::Value, JsonType}; use crate::{ error::Result, macros::{impl_drop, map_result}, @@ -116,6 +116,34 @@ impl<'p, 's> Document<'p, 's> { ) .map(Value::new) } + + pub fn get_number<'a>(&mut self) -> Result> { + map_result!( + ffi::SJ_OD_document_get_number(self.ptr.as_mut()), + ffi::SJ_OD_number_result_error, + ffi::SJ_OD_number_result_value_unsafe + ) + .map(Number::new) + } + + pub fn is_null(&mut self) -> Result { + map_result!( + primitive, + ffi::SJ_OD_document_is_null(self.ptr.as_mut()), + ffi::bool_result_error, + ffi::bool_result_value_unsafe + ) + } + + pub fn json_type(&mut self) -> Result { + let json_type = map_result!( + primitive, + ffi::SJ_OD_document_type(self.ptr.as_mut()), + ffi::int_result_error, + ffi::int_result_value_unsafe + )?; + Ok(JsonType::from(json_type)) + } } impl_drop!(Document<'p, 's>, ffi::SJ_OD_document_free); diff --git a/src/ondemand/json_type.rs b/src/ondemand/json_type.rs new file mode 100644 index 0000000..52a24f6 --- /dev/null +++ b/src/ondemand/json_type.rs @@ -0,0 +1,41 @@ +#[derive(Debug, PartialEq)] +pub enum JsonType { + Array = 1, + Object, + Number, + String, + Boolean, + Null, +} + +impl From for JsonType { + fn from(value: i32) -> Self { + match value { + 1 => JsonType::Array, + 2 => JsonType::Object, + 3 => JsonType::Number, + 4 => JsonType::String, + 5 => JsonType::Boolean, + 6 => JsonType::Null, + _ => panic!("Invalid JsonType value: {}", value), + } + } +} + +#[derive(Debug, PartialEq)] +pub enum NumberType { + FloatingPointNumber = 1, + SignedInteger, + UnsignedInteger, +} + +impl From for NumberType { + fn from(value: i32) -> Self { + match value { + 1 => NumberType::FloatingPointNumber, + 2 => NumberType::SignedInteger, + 3 => NumberType::UnsignedInteger, + _ => panic!("Invalid NumberType value: {}", value), + } + } +} diff --git a/src/ondemand/mod.rs b/src/ondemand/mod.rs index 676f185..a35efd0 100644 --- a/src/ondemand/mod.rs +++ b/src/ondemand/mod.rs @@ -2,6 +2,8 @@ pub(crate) mod array; pub(crate) mod array_iterator; pub(crate) mod document; pub(crate) mod field; +mod json_type; +mod number; pub(crate) mod object; pub(crate) mod object_iterator; pub(crate) mod parser; @@ -11,6 +13,7 @@ pub use array::Array; pub use array_iterator::ArrayIterator; pub use document::Document; pub use field::Field; +pub use json_type::{JsonType, NumberType}; pub use object::Object; pub use object_iterator::ObjectIterator; pub use parser::Parser; diff --git a/src/ondemand/number.rs b/src/ondemand/number.rs new file mode 100644 index 0000000..b9814cd --- /dev/null +++ b/src/ondemand/number.rs @@ -0,0 +1,38 @@ +use std::{marker::PhantomData, ptr::NonNull}; + +use simdjson_sys as ffi; + +use super::{Document, NumberType}; +use crate::macros::impl_drop; + +pub struct Number<'a> { + ptr: NonNull, + _doc: PhantomData<&'a mut Document<'a, 'a>>, +} + +impl<'a> Number<'a> { + pub fn new(ptr: NonNull) -> Self { + Self { + ptr, + _doc: PhantomData, + } + } + + pub fn get_uint64(&mut self) -> u64 { + unsafe { ffi::SJ_OD_number_get_uint64(self.ptr.as_mut()) } + } + + pub fn get_int64(&mut self) -> i64 { + unsafe { ffi::SJ_OD_number_get_int64(self.ptr.as_mut()) } + } + + pub fn get_double(&mut self) -> f64 { + unsafe { ffi::SJ_OD_number_get_double(self.ptr.as_mut()) } + } + + pub fn get_number_type(&mut self) -> NumberType { + unsafe { ffi::SJ_OD_number_get_number_type(self.ptr.as_mut()) }.into() + } +} + +impl_drop!(Number<'a>, ffi::SJ_OD_number_free); diff --git a/src/ondemand/value.rs b/src/ondemand/value.rs index 0ea5ee1..f9959df 100644 --- a/src/ondemand/value.rs +++ b/src/ondemand/value.rs @@ -2,7 +2,7 @@ use std::{marker::PhantomData, ptr::NonNull}; use simdjson_sys as ffi; -use super::{array::Array, document::Document, object::Object}; +use super::{array::Array, document::Document, number::Number, object::Object, JsonType}; use crate::{ error::Result, macros::{impl_drop, map_result}, @@ -76,6 +76,15 @@ impl<'a> Value<'a> { .map(Object::new) } + pub fn get_number(&mut self) -> Result> { + map_result!( + ffi::SJ_OD_value_get_number(self.ptr.as_mut()), + ffi::SJ_OD_number_result_error, + ffi::SJ_OD_number_result_value_unsafe + ) + .map(Number::new) + } + pub fn get_string(&mut self, allow_replacement: bool) -> Result<&'a str> { let sv = map_result!( ffi::SJ_OD_value_get_string(self.ptr.as_mut(), allow_replacement), @@ -97,6 +106,25 @@ impl<'a> Value<'a> { ) .map(Value::new) } + + pub fn is_null(&mut self) -> Result { + map_result!( + primitive, + ffi::SJ_OD_value_is_null(self.ptr.as_mut()), + ffi::bool_result_error, + ffi::bool_result_value_unsafe + ) + } + + pub fn json_type(&mut self) -> Result { + let json_type = map_result!( + primitive, + ffi::SJ_OD_value_type(self.ptr.as_mut()), + ffi::int_result_error, + ffi::int_result_value_unsafe + )?; + Ok(JsonType::from(json_type)) + } } impl_drop!(Value<'a>, ffi::SJ_OD_value_free); diff --git a/src/prelude.rs b/src/prelude.rs index f519ca8..3ff7085 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,4 @@ -pub use crate::padded_string::{ - load_padded_string, make_padded_string, IntoPaddedString, ToPaddedString, +pub use crate::{ + ondemand, + padded_string::{load_padded_string, make_padded_string, IntoPaddedString, ToPaddedString}, };