#include <cinttypes>
#include <string>

class BufferedReader {
 private:
  PackageStream *stream;
  char *package;
  int package_left;
 public:
  explicit BufferedReader(PackageStream *stream) {
    this->stream = stream;
    package = (char *) calloc(stream->PackageLen(), sizeof(char));
    package_left = stream->ReadPackage(package);
  }
  int32_t Read(char *output_buffer, int32_t buffer_len) {
    int32_t read_bytes = 0;
    while (package_left <= buffer_len - read_bytes) {
      memcpy(output_buffer + read_bytes, package, package_left);
      read_bytes += package_left;
      package_left = stream->ReadPackage(package);
      if (package_left == 0) {
        break;
      }
    }
    if (package_left > 0) {
      if (package_left >= buffer_len - read_bytes) {
        memcpy(output_buffer + read_bytes, package,
               buffer_len - read_bytes);
        memmove(package + buffer_len - read_bytes,
                package,
                package_left - buffer_len + read_bytes);
        package_left -= buffer_len - read_bytes;
      }
    }
    return read_bytes;
  }
};