serializer.rs

Overview

[serializer.rs](/projects/287/67745) is a core serialization module designed to convert Python objects (represented as raw pointers to `pyo3_ffi::PyObject`) into a serializable Rust data structure using the `serde` framework. It provides a unified interface to serialize various Python object types—including primitives, collections, datetime objects, enums, numpy arrays, and dataclasses—into a format that can be written out (for example, JSON or other serde-supported formats).

At its heart, the file defines the `PyObjectSerializer` struct which implements `serde::Serialize`. It dynamically dispatches serialization logic based on the runtime Python object type, leveraging specialized serializers per type. The main entry point function is `serialize()`, which wraps this process and handles output buffering and formatting options such as pretty printing and newline appending.

This file acts as the bridge between raw Python FFI objects and Rust’s strongly typed serialization ecosystem, enabling seamless conversion of Python data structures for consumption or storage in Rust applications.


Detailed Documentation

Function: serialize

pub(crate) fn serialize(
    ptr: *mut pyo3_ffi::PyObject,
    default: Option<NonNull<pyo3_ffi::PyObject>>,
    opts: Opt,
) -> Result<NonNull<pyo3_ffi::PyObject>, String>

Purpose

Converts a raw Python object pointer into a serialized byte buffer and returns it as a new Python byte object. Handles serialization options like pretty printing and newline appending.

Parameters

Returns

Behavior

Usage Example

let py_obj_ptr: *mut pyo3_ffi::PyObject = ...; // obtained from Python FFI
let options = Opt::default();
match serialize(py_obj_ptr, None, options) {
    Ok(bytes_ptr) => {
        // Use serialized bytes, e.g., return to Python or write to file
    }
    Err(err) => {
        eprintln!("Serialization failed: {}", err);
    }
}

Struct: PyObjectSerializer

pub(crate) struct PyObjectSerializer {
    pub ptr: *mut pyo3_ffi::PyObject,
    pub state: SerializerState,
    pub default: Option<NonNull<pyo3_ffi::PyObject>>,
}

Purpose

Wraps a raw Python object pointer with serialization context and implements `serde::Serialize`. It serves as the polymorphic serializer that delegates to the appropriate per-type serializer based on the Python object's runtime type.

Fields

Methods

new
pub fn new(
    ptr: *mut pyo3_ffi::PyObject,
    state: SerializerState,
    default: Option<NonNull<pyo3_ffi::PyObject>>,
) -> Self

Constructs a new `PyObjectSerializer` instance.

**Parameters:**

**Returns:**

**Example:**

let serializer = PyObjectSerializer::new(py_obj_ptr, state, None);

Trait Implementation: Serialize for PyObjectSerializer

This implementation is the core dispatcher that selects the correct serializer based on the Python object's type.

Method: serialize

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,

**Algorithmic Detail:**

**Example usage:**

When a `PyObjectSerializer` instance is serialized through serde, the correct underlying serializer is invoked automatically:

let serializer = PyObjectSerializer::new(ptr, state, default);
serde_json::to_string(&serializer)?;

Important Implementation Details


Interaction with Other Modules

This file acts as the orchestrator, tying together type detection, per-type serializers, and output buffering.


Visual Diagram

classDiagram
    class PyObjectSerializer {
        +ptr: *mut PyObject
        +state: SerializerState
        +default: Option<NonNull<PyObject>>
        +new(ptr, state, default) PyObjectSerializer
        +serialize<S: Serializer>(serializer: S) -> Result<S::Ok, S::Error>
    }

    PyObjectSerializer ..> SerializerState : contains
    PyObjectSerializer ..> pyo3_ffi::PyObject : contains pointer
    PyObjectSerializer ..|> serde::Serialize

    PyObjectSerializer "1" --> "1" StrSerializer : when ObType::Str
    PyObjectSerializer "1" --> "1" StrSubclassSerializer : when ObType::StrSubclass
    PyObjectSerializer "1" --> "1" IntSerializer : when ObType::Int
    PyObjectSerializer "1" --> "1" NoneSerializer : when ObType::None
    PyObjectSerializer "1" --> "1" FloatSerializer : when ObType::Float
    PyObjectSerializer "1" --> "1" BoolSerializer : when ObType::Bool
    PyObjectSerializer "1" --> "1" DateTime : when ObType::Datetime
    PyObjectSerializer "1" --> "1" Date : when ObType::Date
    PyObjectSerializer "1" --> "1" Time : when ObType::Time
    PyObjectSerializer "1" --> "1" UUID : when ObType::Uuid
    PyObjectSerializer "1" --> "1" DictGenericSerializer : when ObType::Dict
    PyObjectSerializer "1" --> "1" ListTupleSerializer : when ObType::List or ObType::Tuple (if not empty)
    PyObjectSerializer "1" --> "1" ZeroListSerializer : when ObType::List or ObType::Tuple (empty)
    PyObjectSerializer "1" --> "1" DataclassGenericSerializer : when ObType::Dataclass
    PyObjectSerializer "1" --> "1" EnumSerializer : when ObType::Enum
    PyObjectSerializer "1" --> "1" NumpySerializer : when ObType::NumpyArray
    PyObjectSerializer "1" --> "1" NumpyScalar : when ObType::NumpyScalar
    PyObjectSerializer "1" --> "1" FragmentSerializer : when ObType::Fragment
    PyObjectSerializer "1" --> "1" DefaultSerializer : when ObType::Unknown

Summary

The [serializer.rs](/projects/287/67745) file provides a critical serialization layer turning raw Python objects into serialized Rust representations using serde. It detects Python types dynamically and delegates to specialized serializers, supporting a broad range of Python data types. The main `serialize()` function exposes this functionality in a flexible way with options for pretty output and fallback handlers.

This module integrates deeply with other serialization components to form a robust, extensible serialization pipeline bridging Python FFI and Rust’s serde ecosystem.