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

78 lines
1.5 KiB
C++
Raw Normal View History

2016-08-02 05:14:09 +08:00
#pragma once
#include <cstring>
#include <functional>
#include <cassert>
#include "utils/exceptions/basic_exception.hpp"
#include "utils/likely.hpp"
#include "logging/default.hpp"
namespace bolt
{
template <class Stream>
class ChunkedDecoder
{
public:
class DecoderError : public BasicException
{
public:
using BasicException::BasicException;
};
using byte = unsigned char;
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)
{
while(n > 0)
{
// get size from first two bytes in the chunk
auto size = get_size(chunk);
if(UNLIKELY(size + 2 > n))
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;
stream.get().write(chunk, size);
chunk += size;
n -= size;
}
return false;
}
bool operator()(const byte*& chunk, size_t n)
{
return decode(chunk, n);
}
private:
std::reference_wrapper<Stream> stream;
size_t get_size(const byte* chunk)
{
return size_t(chunk[0]) << 8 | chunk[1];
}
};
}