long long read()

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;
  }