Skip to content
Snippets Groups Projects
Commit b6ef49274d29 authored by ijl's avatar ijl
Browse files

Split to additional serializers

parent d0519d5809b7
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,6 @@
rm -f target/wheels/*
maturin build --no-sdist --manylinux 1 -i python3 --release "$@"
maturin build --no-sdist --manylinux 2014 -i python3 --release "$@"
pip install --force $(find target/wheels -name "*cp3*")
......@@ -119,10 +119,10 @@
where
E: de::Error,
{
Ok(nonnull!(str_to_pyobject!(value.as_str())))
Ok(nonnull!(unicode_from_str(value.as_str())))
}
fn visit_borrowed_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
......@@ -123,13 +123,13 @@
}
fn visit_borrowed_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(nonnull!(str_to_pyobject!(value)))
Ok(nonnull!(unicode_from_str(value)))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
......@@ -130,10 +130,10 @@
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(nonnull!(str_to_pyobject!(value)))
Ok(nonnull!(unicode_from_str(value)))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
......@@ -178,7 +178,7 @@
let entry = map.entry(&hash).or_insert_with(
|| hash,
|| {
let pyob = str_to_pyobject!(&key);
let pyob = unicode_from_str(&key);
CachedKey::new(pyob, hash_str(pyob))
},
);
......@@ -187,7 +187,7 @@
pyhash = tmp.1;
}
} else {
pykey = str_to_pyobject!(&key);
pykey = unicode_from_str(&key);
pyhash = hash_str(pykey);
}
let value = map.next_value_seed(self)?;
......
......@@ -154,6 +154,7 @@
}
#[cold]
#[inline(never)]
fn raise_loads_exception(msg: Cow<str>) -> *mut PyObject {
unsafe {
let err_msg =
......@@ -171,6 +172,7 @@
}
#[cold]
#[inline(never)]
fn raise_dumps_exception(msg: Cow<str>) -> *mut PyObject {
unsafe {
let err_msg =
......
......@@ -11,7 +11,85 @@
use std::ptr::NonNull;
pub struct DataclassSerializer {
pub struct DataclassFastSerializer {
dict: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
}
impl DataclassFastSerializer {
pub fn new(
dict: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
) -> Self {
DataclassFastSerializer {
dict: dict,
opts: opts,
default_calls: default_calls,
recursion: recursion,
default: default,
}
}
}
impl<'p> Serialize for DataclassFastSerializer {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let len = unsafe { PyDict_GET_SIZE(self.dict) as usize };
if unlikely!(len == 0) {
return serializer.serialize_map(Some(0)).unwrap().end();
}
let mut map = serializer.serialize_map(None).unwrap();
let mut pos = 0isize;
let mut str_size: pyo3::ffi::Py_ssize_t = 0;
let mut key: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
let mut value: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
for _ in 0..=len - 1 {
unsafe {
pyo3::ffi::_PyDict_Next(
self.dict,
&mut pos,
&mut key,
&mut value,
std::ptr::null_mut(),
)
};
if unlikely!(ob_type!(key) != STR_TYPE) {
err!(KEY_MUST_BE_STR)
}
{
let data = read_utf8_from_str(key, &mut str_size);
if unlikely!(data.is_null()) {
err!(INVALID_STR)
}
let key_as_str = str_from_slice!(data, str_size);
if unlikely!(key_as_str.as_bytes()[0] == b'_') {
continue;
}
map.serialize_key(key_as_str).unwrap();
}
map.serialize_value(&PyObjectSerializer::new(
value,
self.opts,
self.default_calls,
self.recursion + 1,
self.default,
))?;
}
map.end()
}
}
pub struct DataclassFallbackSerializer {
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
......@@ -19,7 +97,7 @@
default: Option<NonNull<pyo3::ffi::PyObject>>,
}
impl DataclassSerializer {
impl DataclassFallbackSerializer {
pub fn new(
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
......@@ -27,7 +105,7 @@
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
) -> Self {
DataclassSerializer {
DataclassFallbackSerializer {
ptr: ptr,
opts: opts,
default_calls: default_calls,
......@@ -37,7 +115,7 @@
}
}
impl<'p> Serialize for DataclassSerializer {
impl<'p> Serialize for DataclassFallbackSerializer {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
......@@ -84,7 +162,7 @@
let value = ffi!(PyObject_GetAttr(self.ptr, attr));
ffi!(Py_DECREF(value));
map.serialize_value(&SerializePyObject::new(
map.serialize_value(&PyObjectSerializer::new(
value,
self.opts,
self.default_calls,
......
......@@ -56,6 +56,7 @@
}
}
impl<'p> Serialize for Date {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
......@@ -108,6 +109,7 @@
}
impl<'p> Serialize for Time {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
......@@ -266,6 +268,7 @@
}
impl<'p> Serialize for DateTime {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
......
......@@ -8,10 +8,11 @@
use std::ptr::NonNull;
macro_rules! obj_name {
($obj:expr) => {
unsafe { CStr::from_ptr((*$obj).tp_name).to_string_lossy() }
};
#[cold]
#[inline(never)]
fn format_err(ptr: *mut pyo3::ffi::PyObject) -> String {
let name = unsafe { CStr::from_ptr((*ob_type!(ptr)).tp_name).to_string_lossy() };
format_args!("Type is not JSON serializable: {}", name).to_string()
}
pub struct DefaultSerializer {
......@@ -57,8 +58,5 @@
std::ptr::null_mut() as *mut pyo3::ffi::PyObject
));
if unlikely!(default_obj.is_null()) {
err!(format_args!(
"Type is not JSON serializable: {}",
obj_name!(ob_type!(self.ptr))
))
err!(format_err(self.ptr))
} else {
......@@ -64,5 +62,5 @@
} else {
let res = SerializePyObject::new(
let res = PyObjectSerializer::new(
default_obj,
self.opts,
self.default_calls + 1,
......@@ -74,10 +72,7 @@
res
}
}
None => err!(format_args!(
"Type is not JSON serializable: {}",
obj_name!(ob_type!(self.ptr))
)),
None => err!(format_err(self.ptr)),
}
}
}
......@@ -13,6 +13,79 @@
use smallvec::SmallVec;
use std::ptr::NonNull;
pub struct Dict {
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
len: usize,
}
impl Dict {
pub fn new(
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
len: usize,
) -> Self {
Dict {
ptr: ptr,
opts: opts,
default_calls: default_calls,
recursion: recursion,
default: default,
len: len,
}
}
}
impl<'p> Serialize for Dict {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(None).unwrap();
let mut pos = 0isize;
let mut str_size: pyo3::ffi::Py_ssize_t = 0;
let mut key: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
let mut value: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
for _ in 0..=self.len - 1 {
unsafe {
pyo3::ffi::_PyDict_Next(
self.ptr,
&mut pos,
&mut key,
&mut value,
std::ptr::null_mut(),
)
};
if unlikely!(ob_type!(key) != STR_TYPE) {
err!(KEY_MUST_BE_STR)
}
{
let data = read_utf8_from_str(key, &mut str_size);
if unlikely!(data.is_null()) {
err!(INVALID_STR)
}
map.serialize_key(str_from_slice!(data, str_size)).unwrap();
}
map.serialize_value(&PyObjectSerializer::new(
value,
self.opts,
self.default_calls,
self.recursion + 1,
self.default,
))?;
}
map.end()
}
}
pub struct DictSortedKey {
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
......@@ -80,7 +153,7 @@
for (key, val) in items.iter() {
map.serialize_entry(
key,
&SerializePyObject::new(
&PyObjectSerializer::new(
*val,
self.opts,
self.default_calls,
......@@ -101,7 +174,7 @@
UnsupportedType,
}
pub struct NonStrKey {
pub struct DictNonStrKey {
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
......@@ -110,7 +183,7 @@
len: usize,
}
impl NonStrKey {
impl DictNonStrKey {
pub fn new(
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
......@@ -119,7 +192,7 @@
default: Option<NonNull<pyo3::ffi::PyObject>>,
len: usize,
) -> Self {
NonStrKey {
DictNonStrKey {
ptr: ptr,
opts: opts,
default_calls: default_calls,
......@@ -225,7 +298,7 @@
}
}
impl<'p> Serialize for NonStrKey {
impl<'p> Serialize for DictNonStrKey {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
......@@ -283,7 +356,7 @@
for (key, val) in items.iter() {
map.serialize_entry(
str_from_slice!(key.as_ptr(), key.len()),
&SerializePyObject::new(
&PyObjectSerializer::new(
*val,
self.opts,
self.default_calls,
......
......@@ -7,4 +7,5 @@
use crate::serialize::datetime::*;
use crate::serialize::default::*;
use crate::serialize::dict::*;
use crate::serialize::list::*;
use crate::serialize::numpy::*;
......@@ -10,4 +11,5 @@
use crate::serialize::numpy::*;
use crate::serialize::str::*;
use crate::serialize::tuple::*;
use crate::serialize::uuid::*;
use crate::serialize::writer::*;
......@@ -38,7 +40,7 @@
_ => {}
}
buf.prefetch();
let obj = SerializePyObject::with_obtype(ptr, obtype, opts, 0, 0, default);
let obj = PyObjectSerializer::with_obtype(ptr, obtype, opts, 0, 0, default);
let res;
if likely!(opts & INDENT_2 != INDENT_2) {
res = serde_json::to_writer(&mut buf, &obj);
......@@ -127,7 +129,7 @@
ObType::Uuid
} else if (*(ob_type as *mut LocalPyTypeObject)).ob_type == ENUM_TYPE {
ObType::Enum
} else if is_subclass!(ob_type, Py_TPFLAGS_UNICODE_SUBCLASS)
&& opts & PASSTHROUGH_SUBCLASS == 0
} else if opts & PASSTHROUGH_SUBCLASS == 0
&& is_subclass!(ob_type, Py_TPFLAGS_UNICODE_SUBCLASS)
{
ObType::StrSubclass
......@@ -132,6 +134,6 @@
{
ObType::StrSubclass
} else if is_subclass!(ob_type, Py_TPFLAGS_LONG_SUBCLASS)
&& opts & PASSTHROUGH_SUBCLASS == 0
} else if opts & PASSTHROUGH_SUBCLASS == 0
&& is_subclass!(ob_type, Py_TPFLAGS_LONG_SUBCLASS)
{
ObType::Int
......@@ -136,6 +138,6 @@
{
ObType::Int
} else if is_subclass!(ob_type, Py_TPFLAGS_LIST_SUBCLASS)
&& opts & PASSTHROUGH_SUBCLASS == 0
} else if opts & PASSTHROUGH_SUBCLASS == 0
&& is_subclass!(ob_type, Py_TPFLAGS_LIST_SUBCLASS)
{
ObType::List
......@@ -140,7 +142,7 @@
{
ObType::List
} else if is_subclass!(ob_type, Py_TPFLAGS_DICT_SUBCLASS)
&& opts & PASSTHROUGH_SUBCLASS == 0
} else if opts & PASSTHROUGH_SUBCLASS == 0
&& is_subclass!(ob_type, Py_TPFLAGS_DICT_SUBCLASS)
{
ObType::Dict
} else if opts & PASSTHROUGH_DATACLASS == 0
......@@ -157,7 +159,7 @@
}
}
pub struct SerializePyObject {
pub struct PyObjectSerializer {
ptr: *mut pyo3::ffi::PyObject,
obtype: ObType,
opts: Opt,
......@@ -166,7 +168,7 @@
default: Option<NonNull<pyo3::ffi::PyObject>>,
}
impl SerializePyObject {
impl PyObjectSerializer {
#[inline]
pub fn new(
ptr: *mut pyo3::ffi::PyObject,
......@@ -175,7 +177,7 @@
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
) -> Self {
SerializePyObject {
PyObjectSerializer {
ptr: ptr,
obtype: pyobject_to_obtype(ptr, opts),
opts: opts,
......@@ -194,7 +196,7 @@
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
) -> Self {
SerializePyObject {
PyObjectSerializer {
ptr: ptr,
obtype: obtype,
opts: opts,
......@@ -205,7 +207,7 @@
}
}
impl<'p> Serialize for SerializePyObject {
impl<'p> Serialize for PyObjectSerializer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
......@@ -219,14 +221,7 @@
}
serializer.serialize_str(str_from_slice!(uni, str_size))
}
ObType::StrSubclass => {
let mut str_size: pyo3::ffi::Py_ssize_t = 0;
let uni = ffi!(PyUnicode_AsUTF8AndSize(self.ptr, &mut str_size)) as *const u8;
if unlikely!(uni.is_null()) {
err!(INVALID_STR)
}
serializer.serialize_str(str_from_slice!(uni, str_size))
}
ObType::StrSubclass => StrSubclassSerializer::new(self.ptr).serialize(serializer),
ObType::Int => {
let val = ffi!(PyLong_AsLongLong(self.ptr));
if unlikely!(val == -1) && !ffi!(PyErr_Occurred()).is_null() {
......@@ -256,12 +251,5 @@
if unlikely!(len == 0) {
serializer.serialize_map(Some(0)).unwrap().end()
} else if likely!(self.opts & SORT_OR_NON_STR_KEYS == 0) {
let mut map = serializer.serialize_map(None).unwrap();
let mut pos = 0isize;
let mut str_size: pyo3::ffi::Py_ssize_t = 0;
let mut key: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
let mut value: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
for _ in 0..=len - 1 {
unsafe {
pyo3::ffi::_PyDict_Next(
Dict::new(
self.ptr,
......@@ -267,22 +255,3 @@
self.ptr,
&mut pos,
&mut key,
&mut value,
std::ptr::null_mut(),
)
};
if unlikely!(ob_type!(key) != STR_TYPE) {
err!(KEY_MUST_BE_STR)
}
{
let data = read_utf8_from_str(key, &mut str_size);
if unlikely!(data.is_null()) {
err!(INVALID_STR)
}
map.serialize_key(str_from_slice!(data, str_size)).unwrap();
}
map.serialize_value(&SerializePyObject::new(
value,
self.opts,
self.default_calls,
......@@ -287,4 +256,4 @@
self.opts,
self.default_calls,
self.recursion + 1,
self.recursion,
self.default,
......@@ -290,5 +259,5 @@
self.default,
))?;
}
map.end()
len,
)
.serialize(serializer)
} else if self.opts & NON_STR_KEYS != 0 {
......@@ -294,5 +263,5 @@
} else if self.opts & NON_STR_KEYS != 0 {
NonStrKey::new(
DictNonStrKey::new(
self.ptr,
self.opts,
self.default_calls,
......@@ -318,6 +287,6 @@
err!(RECURSION_LIMIT_REACHED)
}
let len = ffi!(PyList_GET_SIZE(self.ptr)) as usize;
if len == 0 {
if unlikely!(len == 0) {
serializer.serialize_seq(Some(0)).unwrap().end()
} else {
......@@ -322,21 +291,6 @@
serializer.serialize_seq(Some(0)).unwrap().end()
} else {
let mut type_ptr = std::ptr::null_mut();
let mut ob_type = ObType::Str;
let mut seq = serializer.serialize_seq(None).unwrap();
for i in 0..=len - 1 {
let elem = unsafe {
*(*(self.ptr as *mut pyo3::ffi::PyListObject))
.ob_item
.offset(i as isize)
};
if ob_type!(elem) != type_ptr {
type_ptr = ob_type!(elem);
ob_type = pyobject_to_obtype(elem, self.opts);
}
seq.serialize_element(&SerializePyObject::with_obtype(
elem,
ob_type,
ListSerializer::new(
self.ptr,
self.opts,
self.default_calls,
......@@ -341,4 +295,4 @@
self.opts,
self.default_calls,
self.recursion + 1,
self.recursion,
self.default,
......@@ -344,6 +298,6 @@
self.default,
))?;
}
seq.end()
len,
)
.serialize(serializer)
}
}
......@@ -348,9 +302,6 @@
}
}
ObType::Tuple => {
let mut seq = serializer.serialize_seq(None).unwrap();
for elem in PyTupleIterator::new(self.ptr) {
seq.serialize_element(&SerializePyObject::new(
elem.as_ptr(),
ObType::Tuple => TupleSerializer::new(
self.ptr,
self.opts,
self.default_calls,
......@@ -355,4 +306,4 @@
self.opts,
self.default_calls,
self.recursion + 1,
self.recursion,
self.default,
......@@ -358,10 +309,8 @@
self.default,
))?
}
seq.end()
}
)
.serialize(serializer),
ObType::Dataclass => {
if unlikely!(self.recursion == RECURSION_LIMIT) {
err!(RECURSION_LIMIT_REACHED)
}
let dict = ffi!(PyObject_GetAttr(self.ptr, DICT_STR));
......@@ -363,7 +312,7 @@
ObType::Dataclass => {
if unlikely!(self.recursion == RECURSION_LIMIT) {
err!(RECURSION_LIMIT_REACHED)
}
let dict = ffi!(PyObject_GetAttr(self.ptr, DICT_STR));
if !dict.is_null() {
if likely!(!dict.is_null()) {
ffi!(Py_DECREF(dict));
......@@ -369,14 +318,3 @@
ffi!(Py_DECREF(dict));
let len = unsafe { PyDict_GET_SIZE(dict) as usize };
if unlikely!(len == 0) {
return serializer.serialize_map(Some(0)).unwrap().end();
}
let mut map = serializer.serialize_map(None).unwrap();
let mut pos = 0isize;
let mut str_size: pyo3::ffi::Py_ssize_t = 0;
let mut key: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
let mut value: *mut pyo3::ffi::PyObject = std::ptr::null_mut();
for _ in 0..=len - 1 {
unsafe {
pyo3::ffi::_PyDict_Next(
DataclassFastSerializer::new(
dict,
......@@ -382,26 +320,3 @@
dict,
&mut pos,
&mut key,
&mut value,
std::ptr::null_mut(),
)
};
if unlikely!(ob_type!(key) != STR_TYPE) {
err!(KEY_MUST_BE_STR)
}
{
let data = read_utf8_from_str(key, &mut str_size);
if unlikely!(data.is_null()) {
err!(INVALID_STR)
}
let key_as_str = str_from_slice!(data, str_size);
if unlikely!(key_as_str.as_bytes()[0] == b'_') {
continue;
}
map.serialize_key(key_as_str).unwrap();
}
map.serialize_value(&SerializePyObject::new(
value,
self.opts,
self.default_calls,
......@@ -406,4 +321,4 @@
self.opts,
self.default_calls,
self.recursion + 1,
self.recursion,
self.default,
......@@ -409,6 +324,5 @@
self.default,
))?;
}
map.end()
)
.serialize(serializer)
} else {
unsafe { pyo3::ffi::PyErr_Clear() };
......@@ -413,6 +327,6 @@
} else {
unsafe { pyo3::ffi::PyErr_Clear() };
DataclassSerializer::new(
DataclassFallbackSerializer::new(
self.ptr,
self.opts,
self.default_calls,
......@@ -425,7 +339,7 @@
ObType::Enum => {
let value = ffi!(PyObject_GetAttr(self.ptr, VALUE_STR));
ffi!(Py_DECREF(value));
SerializePyObject::new(
PyObjectSerializer::new(
value,
self.opts,
self.default_calls,
......
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
use crate::opt::*;
use crate::serialize::encode::*;
use serde::ser::{Serialize, SerializeSeq, Serializer};
use std::ptr::NonNull;
pub struct ListSerializer {
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
len: usize,
}
impl ListSerializer {
pub fn new(
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
len: usize,
) -> Self {
ListSerializer {
ptr: ptr,
opts: opts,
default_calls: default_calls,
recursion: recursion,
default: default,
len: len,
}
}
}
impl<'p> Serialize for ListSerializer {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut type_ptr = std::ptr::null_mut();
let mut ob_type = ObType::Str;
let mut seq = serializer.serialize_seq(None).unwrap();
for i in 0..=self.len - 1 {
let elem = unsafe {
*(*(self.ptr as *mut pyo3::ffi::PyListObject))
.ob_item
.offset(i as isize)
};
if ob_type!(elem) != type_ptr {
type_ptr = ob_type!(elem);
ob_type = pyobject_to_obtype(elem, self.opts);
}
seq.serialize_element(&PyObjectSerializer::with_obtype(
elem,
ob_type,
self.opts,
self.default_calls,
self.recursion + 1,
self.default,
))?;
}
seq.end()
}
}
......@@ -5,4 +5,5 @@
mod default;
mod dict;
mod encode;
mod list;
mod numpy;
......@@ -8,4 +9,5 @@
mod numpy;
mod str;
mod tuple;
mod uuid;
mod writer;
......
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
use crate::exc::*;
use serde::ser::{Serialize, Serializer};
#[repr(transparent)]
pub struct StrSubclassSerializer {
ptr: *mut pyo3::ffi::PyObject,
}
impl StrSubclassSerializer {
pub fn new(ptr: *mut pyo3::ffi::PyObject) -> Self {
StrSubclassSerializer { ptr: ptr }
}
}
impl<'p> Serialize for StrSubclassSerializer {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut str_size: pyo3::ffi::Py_ssize_t = 0;
let uni = ffi!(PyUnicode_AsUTF8AndSize(self.ptr, &mut str_size)) as *const u8;
if unlikely!(uni.is_null()) {
err!(INVALID_STR)
}
serializer.serialize_str(str_from_slice!(uni, str_size))
}
}
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
use crate::opt::*;
use crate::serialize::encode::*;
use serde::ser::{Serialize, SerializeSeq, Serializer};
use std::ptr::NonNull;
......@@ -3,8 +7,10 @@
use std::ptr::NonNull;
pub struct PyTupleIterator {
list: *mut pyo3::ffi::PyObject,
len: isize,
idx: isize,
pub struct TupleSerializer {
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
}
......@@ -9,12 +15,20 @@
}
impl PyTupleIterator {
pub fn new(list: *mut pyo3::ffi::PyObject) -> Self {
PyTupleIterator {
list: list,
len: ffi!(PyTuple_GET_SIZE(list)),
idx: 0,
impl TupleSerializer {
pub fn new(
ptr: *mut pyo3::ffi::PyObject,
opts: Opt,
default_calls: u8,
recursion: u8,
default: Option<NonNull<pyo3::ffi::PyObject>>,
) -> Self {
TupleSerializer {
ptr: ptr,
opts: opts,
default_calls: default_calls,
recursion: recursion,
default: default,
}
}
}
......@@ -17,17 +31,24 @@
}
}
}
impl Iterator for PyTupleIterator {
type Item = NonNull<pyo3::ffi::PyObject>;
#[inline]
fn next(&mut self) -> Option<NonNull<pyo3::ffi::PyObject>> {
if self.len == self.idx {
None
} else {
let item = nonnull!(ffi!(PyTuple_GET_ITEM(self.list, self.idx as isize)));
self.idx += 1;
Some(item)
impl<'p> Serialize for TupleSerializer {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(None).unwrap();
for i in 0..=ffi!(PyTuple_GET_SIZE(self.ptr)) - 1 {
let elem = nonnull!(ffi!(PyTuple_GET_ITEM(self.ptr, i as isize)));
seq.serialize_element(&PyObjectSerializer::new(
elem.as_ptr(),
self.opts,
self.default_calls,
self.recursion + 1,
self.default,
))?
}
seq.end()
}
}
......@@ -32,3 +53,2 @@
}
}
}
......@@ -51,6 +51,7 @@
}
}
impl<'p> Serialize for UUID {
#[inline(never)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
......
......@@ -109,7 +109,6 @@
}
}
#[inline]
pub fn read_utf8_from_str(op: *mut PyObject, str_size: &mut Py_ssize_t) -> *const u8 {
unsafe {
if (*op.cast::<PyASCIIObject>()).state & STATE_COMPACT_ASCII == STATE_COMPACT_ASCII {
......
......@@ -42,12 +42,6 @@
};
}
macro_rules! str_to_pyobject {
($obj:expr) => {
crate::unicode::unicode_from_str($obj)
};
}
macro_rules! ffi {
($fn:ident()) => {
unsafe { pyo3::ffi::$fn() }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment