#pragma once

#include <iostream>
#include <utility>
#include <algorithm>

class PackageStream {
public:
    PackageStream(std::string source, int32_t package_len) :
                    source(std::move(source)), package_len(package_len) {
    }

    int32_t PackageLen() const {
        return this->package_len;
    }
    int32_t ReadPackage(char* output_package) {
        memcpy(output_package, this->source.c_str(), this->PackageLen());
        int32_t real_size = min(static_cast<int>(this->source.size()),
                                this->PackageLen());
        this->source.erase(this->source.begin(),
                           this->source.begin() + real_size);
        return real_size;
    }

    int32_t package_len;
private:
    std::string source;
};

class BufferedReader {
 public:
    explicit BufferedReader(PackageStream* stream) : stream(stream) {
    }
    int32_t Read(char* output_buffer, int32_t buffer_len) {
        int32_t tmp = this->stream->PackageLen();
        this->stream->package_len = buffer_len;
        return this->stream->ReadPackage(output_buffer);
    }

 private:
    PackageStream* stream;
};