diff --git a/script/generate-yyjson b/script/generate-yyjson index 7e9e3e14..793ad220 100755 --- a/script/generate-yyjson +++ b/script/generate-yyjson @@ -16,9 +16,7 @@ bindgen \ --allowlist-function=yyjson_doc_free \ --allowlist-function=yyjson_read_opts \ --allowlist-type=yyjson_alc \ - --allowlist-type=yyjson_arr_iter \ --allowlist-type=yyjson_doc \ - --allowlist-type=yyjson_obj_iter \ --allowlist-type=yyjson_read_code \ --allowlist-type=yyjson_read_err \ --allowlist-type=yyjson_val \ diff --git a/src/deserialize/json.rs b/src/deserialize/json.rs index f637954f..f50ece68 100644 --- a/src/deserialize/json.rs +++ b/src/deserialize/json.rs @@ -127,16 +127,15 @@ impl<'de> Visitor<'de> for JsonValue { let dict_ptr = ffi!(PyDict_New()); while let Some(key) = map.next_key::>()? { let (pykey, pyhash) = get_unicode_key(&key); - let value = map.next_value_seed(self)?; + let pyval = map.next_value_seed(self)?; let _ = ffi!(_PyDict_SetItem_KnownHash( dict_ptr, pykey, - value.as_ptr(), + pyval.as_ptr(), pyhash )); - // counter Py_INCREF in insertdict - ffi!(Py_DECREF(pykey)); - ffi!(Py_DECREF(value.as_ptr())); + py_decref_without_destroy!(pykey); + py_decref_without_destroy!(pyval.as_ptr()); } Ok(nonnull!(dict_ptr)) } diff --git a/src/deserialize/yyjson.rs b/src/deserialize/yyjson.rs index af78ea47..eacc267d 100644 --- a/src/deserialize/yyjson.rs +++ b/src/deserialize/yyjson.rs @@ -35,10 +35,6 @@ fn unsafe_yyjson_get_len(val: *mut yyjson_val) -> usize { unsafe { ((*val).tag >> YYJSON_TAG_BIT) as usize } } -fn yyjson_obj_iter_get_val(key: *mut yyjson_val) -> *mut yyjson_val { - unsafe { key.add(1) } -} - fn unsafe_yyjson_get_first(ctn: *mut yyjson_val) -> *mut yyjson_val { unsafe { ctn.add(1) } } @@ -61,24 +57,6 @@ fn unsafe_yyjson_get_next(val: *mut yyjson_val) -> *mut yyjson_val { } } -fn yyjson_arr_iter_next(iter: &mut yyjson_arr_iter) -> *mut yyjson_val { - unsafe { - let val = (*iter).cur; - (*iter).cur = unsafe_yyjson_get_next(val); - (*iter).idx += 1; - val - } -} - -fn yyjson_obj_iter_next(iter: &mut yyjson_obj_iter) -> *mut yyjson_val { - unsafe { - let key = (*iter).cur; - (*iter).cur = unsafe_yyjson_get_next(key.add(1)); - (*iter).idx += 1; - key - } -} - pub fn deserialize_yyjson( data: &'static str, ) -> Result, DeserializeError<'static>> { @@ -156,15 +134,12 @@ fn parse_yy_array(elem: *mut yyjson_val) -> NonNull { if len == 0 { return nonnull!(list); } - let mut iter: yyjson_arr_iter = yyjson_arr_iter { - idx: 0, - max: len, - cur: unsafe_yyjson_get_first(elem), - }; + let mut cur = unsafe_yyjson_get_first(elem); for idx in 0..=len - 1 { - let val = yyjson_arr_iter_next(&mut iter); - let each = parse_node(val); - ffi!(PyList_SET_ITEM(list, idx as isize, each.as_ptr())); + let next = unsafe_yyjson_get_next(cur); + let val = parse_node(cur).as_ptr(); + ffi!(PyList_SET_ITEM(list, idx as isize, val)); + cur = next; } nonnull!(list) } @@ -177,27 +152,16 @@ fn parse_yy_object(elem: *mut yyjson_val) -> NonNull { if len == 0 { return nonnull!(ffi!(PyDict_New())); } + let mut key = unsafe_yyjson_get_first(elem); let dict = ffi!(_PyDict_NewPresized(len as isize)); - let mut iter = yyjson_obj_iter { - idx: 0, - max: len, - cur: unsafe_yyjson_get_first(elem), - obj: elem, - }; for _ in 0..=len - 1 { - let key = yyjson_obj_iter_next(&mut iter); - let val = yyjson_obj_iter_get_val(key); let key_str = str_from_slice!((*key).uni.str_ as *const u8, unsafe_yyjson_get_len(key)); let (pykey, pyhash) = get_unicode_key(key_str); - let pyval = parse_node(val); - let _ = ffi!(_PyDict_SetItem_KnownHash( - dict, - pykey, - pyval.as_ptr(), - pyhash - )); - ffi!(Py_DECREF(pykey)); - ffi!(Py_DECREF(pyval.as_ptr())); + let pyval = parse_node(key.add(1)).as_ptr(); + let _ = ffi!(_PyDict_SetItem_KnownHash(dict, pykey, pyval, pyhash)); + py_decref_without_destroy!(pykey); + py_decref_without_destroy!(pyval); + key = unsafe_yyjson_get_next(key.add(1)); } nonnull!(dict) } diff --git a/src/util.rs b/src/util.rs index 91676746..83fb6d4e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -44,6 +44,14 @@ macro_rules! str_from_slice { }; } +macro_rules! py_decref_without_destroy { + ($op:expr) => { + unsafe { + (*$op).ob_refcnt -= 1; + } + }; +} + macro_rules! ffi { ($fn:ident()) => { unsafe { pyo3_ffi::$fn() } diff --git a/src/yyjson.rs b/src/yyjson.rs index 9f2670b5..f2d64d01 100644 --- a/src/yyjson.rs +++ b/src/yyjson.rs @@ -69,16 +69,3 @@ pub struct yyjson_doc { pub val_read: usize, pub str_pool: *mut ::std::os::raw::c_char, } -#[repr(C)] -pub struct yyjson_arr_iter { - pub idx: usize, - pub max: usize, - pub cur: *mut yyjson_val, -} -#[repr(C)] -pub struct yyjson_obj_iter { - pub idx: usize, - pub max: usize, - pub cur: *mut yyjson_val, - pub obj: *mut yyjson_val, -}