Last active
March 22, 2017 20:55
-
-
Save mavam/e762acbea8ef5d9166dc6aaddd4503e8 to your computer and use it in GitHub Desktop.
FlexBuffer serializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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