blob: 3a5bb74965ab9ea64ca636a193511cdcc7770667 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include <sstream>
#ifndef _PY_SERDE_HPP_
#define _PY_SERDE_HPP_
namespace py = pybind11;
namespace datasketches {
/**
* @brief The py_object_serde is an abstract class that implements the
* datasketches serde interface, and is used to allow custom Python
* serialization of items wrapped as generic py::object types. The actual
* Python implementation classes must extend the PyObjectSerDe class.
*/
struct py_object_serde {
/**
* @brief Get the serialized size of an object, in bytes
*
* @param item A provided item
* @return int64_t The serialized size of the item, in bytes
*/
virtual int64_t get_size(const py::object& item) const = 0;
/**
* @brief Serializes an item to a bytes object
*
* @param item A provided item
* @return The serialized image of the item as a Python bytes object
*/
virtual py::bytes to_bytes(const py::object& item) const = 0;
/**
* @brief Constructs an object from a serialized image, reading the
* incoming buffer starting at the specified offset.
*
* @param bytes A buffer containing items from a serialized sketch
* @param offset The starting offset into the bytes buffer
* @return A Python tuple of the reconstructed item and the total number of bytes read
*/
virtual py::tuple from_bytes(py::bytes& bytes, size_t offset) const = 0;
virtual ~py_object_serde() = default;
// these methods are required by the serde interface; see common/include/serde.hpp for
// default implementations for C++ std::string and numeric types.
size_t size_of_item(const py::object& item) const;
size_t serialize(void* ptr, size_t capacity, const py::object* items, unsigned num) const;
size_t deserialize(const void* ptr, size_t capacity, py::object* items, unsigned num) const;
};
/**
* @brief The PyObjectSerDe class provides a concrete base class
* that pybind11 uses as a "trampoline" to pass calls through to
* the abstract py_object_serde class. Custom Python serde implementations
* must extend this class.
*/
struct PyObjectSerDe : public py_object_serde {
using py_object_serde::py_object_serde;
// trampoline definitions -- need one for each virtual function
int64_t get_size(const py::object& item) const override {
PYBIND11_OVERRIDE_PURE(
int64_t, // Return type
py_object_serde, // Parent class
get_size, // Name of function in C++ (must match Python name)
item // Argument(s)
);
}
py::bytes to_bytes(const py::object& item) const override {
PYBIND11_OVERRIDE_PURE(
py::bytes, // Return type
py_object_serde, // Parent class
to_bytes, // Name of function in C++ (must match Python name)
item // Argument(s)
);
}
py::tuple from_bytes(py::bytes& bytes, size_t offset) const override {
PYBIND11_OVERRIDE_PURE(
py::tuple, // Return type
py_object_serde, // Parent class
from_bytes, // Name of function in C++ (must match Python name)
bytes, offset // Argument(s)
);
}
};
}
#endif // _PY_SERDE_HPP_