Rename Location to Channel and add extra Flatbuffer helpers
This now follows the convention in the design doc and is more closely
aligned to classic pubsub terminology.
Also add a Flatbuffer<T> base type, along with both an array backed
version. Rename the DetachedBuffer variant.
Change-Id: I257b5dbb5838120c479c4b98139657fc08e73150
diff --git a/aos/BUILD b/aos/BUILD
index 9662ee3..206eefb 100644
--- a/aos/BUILD
+++ b/aos/BUILD
@@ -501,11 +501,16 @@
cc_library(
name = "flatbuffers",
+ srcs = [
+ "flatbuffers.cc",
+ ],
hdrs = [
"flatbuffers.h",
],
+ visibility = ["//visibility:public"],
deps = [
"@com_github_google_flatbuffers//:flatbuffers",
+ "@com_github_google_glog//:glog",
],
)
diff --git a/aos/configuration.cc b/aos/configuration.cc
index a1cc614..56c5b0e 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -20,15 +20,15 @@
namespace aos {
-// Define the compare and equal operators for Location and Application so we can
+// Define the compare and equal operators for Channel and Application so we can
// insert them in the btree below.
//
// These are not in headers because they are only comparing part of the
// flatbuffer, and it seems weird to expose that as *the* compare operator. And
// I can't put them in an anonymous namespace because they wouldn't be found
// that way by the btree.
-bool operator<(const Flatbuffer<Location> &lhs,
- const Flatbuffer<Location> &rhs) {
+bool operator<(const FlatbufferDetachedBuffer<Channel> &lhs,
+ const FlatbufferDetachedBuffer<Channel> &rhs) {
int name_compare = lhs.message().name()->string_view().compare(
rhs.message().name()->string_view());
if (name_compare == 0) {
@@ -41,22 +41,22 @@
}
}
-bool operator==(const Flatbuffer<Location> &lhs,
- const Flatbuffer<Location> &rhs) {
+bool operator==(const FlatbufferDetachedBuffer<Channel> &lhs,
+ const FlatbufferDetachedBuffer<Channel> &rhs) {
return lhs.message().name()->string_view() ==
rhs.message().name()->string_view() &&
lhs.message().type()->string_view() ==
rhs.message().type()->string_view();
}
-bool operator==(const Flatbuffer<Application> &lhs,
- const Flatbuffer<Application> &rhs) {
+bool operator==(const FlatbufferDetachedBuffer<Application> &lhs,
+ const FlatbufferDetachedBuffer<Application> &rhs) {
return lhs.message().name()->string_view() ==
rhs.message().name()->string_view();
}
-bool operator<(const Flatbuffer<Application> &lhs,
- const Flatbuffer<Application> &rhs) {
+bool operator<(const FlatbufferDetachedBuffer<Application> &lhs,
+ const FlatbufferDetachedBuffer<Application> &rhs) {
return lhs.message().name()->string_view() <
rhs.message().name()->string_view();
}
@@ -154,15 +154,15 @@
: filename.substr(0, last_slash_pos + 1);
}
-Flatbuffer<Configuration> ReadConfig(
+FlatbufferDetachedBuffer<Configuration> ReadConfig(
const absl::string_view path, absl::btree_set<std::string> *visited_paths) {
- Flatbuffer<Configuration> config(JsonToFlatbuffer(
+ FlatbufferDetachedBuffer<Configuration> config(JsonToFlatbuffer(
util::ReadFileToStringOrDie(path), ConfigurationTypeTable()));
// Depth first. Take the following example:
//
// config1.json:
// {
- // "locations": [
+ // "channels": [
// {
// "name": "/foo",
// "type": ".aos.bar",
@@ -176,7 +176,7 @@
//
// config2.json:
// {
- // "locations": [
+ // "channels": [
// {
// "name": "/foo",
// "type": ".aos.bar",
@@ -201,8 +201,8 @@
config.mutable_message()->clear_imports();
// Start with an empty configuration to merge into.
- Flatbuffer<Configuration> merged_config =
- Flatbuffer<Configuration>::Empty();
+ FlatbufferDetachedBuffer<Configuration> merged_config =
+ FlatbufferDetachedBuffer<Configuration>::Empty();
const ::std::string folder(ExtractFolder(path));
@@ -225,33 +225,33 @@
}
// Remove duplicate entries, and handle overrides.
-Flatbuffer<Configuration> MergeConfiguration(
+FlatbufferDetachedBuffer<Configuration> MergeConfiguration(
const Flatbuffer<Configuration> &config) {
- // Store all the locations in a sorted set. This lets us track locations we
+ // Store all the channels in a sorted set. This lets us track channels we
// have seen before and merge the updates in.
- absl::btree_set<Flatbuffer<Location>> locations;
+ absl::btree_set<FlatbufferDetachedBuffer<Channel>> channels;
- if (config.message().has_locations()) {
- for (const Location *l : *config.message().locations()) {
+ if (config.message().has_channels()) {
+ for (const Channel *c : *config.message().channels()) {
// Ignore malformed entries.
- if (!l->has_name()) {
+ if (!c->has_name()) {
continue;
}
- if (!l->has_type()) {
+ if (!c->has_type()) {
continue;
}
- // Attempt to insert the location.
- auto result = locations.insert(CopyFlatBuffer(l));
+ // Attempt to insert the channel.
+ auto result = channels.insert(CopyFlatBuffer(c));
if (!result.second) {
// Already there, so merge the new table into the original.
- *result.first = MergeFlatBuffers(*result.first, CopyFlatBuffer(l));
+ *result.first = MergeFlatBuffers(*result.first, CopyFlatBuffer(c));
}
}
}
// Now repeat this for the application list.
- absl::btree_set<Flatbuffer<Application>> applications;
+ absl::btree_set<FlatbufferDetachedBuffer<Application>> applications;
if (config.message().has_applications()) {
for (const Application *a : *config.message().applications()) {
if (!a->has_name()) {
@@ -269,16 +269,16 @@
fbb.ForceDefaults(1);
// Start by building the vectors. They need to come before the final table.
- // Locations
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Location>>>
- locations_offset;
+ // Channels
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Channel>>>
+ channels_offset;
{
- ::std::vector<flatbuffers::Offset<Location>> location_offsets;
- for (const Flatbuffer<Location> &l : locations) {
- location_offsets.emplace_back(
- CopyFlatBuffer<Location>(&l.message(), &fbb));
+ ::std::vector<flatbuffers::Offset<Channel>> channel_offsets;
+ for (const FlatbufferDetachedBuffer<Channel> &c : channels) {
+ channel_offsets.emplace_back(
+ CopyFlatBuffer<Channel>(&c.message(), &fbb));
}
- locations_offset = fbb.CreateVector(location_offsets);
+ channels_offset = fbb.CreateVector(channel_offsets);
}
// Applications
@@ -286,7 +286,7 @@
applications_offset;
{
::std::vector<flatbuffers::Offset<Application>> applications_offsets;
- for (const Flatbuffer<Application> &a : applications) {
+ for (const FlatbufferDetachedBuffer<Application> &a : applications) {
applications_offsets.emplace_back(
CopyFlatBuffer<Application>(&a.message(), &fbb));
}
@@ -308,7 +308,7 @@
// And then build a Configuration with them all.
ConfigurationBuilder configuration_builder(fbb);
- configuration_builder.add_locations(locations_offset);
+ configuration_builder.add_channels(channels_offset);
if (config.message().has_maps()) {
configuration_builder.add_maps(maps_offset);
}
@@ -318,12 +318,12 @@
return fbb.Release();
}
-// Compares (l < p) a location, and a name, type tuple.
-bool CompareLocations(const Location *l,
- ::std::pair<absl::string_view, absl::string_view> p) {
- int name_compare = l->name()->string_view().compare(p.first);
+// Compares (c < p) a channel, and a name, type tuple.
+bool CompareChannels(const Channel *c,
+ ::std::pair<absl::string_view, absl::string_view> p) {
+ int name_compare = c->name()->string_view().compare(p.first);
if (name_compare == 0) {
- return l->type()->string_view() < p.second;
+ return c->type()->string_view() < p.second;
} else if (name_compare < 0) {
return true;
} else {
@@ -331,19 +331,19 @@
}
};
-// Compares for equality (l == p) a location, and a name, type tuple.
-bool EqualsLocations(const Location *l,
+// Compares for equality (c == p) a channel, and a name, type tuple.
+bool EqualsChannels(const Channel *c,
::std::pair<absl::string_view, absl::string_view> p) {
- return l->name()->string_view() == p.first &&
- l->type()->string_view() == p.second;
+ return c->name()->string_view() == p.first &&
+ c->type()->string_view() == p.second;
}
-// Compares (l < p) an application, and a name;
+// Compares (c < p) an application, and a name;
bool CompareApplications(const Application *a, absl::string_view name) {
return a->name()->string_view() < name;
};
-// Compares for equality (l == p) an application, and a name;
+// Compares for equality (c == p) an application, and a name;
bool EqualsApplications(const Application *a, absl::string_view name) {
return a->name()->string_view() == name;
}
@@ -352,7 +352,7 @@
void HandleMaps(const flatbuffers::Vector<flatbuffers::Offset<aos::Map>> *maps,
absl::string_view *name) {
// For the same reason we merge configs in reverse order, we want to process
- // maps in reverse order. That lets the outer config overwrite locations from
+ // maps in reverse order. That lets the outer config overwrite channels from
// the inner configs.
for (auto i = maps->rbegin(); i != maps->rend(); ++i) {
if (i->has_match() && i->match()->has_name() && i->has_rename() &&
@@ -381,26 +381,26 @@
return *once.Get();
}
-Flatbuffer<Configuration> ReadConfig(const absl::string_view path) {
+FlatbufferDetachedBuffer<Configuration> ReadConfig(
+ const absl::string_view path) {
// We only want to read a file once. So track the visited files in a set.
absl::btree_set<std::string> visited_paths;
return MergeConfiguration(ReadConfig(path, &visited_paths));
}
-const Location *GetLocation(const Flatbuffer<Configuration> &config,
- absl::string_view name, absl::string_view type,
- absl::string_view application_name) {
+const Channel *GetChannel(const Configuration *config, absl::string_view name,
+ absl::string_view type,
+ absl::string_view application_name) {
VLOG(1) << "Looking up { \"name\": \"" << name << "\", \"type\": \"" << type
<< "\" }";
// First handle application specific maps. Only do this if we have a matching
// application name, and it has maps.
- if (config.message().has_applications()) {
- auto application_iterator =
- std::lower_bound(config.message().applications()->cbegin(),
- config.message().applications()->cend(),
- application_name, CompareApplications);
- if (application_iterator != config.message().applications()->cend() &&
+ if (config->has_applications()) {
+ auto application_iterator = std::lower_bound(
+ config->applications()->cbegin(), config->applications()->cend(),
+ application_name, CompareApplications);
+ if (application_iterator != config->applications()->cend() &&
EqualsApplications(*application_iterator, application_name)) {
if (application_iterator->has_maps()) {
HandleMaps(application_iterator->maps(), &name);
@@ -409,21 +409,21 @@
}
// Now do global maps.
- if (config.message().has_maps()) {
- HandleMaps(config.message().maps(), &name);
+ if (config->has_maps()) {
+ HandleMaps(config->maps(), &name);
}
- // Then look for the location.
- auto location_iterator =
- std::lower_bound(config.message().locations()->cbegin(),
- config.message().locations()->cend(),
- std::make_pair(name, type), CompareLocations);
+ // Then look for the channel.
+ auto channel_iterator =
+ std::lower_bound(config->channels()->cbegin(),
+ config->channels()->cend(),
+ std::make_pair(name, type), CompareChannels);
// Make sure we actually found it, and it matches.
- if (location_iterator != config.message().locations()->cend() &&
- EqualsLocations(*location_iterator, std::make_pair(name, type))) {
- VLOG(1) << "Found: " << FlatbufferToJson(*location_iterator);
- return *location_iterator;
+ if (channel_iterator != config->channels()->cend() &&
+ EqualsChannels(*channel_iterator, std::make_pair(name, type))) {
+ VLOG(1) << "Found: " << FlatbufferToJson(*channel_iterator);
+ return *channel_iterator;
} else {
VLOG(1) << "No match for { \"name\": \"" << name << "\", \"type\": \""
<< type << "\" }";
diff --git a/aos/configuration.fbs b/aos/configuration.fbs
index bc0f40e..d23c4b9 100644
--- a/aos/configuration.fbs
+++ b/aos/configuration.fbs
@@ -1,26 +1,26 @@
namespace aos;
-// Table representing a location. Locations are where data is published and
+// Table representing a channel. Channels are where data is published and
// subscribed from. The tuple of name, type is the identifying information.
-table Location {
- // Name of the location.
+table Channel {
+ // Name of the channel.
name:string;
// Type name of the flatbuffer.
type:string;
- // Max frequency in messages/sec of the data published on this location.
+ // Max frequency in messages/sec of the data published on this channel.
frequency:int = 100;
// Max size of the data being published. (This will be automatically
// computed in the future.)
max_size:int = 1000;
}
-// Table to support renaming location names.
+// Table to support renaming channel names.
table Map {
- // Location to match with. If the name in here matches, the name is replaced
+ // Channel to match with. If the name in here matches, the name is replaced
// with the name in rename.
- match:Location;
- // The location to merge in.
- rename:Location;
+ match:Channel;
+ // The channel to merge in.
+ rename:Channel;
}
// Application specific information.
@@ -31,9 +31,9 @@
// maps are applied in reverse order, and before the global maps.
// For example
// "maps": [ { "match": { "name": "/foo" }, "rename": { "name": "/bar" } } ]
- // will make it so any locations named "/foo" actually go to "/bar" for just
+ // will make it so any channels named "/foo" actually go to "/bar" for just
// this application. This is super handy for running an application twice
- // publishing to different locations, or for injecting a little application
+ // publishing to different channels, or for injecting a little application
// to modify messages live for testing.
//
// "maps": [
@@ -47,8 +47,8 @@
// Overall configuration datastructure for the pubsub.
table Configuration {
- // List of locations.
- locations:[Location] (id: 0);
+ // List of channels.
+ channels:[Channel] (id: 0);
// List of global maps. These are applied in reverse order.
maps:[Map] (id: 1);
// List of applications.
diff --git a/aos/configuration.h b/aos/configuration.h
index b30a2b3..3cee8e7 100644
--- a/aos/configuration.h
+++ b/aos/configuration.h
@@ -18,16 +18,24 @@
// Reads a json configuration. This includes all imports and merges. Note:
// duplicate imports will result in a CHECK.
-Flatbuffer<Configuration> ReadConfig(const absl::string_view path);
+FlatbufferDetachedBuffer<Configuration> ReadConfig(
+ const absl::string_view path);
-// Returns the resolved location for a name, type, and application name.
+// Returns the resolved location for a name, type, and application name. Returns
+// nullptr if none is found.
//
// If the application name is empty, it is ignored. Maps are processed in
// reverse order, and application specific first.
-const Location *GetLocation(const Flatbuffer<Configuration> &config,
- const absl::string_view name,
- const absl::string_view type,
- const absl::string_view application_name);
+const Channel *GetChannel(const Configuration *config,
+ const absl::string_view name,
+ const absl::string_view type,
+ const absl::string_view application_name);
+inline const Channel *GetChannel(const Flatbuffer<Configuration> &config,
+ const absl::string_view name,
+ const absl::string_view type,
+ const absl::string_view application_name) {
+ return GetChannel(&config.message(), name, type, application_name);
+}
// Returns "our" IP address.
const in_addr &GetOwnIPAddress();
diff --git a/aos/configuration_test.cc b/aos/configuration_test.cc
index 3177265..0f13041 100644
--- a/aos/configuration_test.cc
+++ b/aos/configuration_test.cc
@@ -23,7 +23,8 @@
// Tests that we can read and merge a configuration.
TEST_F(ConfigurationTest, ConfigMerge) {
- Flatbuffer<Configuration> config = ReadConfig("aos/testdata/config1.json");
+ FlatbufferDetachedBuffer<Configuration> config =
+ ReadConfig("aos/testdata/config1.json");
printf("Read: %s\n", FlatbufferToJson(config, true).c_str());
EXPECT_EQ(
@@ -36,7 +37,7 @@
TEST_F(ConfigurationDeathTest, DuplicateFile) {
EXPECT_DEATH(
{
- Flatbuffer<Configuration> config =
+ FlatbufferDetachedBuffer<Configuration> config =
ReadConfig("aos/testdata/config1_bad.json");
},
"aos/testdata/config1_bad.json");
@@ -44,30 +45,31 @@
// Tests that we can lookup a location, complete with maps, from a merged
// config.
-TEST_F(ConfigurationTest, GetLocation) {
- Flatbuffer<Configuration> config = ReadConfig("aos/testdata/config1.json");
+TEST_F(ConfigurationTest, GetChannel) {
+ FlatbufferDetachedBuffer<Configuration> config =
+ ReadConfig("aos/testdata/config1.json");
// Test a basic lookup first.
- EXPECT_EQ(FlatbufferToJson(GetLocation(config, "/foo", ".aos.bar", "app1")),
+ EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/foo", ".aos.bar", "app1")),
kExpectedLocation);
// Test that an invalid name results in nullptr back.
- EXPECT_EQ(GetLocation(config, "/invalid_name", ".aos.bar", "app1"), nullptr);
+ EXPECT_EQ(GetChannel(config, "/invalid_name", ".aos.bar", "app1"), nullptr);
// Tests that a root map/rename works. And that they get processed from the
// bottom up.
EXPECT_EQ(
- FlatbufferToJson(GetLocation(config, "/batman", ".aos.bar", "app1")),
+ FlatbufferToJson(GetChannel(config, "/batman", ".aos.bar", "app1")),
kExpectedLocation);
// And then test that an application specific map/rename works.
- EXPECT_EQ(FlatbufferToJson(GetLocation(config, "/bar", ".aos.bar", "app1")),
+ EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/bar", ".aos.bar", "app1")),
kExpectedLocation);
- EXPECT_EQ(FlatbufferToJson(GetLocation(config, "/baz", ".aos.bar", "app2")),
+ EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/baz", ".aos.bar", "app2")),
kExpectedLocation);
// And then test that an invalid application name gets properly ignored.
- EXPECT_EQ(FlatbufferToJson(GetLocation(config, "/foo", ".aos.bar", "app3")),
+ EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/foo", ".aos.bar", "app3")),
kExpectedLocation);
}
diff --git a/aos/flatbuffer_merge.h b/aos/flatbuffer_merge.h
index 16372ed..afb4f69 100644
--- a/aos/flatbuffer_merge.h
+++ b/aos/flatbuffer_merge.h
@@ -43,15 +43,18 @@
}
template <class T>
-inline aos::Flatbuffer<T> MergeFlatBuffers(const aos::Flatbuffer<T> &fb1,
- const aos::Flatbuffer<T> &fb2) {
- return aos::Flatbuffer<T>(
- MergeFlatBuffers(T::MiniReflectTypeTable(), fb1.data(), fb2.data()));
+inline aos::FlatbufferDetachedBuffer<T> MergeFlatBuffers(
+ const aos::Flatbuffer<T> &fb1, const aos::Flatbuffer<T> &fb2) {
+const uint8_t *data1 = fb1.data();
+const uint8_t *data2 = fb2.data();
+ return aos::FlatbufferDetachedBuffer<T>(
+ MergeFlatBuffers(T::MiniReflectTypeTable(), data1, data2));
}
template <class T>
-inline aos::Flatbuffer<T> MergeFlatBuffers(const T *fb1, const T *fb2) {
- return aos::Flatbuffer<T>(MergeFlatBuffers(
+inline aos::FlatbufferDetachedBuffer<T> MergeFlatBuffers(const T *fb1,
+ const T *fb2) {
+ return aos::FlatbufferDetachedBuffer<T>(MergeFlatBuffers(
T::MiniReflectTypeTable(), reinterpret_cast<const uint8_t *>(fb1),
reinterpret_cast<const uint8_t *>(fb2)));
}
@@ -64,11 +67,11 @@
}
template <class T>
-inline Flatbuffer<T> CopyFlatBuffer(const T *t) {
+inline FlatbufferDetachedBuffer<T> CopyFlatBuffer(const T *t) {
flatbuffers::FlatBufferBuilder fbb;
fbb.ForceDefaults(1);
fbb.Finish(CopyFlatBuffer<T>(t, &fbb));
- return Flatbuffer<T>(fbb.Release());
+ return FlatbufferDetachedBuffer<T>(fbb.Release());
}
} // namespace aos
diff --git a/aos/flatbuffers.cc b/aos/flatbuffers.cc
new file mode 100644
index 0000000..3fe22c0
--- /dev/null
+++ b/aos/flatbuffers.cc
@@ -0,0 +1,22 @@
+#include "aos/flatbuffers.h"
+
+#include "glog/logging.h"
+
+namespace aos {
+
+uint8_t *FixedAllocatorBase::allocate(size_t) {
+ if (is_allocated_) {
+ LOG(FATAL) << "Tried to allocate already allocated flatbuffer";
+ }
+
+ is_allocated_ = true;
+ return data();
+}
+
+uint8_t *FixedAllocatorBase::reallocate_downward(uint8_t *, size_t, size_t,
+ size_t, size_t) {
+ LOG(FATAL) << "Tried to reallocate a flatbuffer";
+ return nullptr;
+}
+
+} // namespace aos
diff --git a/aos/flatbuffers.h b/aos/flatbuffers.h
index 6f6fc11..448f34b 100644
--- a/aos/flatbuffers.h
+++ b/aos/flatbuffers.h
@@ -5,8 +5,99 @@
namespace aos {
-// TODO(austin): FlatbufferBase ? We can associate the type table with it, and
-// make it generic.
+// This class is a base class for all sizes of array backed allocators.
+class FixedAllocatorBase : public flatbuffers::Allocator {
+ public:
+ // TODO(austin): Read the contract for these.
+ uint8_t *allocate(size_t) override;
+
+ void deallocate(uint8_t *, size_t) override { is_allocated_ = false; }
+
+ uint8_t *reallocate_downward(uint8_t *, size_t, size_t, size_t,
+ size_t) override;
+
+ virtual const uint8_t *data() const = 0;
+ virtual uint8_t *data() = 0;
+ virtual size_t size() const = 0;
+
+ private:
+ bool is_allocated_ = false;
+};
+
+// This class is a fixed memory allocator which holds the data for a flatbuffer
+// in an array.
+template <size_t S>
+class FixedAllocator : public FixedAllocatorBase {
+ public:
+ uint8_t *data() override { return &buffer_[0]; }
+ const uint8_t *data() const override { return &buffer_[0]; }
+ size_t size() const override { return buffer_.size(); }
+
+ private:
+ std::array<uint8_t, S> buffer_;
+};
+
+// Base class representing an object which holds the memory representing a root
+// flatbuffer.
+template <typename T>
+class Flatbuffer {
+ public:
+ // Returns the MiniReflectTypeTable for T.
+ static const flatbuffers::TypeTable *MiniReflectTypeTable() {
+ return T::MiniReflectTypeTable();
+ }
+
+ // Returns a message from the buffer.
+ const T &message() const {
+ return *flatbuffers::GetRoot<T>(reinterpret_cast<const void *>(data()));
+ }
+ // Returns a mutable message. It can be mutated via the flatbuffer rules.
+ T *mutable_message() {
+ return flatbuffers::GetMutableRoot<T>(reinterpret_cast<void *>(data()));
+ }
+
+ virtual const uint8_t *data() const = 0;
+ virtual uint8_t *data() = 0;
+ virtual size_t size() const = 0;
+};
+
+// Array backed flatbuffer.
+template <typename T>
+class FlatbufferArray : public Flatbuffer<T> {
+ public:
+ // Builds a Flatbuffer by copying the data from the other flatbuffer.
+ FlatbufferArray(const Flatbuffer<T> &other) {
+ CHECK_LE(other.size(), data_.size());
+
+ memcpy(data_.data(), other.data(), other.size());
+ size_ = other.size();
+ }
+
+ // Coppies the data from the other flatbuffer.
+ FlatbufferArray &operator=(const Flatbuffer<T> &other) {
+ CHECK_LE(other.size(), data_.size());
+
+ memcpy(data_.data(), other.data(), other.size());
+ size_ = other.size();
+ return *this;
+ }
+
+ // Creates a builder wrapping the underlying data.
+ flatbuffers::FlatBufferBuilder FlatBufferBuilder() {
+ data_.deallocate(data_.data(), data_.size());
+ flatbuffers::FlatBufferBuilder fbb(data_.size(), &data_);
+ fbb.ForceDefaults(1);
+ return fbb;
+ }
+
+ const uint8_t *data() const override { return data_.data(); }
+ uint8_t *data() override { return data_.data(); }
+ size_t size() const override { return size_; }
+
+ private:
+ FixedAllocator<8 * 1024> data_;
+ size_t size_ = data_.size();
+};
// This object associates the message type with the memory storing the
// flatbuffer. This only stores root tables.
@@ -14,50 +105,40 @@
// From a usage point of view, pointers to the data are very different than
// pointers to the tables.
template <typename T>
-class Flatbuffer {
+class FlatbufferDetachedBuffer : public Flatbuffer<T> {
public:
// Builds a Flatbuffer by taking ownership of the buffer.
- Flatbuffer(flatbuffers::DetachedBuffer &&buffer)
+ FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
: buffer_(::std::move(buffer)) {}
// Builds a flatbuffer by taking ownership of the buffer from the other
// flatbuffer.
- Flatbuffer(Flatbuffer &&fb) : buffer_(::std::move(fb.buffer_)) {}
- Flatbuffer &operator=(Flatbuffer &&fb) {
+ FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
+ : buffer_(::std::move(fb.buffer_)) {}
+ FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
::std::swap(buffer_, fb.buffer_);
return *this;
}
// Constructs an empty flatbuffer of type T.
- static Flatbuffer<T> Empty() {
+ static FlatbufferDetachedBuffer<T> Empty() {
flatbuffers::FlatBufferBuilder fbb;
fbb.ForceDefaults(1);
const auto end = fbb.EndTable(fbb.StartTable());
fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
- return Flatbuffer<T>(fbb.Release());
- }
-
- // Returns the MiniReflectTypeTable for T.
- static const flatbuffers::TypeTable *MiniReflectTypeTable() {
- return T::MiniReflectTypeTable();
- }
-
- // Returns a message from the buffer.
- const T &message() const { return *flatbuffers::GetRoot<T>(buffer_.data()); }
- // Returns a mutable message. It can be mutated via the flatbuffer rules.
- T *mutable_message() {
- return flatbuffers::GetMutableRoot<T>(buffer_.data());
+ return FlatbufferDetachedBuffer<T>(fbb.Release());
}
// Returns references to the buffer, and the data.
const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
- const uint8_t *data() const { return buffer_.data(); }
+ const uint8_t *data() const override { return buffer_.data(); }
+ uint8_t *data() override { return buffer_.data(); }
+ size_t size() const override { return buffer_.size(); }
private:
flatbuffers::DetachedBuffer buffer_;
};
-// TODO(austin): Need a fixed buffer version of Flatbuffer.
// TODO(austin): Need a way to get our hands on the max size. Can start with
// "large" for now.
diff --git a/aos/testdata/config1.json b/aos/testdata/config1.json
index 9f5fcb6..6bbf1a4 100644
--- a/aos/testdata/config1.json
+++ b/aos/testdata/config1.json
@@ -1,5 +1,5 @@
{
- "locations": [
+ "channels": [
{
"name": "/foo",
"type": ".aos.bar",
diff --git a/aos/testdata/config1_bad.json b/aos/testdata/config1_bad.json
index 738d46e..ff53a14 100644
--- a/aos/testdata/config1_bad.json
+++ b/aos/testdata/config1_bad.json
@@ -1,5 +1,5 @@
{
- "locations": [
+ "channels": [
{
"name": "/foo",
"type": ".aos.bar",
diff --git a/aos/testdata/config2.json b/aos/testdata/config2.json
index 0e6e451..2b8c67e 100644
--- a/aos/testdata/config2.json
+++ b/aos/testdata/config2.json
@@ -1,5 +1,5 @@
{
- "locations": [
+ "channels": [
{
"name": "/foo",
"type": ".aos.bar",
diff --git a/aos/testdata/config3.json b/aos/testdata/config3.json
index bb6c580..b29cc77 100644
--- a/aos/testdata/config3.json
+++ b/aos/testdata/config3.json
@@ -1,5 +1,5 @@
{
- "locations": [
+ "channels": [
{
"name": "/foo3",
"type": ".aos.bar"
diff --git a/aos/testdata/expected.json b/aos/testdata/expected.json
index 62c0bad..4227c91 100644
--- a/aos/testdata/expected.json
+++ b/aos/testdata/expected.json
@@ -1,5 +1,5 @@
{
- "locations": [
+ "channels": [
{
"name": "/foo",
"type": ".aos.bar",