Skip to content

Commit 75d9ea3

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

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

pybind11_abseil/absl_casters.h

Lines changed: 34 additions & 2 deletions
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>
@@ -43,8 +44,10 @@
4344
#include <complex>
4445
#include <cstdint>
4546
#include <cstring>
47+
#include <optional>
4648
#include <tuple>
4749
#include <type_traits>
50+
#include <utility>
4851
#include <vector>
4952

5053
#include "absl/cleanup/cleanup.h"
@@ -618,10 +621,39 @@ struct type_caster<absl::Cord> {
618621

619622
// Conversion part 1 (Python->C++)
620623
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+
}
621654
auto caster = StringViewCaster();
622655
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)));
625657
return true;
626658
}
627659
return false;

0 commit comments

Comments
 (0)