Skip to content

Instantly share code, notes, and snippets.

@mavam
Last active March 22, 2017 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mavam/e762acbea8ef5d9166dc6aaddd4503e8 to your computer and use it in GitHub Desktop.
Save mavam/e762acbea8ef5d9166dc6aaddd4503e8 to your computer and use it in GitHub Desktop.
FlexBuffer serializer
#ifndef VAST_FLEXBUFFER_PACKER_HPP
#define VAST_FLEXBUFFER_PACKER_HPP
#include <caf/deserializer.hpp>
#include <caf/serializer.hpp>
#include <flatbuffers/flexbuffers.h>
#include "vast/chunk.hpp"
namespace vast {
namespace detail {
/// A packer that serializes into a FlexBuffer.
class flexbuffer_serializer : public caf::serializer {
public:
/// Constructs a FlexBuffer packer.
/// @param xs The arguments forwarded to `flexbuffers::Builder`.
template <class... Ts>
explicit flexbuffer_serializer(Ts&&... xs)
: builder_{std::make_shared<flexbuffers::Builder>(
std::forward<Ts>(xs)...)} {
}
// -- serializer API --------------------------------------------------------
error begin_object(uint16_t&, std::string&) override {
return nil;
}
error end_object() override {
return nil;
}
error begin_sequence(size_t&) override {
sequences_.push_back(builder_->StartVector());
return nil;
}
error end_sequence() override {
builder_->EndVector(sequences_.back(), false, false);
sequences_.pop_back();
return nil;
}
error apply_builtin(builtin type, void* x) override {
switch (type) {
case i8_v:
builder_->Int(*reinterpret_cast<int8_t*>(x));
break;
case i16_v:
builder_->Int(*reinterpret_cast<int16_t*>(x));
break;
case i32_v:
builder_->Int(*reinterpret_cast<int32_t*>(x));
break;
case i64_v:
builder_->Int(*reinterpret_cast<int64_t*>(x));
break;
case u8_v:
builder_->UInt(*reinterpret_cast<uint8_t*>(x));
break;
case u16_v:
builder_->UInt(*reinterpret_cast<uint16_t*>(x));
break;
case u32_v:
builder_->UInt(*reinterpret_cast<uint32_t*>(x));
break;
case u64_v:
builder_->UInt(*reinterpret_cast<uint64_t*>(x));
break;
case float_v:
builder_->Int(caf::detail::pack754(*reinterpret_cast<float*>(x)));
break;
case double_v:
builder_->Int(caf::detail::pack754(*reinterpret_cast<double*>(x)));
break;
case ldouble_v: {
// the IEEE-754 conversion does not work for long double
// => fall back to string serialization (event though it sucks)
std::ostringstream oss;
oss << std::setprecision(std::numeric_limits<long double>::digits)
<< *reinterpret_cast<long double*>(x);
auto tmp = oss.str();
builder_->String(tmp);
break;
}
case string8_v:
builder_->String(*reinterpret_cast<std::string*>(x));
break;
case string16_v: {
auto str = reinterpret_cast<std::u16string*>(x);
auto s = str->size();
return error::eval([&] { return begin_sequence(s); },
[&] { return consume_range_c<uint16_t>(*str); },
[&] { return end_sequence(); });
}
case string32_v: {
auto str = reinterpret_cast<std::u32string*>(x);
auto s = str->size();
return error::eval([&] { return begin_sequence(s); },
[&] { return consume_range_c<uint32_t>(*str); },
[&] { return end_sequence(); });
}
}
return nil;
}
error apply_raw(size_t num_bytes, void* data) override {
builder_->Blob(reinterpret_cast<char*>(data), num_bytes);
return nil;
}
// -- packer API ------------------------------------------------------------
/// Complete incremental packing of items and construct a chunk from the
/// current set of encoded objects.
chunk_ptr finish() {
VAST_ASSERT(sequences_.empty());
builder_->Finish();
auto& buffer = builder_->GetBuffer();
auto data = const_cast<char*>(reinterpret_cast<const char*>(buffer.data()));
auto deleter = [builder=builder_](char*, size_t) mutable {
builder.reset();
};
return make_chunk(buffer.size(), data, deleter);
}
private:
std::vector<size_t> sequences_;
std::shared_ptr<flexbuffers::Builder> builder_;
};
} // namespace detail
} // namespace vast
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment