Skip to content

Commit

Permalink
Simplify yyjson iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
ijl committed Jan 4, 2023
1 parent 728c464 commit f36a421
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 67 deletions.
2 changes: 0 additions & 2 deletions script/generate-yyjson
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
9 changes: 4 additions & 5 deletions src/deserialize/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,15 @@ impl<'de> Visitor<'de> for JsonValue {
let dict_ptr = ffi!(PyDict_New());
while let Some(key) = map.next_key::<beef::lean::Cow<str>>()? {
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))
}
Expand Down
58 changes: 11 additions & 47 deletions src/deserialize/yyjson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
}
Expand All @@ -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<NonNull<pyo3_ffi::PyObject>, DeserializeError<'static>> {
Expand Down Expand Up @@ -156,15 +134,12 @@ fn parse_yy_array(elem: *mut yyjson_val) -> NonNull<pyo3_ffi::PyObject> {
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)
}
Expand All @@ -177,27 +152,16 @@ fn parse_yy_object(elem: *mut yyjson_val) -> NonNull<pyo3_ffi::PyObject> {
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)
}
Expand Down
8 changes: 8 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() }
Expand Down
13 changes: 0 additions & 13 deletions src/yyjson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

0 comments on commit f36a421

Please sign in to comment.