in python/src/PythonInputStream.h [74:151]
long long read(char *buffer, long long bytesToRead) {
nb::gil_scoped_acquire acquire;
if (buffer == nullptr) {
throw nb::buffer_error(
"C++ code attempted to read from a Python file-like object into a "
"null destination buffer.");
}
if (bytesToRead < 0) {
throw nb::buffer_error("C++ code attempted to read a negative number "
"of bytes from a Python file-like object.");
}
long long bytesRead = 0;
if (peekValue.size()) {
long long bytesToCopy =
std::min(bytesToRead, (long long)peekValue.size());
std::memcpy(buffer, peekValue.data(), bytesToCopy);
for (int i = 0; i < bytesToCopy; i++)
peekValue.erase(peekValue.begin());
bytesRead += bytesToCopy;
buffer += bytesToCopy;
}
while (bytesRead < bytesToRead) {
auto readResult = fileLike.attr("read")(
std::min(MAX_BUFFER_SIZE, bytesToRead - bytesRead));
if (!nb::isinstance<nb::bytes>(readResult)) {
std::string message =
"Python file-like object was expected to return "
"bytes from its read(...) method, but "
"returned " +
nb::cast<std::string>(
nb::str(nb::handle(readResult.type().attr("__name__")))) +
".";
if (nb::hasattr(fileLike, "mode") &&
nb::cast<std::string>(nb::str(nb::handle(fileLike.attr("mode")))) ==
"r") {
message += " (Try opening the stream in \"rb\" mode instead of "
"\"r\" mode if possible.)";
}
throw nb::type_error(message.c_str());
return 0;
}
nb::bytes bytesObject = nb::cast<nb::bytes>(readResult);
const char *pythonBuffer = bytesObject.c_str();
nb::ssize_t pythonLength = bytesObject.size();
if (!buffer && pythonLength > 0) {
throw nb::buffer_error("Internal error: bytes pointer is null, but a "
"non-zero number of bytes were returned!");
}
if (bytesRead + pythonLength > bytesToRead) {
throw nb::buffer_error(
("Python returned " + std::to_string(pythonLength) +
" bytes, but only " + std::to_string(bytesToRead - bytesRead) +
" bytes were requested.")
.c_str());
}
if (buffer && pythonLength > 0) {
std::memcpy(buffer, pythonBuffer, pythonLength);
bytesRead += pythonLength;
buffer += pythonLength;
} else {
break;
}
}
lastReadWasSmallerThanExpected = bytesToRead > bytesRead;
return bytesRead;
}