Skip to content

Commit 09cc01c

Browse files
charlesbeattiecopybara-github
authored andcommitted
Support using handle for absl::Cord saving a memcpy.
PiperOrigin-RevId: 730847922
1 parent b122679 commit 09cc01c

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

pybind11_abseil/absl_casters.h

+33-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#ifndef PYBIND11_ABSEIL_ABSL_CASTERS_H_
3333
#define PYBIND11_ABSEIL_ABSL_CASTERS_H_
3434

35+
#include <Python.h>
3536
#include <pybind11/cast.h>
3637
#include <pybind11/pybind11.h>
3738
#include <pybind11/stl.h>
@@ -45,6 +46,7 @@
4546
#include <cstring>
4647
#include <tuple>
4748
#include <type_traits>
49+
#include <utility>
4850
#include <vector>
4951

5052
#include "absl/cleanup/cleanup.h"
@@ -618,10 +620,39 @@ struct type_caster<absl::Cord> {
618620

619621
// Conversion part 1 (Python->C++)
620622
bool load(handle src, bool convert) {
623+
// If the source is a bytes/string object, we can avoid a copy by using
624+
// absl::MakeCordFromExternal.
625+
absl::optional<absl::string_view> view;
626+
if (PyUnicode_Check(src.ptr())) {
627+
Py_ssize_t size = 0;
628+
const char* data = PyUnicode_AsUTF8AndSize(src.ptr(), &size);
629+
if (data) {
630+
view = absl::string_view(data, size);
631+
} else {
632+
PyErr_Clear();
633+
}
634+
} else if (PyBytes_Check(src.ptr())) {
635+
view = absl::string_view(PyBytes_AS_STRING(src.ptr()),
636+
PyBytes_GET_SIZE(src.ptr()));
637+
}
638+
if (view.has_value()) {
639+
if (!view->empty()) {
640+
// Bypass StringViewCaster life support as absl::Cord may outlive the
641+
// handle.
642+
src.inc_ref();
643+
value = absl::MakeCordFromExternal(*view, [src] {
644+
PyGILState_STATE gstate = PyGILState_Ensure();
645+
src.dec_ref();
646+
PyGILState_Release(gstate);
647+
});
648+
} else {
649+
value.Clear();
650+
}
651+
return true;
652+
}
621653
auto caster = StringViewCaster();
622654
if (caster.load(src, convert)) {
623-
absl::string_view view = cast_op<absl::string_view>(std::move(caster));
624-
value = view;
655+
value = absl::Cord(cast_op<absl::string_view>(std::move(caster)));
625656
return true;
626657
}
627658
return false;

0 commit comments

Comments
 (0)