From 0ada8f37dfb0bd7d7ff9bc11ba390fffa4c1dfe7 Mon Sep 17 00:00:00 2001 From: Blayne Chard Date: Fri, 5 Nov 2021 00:06:23 +1300 Subject: [PATCH] refactor: split list and tuple serialization --- bindings/python/src/ser.rs | 45 ++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/bindings/python/src/ser.rs b/bindings/python/src/ser.rs index 25264279..afb3c806 100644 --- a/bindings/python/src/ser.rs +++ b/bindings/python/src/ser.rs @@ -149,16 +149,11 @@ impl Serialize for SerializePyObject { map.end() } } - ObjectType::Tuple | ObjectType::List => { + ObjectType::List => { if self.recursion_depth == RECURSION_LIMIT { return Err(ser::Error::custom("Recursion limit reached")); } - - let length = match self.object_type { - ObjectType::Tuple => unsafe { PyTuple_GET_SIZE(self.object) as usize }, - ObjectType::List => unsafe { PyList_GET_SIZE(self.object) as usize }, - _ => return Err(ser::Error::custom("Object is not a list or tuple")), - }; + let length = unsafe { PyList_GET_SIZE(self.object) as usize }; if length == 0 { serializer.serialize_seq(Some(0))?.end() } else { @@ -166,13 +161,35 @@ impl Serialize for SerializePyObject { let mut ob_type = ObjectType::Str; let mut sequence = serializer.serialize_seq(Some(length))?; for i in 0..length { - let elem = match self.object_type { - ObjectType::Tuple => unsafe { - PyTuple_GET_ITEM(self.object, i as isize) - }, - ObjectType::List => unsafe { PyList_GET_ITEM(self.object, i as isize) }, - _ => return Err(ser::Error::custom("Object is not a list or tuple")), - }; + let elem = unsafe { PyList_GET_ITEM(self.object, i as isize) }; + let current_ob_type = unsafe { Py_TYPE(elem) }; + if current_ob_type != type_ptr { + type_ptr = current_ob_type; + ob_type = get_object_type(current_ob_type); + } + #[allow(clippy::integer_arithmetic)] + sequence.serialize_element(&SerializePyObject::with_obtype( + elem, + ob_type.clone(), + self.recursion_depth + 1, + ))?; + } + sequence.end() + } + } + ObjectType::Tuple => { + if self.recursion_depth == RECURSION_LIMIT { + return Err(ser::Error::custom("Recursion limit reached")); + } + let length = unsafe { PyTuple_GET_SIZE(self.object) as usize }; + if length == 0 { + serializer.serialize_seq(Some(0))?.end() + } else { + let mut type_ptr = std::ptr::null_mut(); + let mut ob_type = ObjectType::Str; + let mut sequence = serializer.serialize_seq(Some(length))?; + for i in 0..length { + let elem = unsafe { PyTuple_GET_ITEM(self.object, i as isize) }; let current_ob_type = unsafe { Py_TYPE(elem) }; if current_ob_type != type_ptr { type_ptr = current_ob_type;