memgraph/include/communication/bolt/v1/transport/chunked_decoder.hpp

71 lines
1.5 KiB
C++
Raw Normal View History

2016-08-02 05:14:09 +08:00
#pragma once
#include <cassert>
2016-08-02 05:14:09 +08:00
#include <cstring>
#include <functional>
#include "logging/default.hpp"
2016-08-02 05:14:09 +08:00
#include "utils/exceptions/basic_exception.hpp"
#include "utils/likely.hpp"
#include "utils/types/byte.hpp"
2016-08-02 05:14:09 +08:00
namespace bolt
{
template <class Stream>
class ChunkedDecoder
{
public:
class DecoderError : public BasicException
{
public:
using BasicException::BasicException;
};
ChunkedDecoder(Stream& stream) : stream(stream) {}
/* Decode chunked data
*
* Chunk format looks like:
*
* |Header| Data ||Header| Data || ... || End |
* | 2B | size bytes || 2B | size bytes || ... ||00 00|
*/
bool decode(const byte *&chunk, size_t n)
2016-08-02 05:14:09 +08:00
{
while (n > 0)
2016-08-02 05:14:09 +08:00
{
// get size from first two bytes in the chunk
auto size = get_size(chunk);
if (UNLIKELY(size + 2 > n))
2016-08-02 05:14:09 +08:00
throw DecoderError("Chunk size larger than available data.");
// advance chunk to pass those two bytes
chunk += 2;
n -= 2;
// if chunk size is 0, we're done!
if (size == 0) return true;
2016-08-02 05:14:09 +08:00
stream.get().write(chunk, size);
chunk += size;
n -= size;
}
return false;
}
bool operator()(const byte *&chunk, size_t n) { return decode(chunk, n); }
2016-08-02 05:14:09 +08:00
private:
std::reference_wrapper<Stream> stream;
size_t get_size(const byte *chunk)
2016-08-02 05:14:09 +08:00
{
return size_t(chunk[0]) << 8 | chunk[1];
}
};
}