Skip to content

Instantly share code, notes, and snippets.

@mavam
Created March 22, 2017 20:57
Show Gist options
  • Save mavam/6aae479c66d0e93666c315e26935a7df to your computer and use it in GitHub Desktop.
Save mavam/6aae479c66d0e93666c315e26935a7df to your computer and use it in GitHub Desktop.
A function that takes a discriminated union and writes it into a flatbuffers builder.
flexbuffers::Builder& build(flexBuffers::Builder& builder, const data& x) {
struct converter {
converter(flatbuffers::FlatBufferBuilder& builder) : builder_{builder} {
}
using result_type = flatbuffers::Offset<detail::Data>;
result_type operator()(none) {
detail::DataBuilder db{builder_};
return db.Finish();
}
result_type operator()(boolean x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::BooleanType);
db.add_integer(x ? 1 : 0);
return db.Finish();
}
result_type operator()(integer x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::IntegerType);
db.add_integer(x);
return db.Finish();
}
result_type operator()(count x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::CountType);
db.add_count(x);
return db.Finish();
}
result_type operator()(real x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::RealType);
db.add_real(x);
return db.Finish();
}
result_type operator()(timestamp x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::TimestampType);
db.add_integer(x.time_since_epoch().count());
return db.Finish();
}
result_type operator()(timespan x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::TimespanType);
db.add_integer(x.count());
return db.Finish();
}
result_type operator()(const enumeration& x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::EnumerationType);
db.add_integer(x);
return db.Finish();
}
result_type operator()(const std::string& x) {
auto ptr = reinterpret_cast<const uint8_t*>(x.data());
auto bytes = builder_.CreateVector<uint8_t>(ptr, x.size());
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::StringType);
db.add_bytes(bytes);
return db.Finish();
}
result_type operator()(const pattern& x) {
auto ptr = reinterpret_cast<const uint8_t*>(x.string().data());
auto bytes = builder_.CreateVector<uint8_t>(ptr, x.string().size());
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::PatternType);
db.add_bytes(bytes);
return db.Finish();
}
result_type operator()(const address& x) {
if (x.is_v4()) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::AddressType);
db.add_count(*reinterpret_cast<const count*>(x.data().data() + 12));
return db.Finish();
} else {
auto bytes = builder_.CreateVector<uint8_t>(x.data().data(), 16);
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::AddressType);
db.add_bytes(bytes);
return db.Finish();
}
}
result_type operator()(const subnet& x) {
if (x.network().is_v4()) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::AddressType);
auto ptr = x.network().data().data() + 12;
db.add_count(*reinterpret_cast<const count*>(ptr));
db.add_integer(static_cast<integer>(x.length()));
return db.Finish();
} else {
auto ptr = x.network().data().data();
auto bytes = builder_.CreateVector<uint8_t>(ptr, 16);
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::AddressType);
db.add_bytes(bytes);
db.add_integer(static_cast<integer>(x.length()));
return db.Finish();
}
}
result_type operator()(const port& x) {
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::PortType);
db.add_integer(static_cast<integer>(x.type()));
db.add_count(static_cast<count>(x.number()));
return db.Finish();
}
result_type operator()(const vector& xs) {
std::vector<flatbuffers::Offset<detail::Data>> offsets;
offsets.reserve(xs.size());
std::transform(xs.begin(), xs.end(), std::back_inserter(offsets),
[&](auto& x) { return visit(*this, x); });
auto v = builder_.CreateVector(offsets);
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::VectorType);
db.add_vector(v);
return db.Finish();
}
result_type operator()(const set& xs) {
std::vector<flatbuffers::Offset<detail::Data>> offsets;
offsets.reserve(xs.size());
std::transform(xs.begin(), xs.end(), std::back_inserter(offsets),
[&](auto& x) { return visit(*this, x); });
auto v = builder_.CreateVector(offsets);
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::SetType);
db.add_vector(v);
return db.Finish();
}
result_type operator()(const table& xs) {
std::vector<flatbuffers::Offset<detail::Data>> offsets;
offsets.reserve(xs.size() * 2);
for (auto& x : xs) {
offsets.push_back(visit(*this, x.first));
offsets.push_back(visit(*this, x.second));
};
auto v = builder_.CreateVector(offsets);
detail::DataBuilder db{builder_};
db.add_which(detail::DataType::MapType);
db.add_vector(v);
return db.Finish();
}
flatbuffers::FlatBufferBuilder& builder_;
};
return visit(converter{builder}, x);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment