|
32 | 32 | #ifndef PYBIND11_ABSEIL_ABSL_CASTERS_H_
|
33 | 33 | #define PYBIND11_ABSEIL_ABSL_CASTERS_H_
|
34 | 34 |
|
| 35 | +#include <Python.h> |
35 | 36 | #include <pybind11/cast.h>
|
36 | 37 | #include <pybind11/pybind11.h>
|
37 | 38 | #include <pybind11/stl.h>
|
|
43 | 44 | #include <complex>
|
44 | 45 | #include <cstdint>
|
45 | 46 | #include <cstring>
|
| 47 | +#include <optional> |
46 | 48 | #include <tuple>
|
47 | 49 | #include <type_traits>
|
| 50 | +#include <utility> |
48 | 51 | #include <vector>
|
49 | 52 |
|
50 | 53 | #include "absl/cleanup/cleanup.h"
|
@@ -618,10 +621,39 @@ struct type_caster<absl::Cord> {
|
618 | 621 |
|
619 | 622 | // Conversion part 1 (Python->C++)
|
620 | 623 | bool load(handle src, bool convert) {
|
| 624 | + // If the source is a bytes/string object, we can avoid a copy by using |
| 625 | + // absl::MakeCordFromExternal. |
| 626 | + std::optional<absl::string_view> view; |
| 627 | + if (PyUnicode_Check(src.ptr())) { |
| 628 | + Py_ssize_t size = 0; |
| 629 | + const char* data = PyUnicode_AsUTF8AndSize(src.ptr(), &size); |
| 630 | + if (data) { |
| 631 | + view = absl::string_view(data, size); |
| 632 | + } else { |
| 633 | + PyErr_Clear(); |
| 634 | + } |
| 635 | + } else if (PyBytes_Check(src.ptr())) { |
| 636 | + view = absl::string_view(PyBytes_AS_STRING(src.ptr()), |
| 637 | + PyBytes_GET_SIZE(src.ptr())); |
| 638 | + } |
| 639 | + if (view.has_value()) { |
| 640 | + if (!view->empty()) { |
| 641 | + // Bypass StringViewCaster life support as absl::Cord may outlive the |
| 642 | + // handle. |
| 643 | + src.inc_ref(); |
| 644 | + value = absl::MakeCordFromExternal(*view, [src] { |
| 645 | + PyGILState_STATE gstate = PyGILState_Ensure(); |
| 646 | + src.dec_ref(); |
| 647 | + PyGILState_Release(gstate); |
| 648 | + }); |
| 649 | + } else { |
| 650 | + value.Clear(); |
| 651 | + } |
| 652 | + return true; |
| 653 | + } |
621 | 654 | auto caster = StringViewCaster();
|
622 | 655 | if (caster.load(src, convert)) {
|
623 |
| - absl::string_view view = cast_op<absl::string_view>(std::move(caster)); |
624 |
| - value = view; |
| 656 | + value = absl::Cord(cast_op<absl::string_view>(std::move(caster))); |
625 | 657 | return true;
|
626 | 658 | }
|
627 | 659 | return false;
|
|
0 commit comments