blob: efb4f0eec7a21085b734931ea5e789aebf9d573d [file] [log] [blame]
Austin Schuhe93d8642019-10-13 15:27:07 -07001#ifndef AOS_FLATBUFFERS_H_
2#define AOS_FLATBUFFERS_H_
3
Alex Perrycb7da4b2019-08-28 19:35:56 -07004#include <array>
James Kuszmaul3ae42262019-11-08 12:33:41 -08005#include <string_view>
Alex Perrycb7da4b2019-08-28 19:35:56 -07006
Austin Schuh6f3babe2020-01-26 20:34:50 -08007#include "absl/types/span.h"
Brian Silverman354697a2020-09-22 21:06:32 -07008#include "aos/containers/resizeable_buffer.h"
Tyler Chatow116edf12020-01-26 11:52:39 -08009#include "aos/macros.h"
Austin Schuhb8075812020-10-19 09:36:49 -070010#include "flatbuffers/flatbuffers.h" // IWYU pragma: export
Austin Schuhe84c3ed2019-12-14 15:29:48 -080011#include "glog/logging.h"
Austin Schuhe93d8642019-10-13 15:27:07 -070012
13namespace aos {
14
Austin Schuh40485ed2019-10-26 21:51:44 -070015// This class is a base class for all sizes of array backed allocators.
16class FixedAllocatorBase : public flatbuffers::Allocator {
17 public:
Brian Silvermana1652f32020-01-29 20:41:44 -080018 ~FixedAllocatorBase() override { CHECK(!is_allocated_); }
19
Austin Schuh40485ed2019-10-26 21:51:44 -070020 // TODO(austin): Read the contract for these.
21 uint8_t *allocate(size_t) override;
22
Brian Silverman1715d472020-08-12 22:54:15 -070023 void deallocate(uint8_t *allocated_data, size_t allocated_size) override {
24 DCHECK_LE(allocated_size, size());
25 DCHECK_EQ(allocated_data, data());
26 CHECK(is_allocated_);
27 is_allocated_ = false;
28 }
Austin Schuh40485ed2019-10-26 21:51:44 -070029
30 uint8_t *reallocate_downward(uint8_t *, size_t, size_t, size_t,
31 size_t) override;
32
33 virtual const uint8_t *data() const = 0;
34 virtual uint8_t *data() = 0;
35 virtual size_t size() const = 0;
36
Brian Silverman1715d472020-08-12 22:54:15 -070037 void Reset() {
38 CHECK(!is_allocated_);
39 is_allocated_ = false;
40 }
Brian Silvermana1652f32020-01-29 20:41:44 -080041 bool is_allocated() const { return is_allocated_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070042
Tyler Chatow116edf12020-01-26 11:52:39 -080043 bool allocated() { return is_allocated_; }
44
Austin Schuh40485ed2019-10-26 21:51:44 -070045 private:
46 bool is_allocated_ = false;
47};
48
49// This class is a fixed memory allocator which holds the data for a flatbuffer
Tyler Chatow116edf12020-01-26 11:52:39 -080050// in a vector.
Austin Schuh40485ed2019-10-26 21:51:44 -070051class FixedAllocator : public FixedAllocatorBase {
52 public:
Austin Schuhe84c3ed2019-12-14 15:29:48 -080053 FixedAllocator(size_t size) : buffer_(size, 0) {}
54
Austin Schuh40485ed2019-10-26 21:51:44 -070055 uint8_t *data() override { return &buffer_[0]; }
56 const uint8_t *data() const override { return &buffer_[0]; }
57 size_t size() const override { return buffer_.size(); }
58
Austin Schuhe84c3ed2019-12-14 15:29:48 -080059 // Releases the data in the buffer.
60 std::vector<uint8_t> release() { return std::move(buffer_); }
61
Austin Schuh40485ed2019-10-26 21:51:44 -070062 private:
Austin Schuhe84c3ed2019-12-14 15:29:48 -080063 std::vector<uint8_t> buffer_;
Austin Schuh40485ed2019-10-26 21:51:44 -070064};
65
Alex Perrycb7da4b2019-08-28 19:35:56 -070066// This class adapts a preallocated memory region to an Allocator.
67class PreallocatedAllocator : public FixedAllocatorBase {
68 public:
69 PreallocatedAllocator(void *data, size_t size) : data_(data), size_(size) {}
Tyler Chatow116edf12020-01-26 11:52:39 -080070 PreallocatedAllocator(const PreallocatedAllocator &) = delete;
Brian Silvermana1652f32020-01-29 20:41:44 -080071 PreallocatedAllocator(PreallocatedAllocator &&other)
72 : data_(other.data_), size_(other.size_) {
Brian Silverman341b57e2020-06-23 16:23:18 -070073 CHECK(!is_allocated()) << ": May not overwrite in-use allocator";
Brian Silvermana1652f32020-01-29 20:41:44 -080074 CHECK(!other.is_allocated());
Alex Perrycb7da4b2019-08-28 19:35:56 -070075 }
Brian Silvermana1652f32020-01-29 20:41:44 -080076
77 PreallocatedAllocator &operator=(const PreallocatedAllocator &) = delete;
78 PreallocatedAllocator &operator=(PreallocatedAllocator &&other) {
Brian Silverman341b57e2020-06-23 16:23:18 -070079 CHECK(!is_allocated()) << ": May not overwrite in-use allocator";
Brian Silvermana1652f32020-01-29 20:41:44 -080080 CHECK(!other.is_allocated());
81 data_ = other.data_;
82 size_ = other.size_;
83 return *this;
84 }
85
86 uint8_t *data() final {
87 return reinterpret_cast<uint8_t *>(CHECK_NOTNULL(data_));
88 }
89 const uint8_t *data() const final {
90 return reinterpret_cast<const uint8_t *>(CHECK_NOTNULL(data_));
91 }
92 size_t size() const final { return size_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070093
94 private:
Brian Silvermana1652f32020-01-29 20:41:44 -080095 void *data_;
Alex Perrycb7da4b2019-08-28 19:35:56 -070096 size_t size_;
97};
98
Austin Schuh40485ed2019-10-26 21:51:44 -070099// Base class representing an object which holds the memory representing a root
100// flatbuffer.
101template <typename T>
102class Flatbuffer {
103 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -0700104 virtual ~Flatbuffer() {}
Austin Schuh40485ed2019-10-26 21:51:44 -0700105 // Returns the MiniReflectTypeTable for T.
106 static const flatbuffers::TypeTable *MiniReflectTypeTable() {
107 return T::MiniReflectTypeTable();
108 }
109
110 // Returns a message from the buffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800111 virtual const T &message() const = 0;
Austin Schuh40485ed2019-10-26 21:51:44 -0700112 // Returns a mutable message. It can be mutated via the flatbuffer rules.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800113 virtual T *mutable_message() = 0;
Austin Schuh39580f12020-08-01 14:44:08 -0700114
115 // Wipes out the data buffer. This is handy to mark an instance as freed, and
116 // make attempts to use it fail more obviously.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800117 void Wipe() { memset(span().data(), 0, span().size()); }
Austin Schuha4fc60f2020-11-01 23:06:47 -0800118
Austin Schuhadd6eb32020-11-09 21:24:26 -0800119 bool Verify() const {
120 flatbuffers::Verifier v(span().data(), span().size());
Austin Schuha4fc60f2020-11-01 23:06:47 -0800121 return v.VerifyTable(&message());
122 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800123
124 protected:
125 virtual absl::Span<uint8_t> span() = 0;
126 virtual absl::Span<const uint8_t> span() const = 0;
127};
128
129// Base class for non-size prefixed flatbuffers. span() means different things
130// across the 2 types, so you end up with a different GetRoot.
131template <typename T>
132class NonSizePrefixedFlatbuffer : public Flatbuffer<T> {
133 public:
134 const T &message() const override {
135 return *flatbuffers::GetRoot<T>(
136 reinterpret_cast<const void *>(this->span().data()));
137 }
138 T *mutable_message() override {
139 return flatbuffers::GetMutableRoot<T>(
140 reinterpret_cast<void *>(this->span().data()));
141 }
142
143 absl::Span<uint8_t> span() override = 0;
144 absl::Span<const uint8_t> span() const override = 0;
Austin Schuha4fc60f2020-11-01 23:06:47 -0800145};
146
147// Non-owning Span backed flatbuffer.
148template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800149class FlatbufferSpan : public NonSizePrefixedFlatbuffer<T> {
Austin Schuha4fc60f2020-11-01 23:06:47 -0800150 public:
151 // Builds a flatbuffer pointing to the contents of a span.
152 FlatbufferSpan(const absl::Span<const uint8_t> data) : data_(data) {}
153 // Builds a Flatbuffer pointing to the contents of another flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800154 FlatbufferSpan(const NonSizePrefixedFlatbuffer<T> &other) {
155 data_ = other.span();
156 }
Austin Schuha4fc60f2020-11-01 23:06:47 -0800157
158 // Copies the data from the other flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800159 FlatbufferSpan &operator=(const NonSizePrefixedFlatbuffer<T> &other) {
Austin Schuha4fc60f2020-11-01 23:06:47 -0800160 data_ = other.span();
161 return *this;
162 }
163
164 virtual ~FlatbufferSpan() override {}
165
Austin Schuhadd6eb32020-11-09 21:24:26 -0800166 absl::Span<uint8_t> span() override {
167 LOG(FATAL) << "Unimplemented";
168 return absl::Span<uint8_t>(nullptr, 0);
Austin Schuha4fc60f2020-11-01 23:06:47 -0800169 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800170 absl::Span<const uint8_t> span() const override { return data_; }
Austin Schuha4fc60f2020-11-01 23:06:47 -0800171
172 private:
173 absl::Span<const uint8_t> data_;
Austin Schuh40485ed2019-10-26 21:51:44 -0700174};
175
Alex Perrycb7da4b2019-08-28 19:35:56 -0700176// String backed flatbuffer.
177template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800178class FlatbufferString : public NonSizePrefixedFlatbuffer<T> {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700179 public:
180 // Builds a flatbuffer using the contents of the string.
James Kuszmaul3ae42262019-11-08 12:33:41 -0800181 FlatbufferString(const std::string_view data) : data_(data) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -0700182 // Builds a Flatbuffer by copying the data from the other flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800183 FlatbufferString(const NonSizePrefixedFlatbuffer<T> &other) {
184 absl::Span<const uint8_t> d = other.span();
185 data_ = std::string(reinterpret_cast<const char *>(d.data()), d.size());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700186 }
187
Jim Ostrowski46d25232020-09-07 18:44:17 -0700188 // Copies the data from the other flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800189 FlatbufferString &operator=(const NonSizePrefixedFlatbuffer<T> &other) {
190 absl::Span<const uint8_t> d = other.span();
191 data_ = std::string(reinterpret_cast<const char *>(d.data()), d.size());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700192 return *this;
193 }
194
195 virtual ~FlatbufferString() override {}
196
Austin Schuhadd6eb32020-11-09 21:24:26 -0800197 absl::Span<uint8_t> span() override {
198 return absl::Span<uint8_t>(reinterpret_cast<uint8_t *>(data_.data()),
199 data_.size());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700200 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800201 absl::Span<const uint8_t> span() const override {
202 return absl::Span<const uint8_t>(
203 reinterpret_cast<const uint8_t *>(data_.data()), data_.size());
204 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700205
206 private:
207 std::string data_;
208};
209
Austin Schuhadd6eb32020-11-09 21:24:26 -0800210// ResizeableBuffer backed flatbuffer.
Austin Schuhe309d2a2019-11-29 13:25:21 -0800211template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800212class FlatbufferVector : public NonSizePrefixedFlatbuffer<T> {
Austin Schuhe309d2a2019-11-29 13:25:21 -0800213 public:
Austin Schuhadd6eb32020-11-09 21:24:26 -0800214 // Builds a Flatbuffer around a ResizeableBuffer.
Brian Silverman354697a2020-09-22 21:06:32 -0700215 FlatbufferVector(ResizeableBuffer &&data) : data_(std::move(data)) {}
Austin Schuhe309d2a2019-11-29 13:25:21 -0800216
217 // Builds a Flatbuffer by copying the data from the other flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800218 FlatbufferVector(const NonSizePrefixedFlatbuffer<T> &other) {
219 data_.resize(other.span().size());
220 memcpy(data_.data(), other.span().data(), data_.size());
Brian Silverman354697a2020-09-22 21:06:32 -0700221 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800222
Austin Schuh5131bd02020-01-08 17:25:59 -0800223 // Copy constructor.
Brian Silverman354697a2020-09-22 21:06:32 -0700224 FlatbufferVector(const FlatbufferVector<T> &other) : data_(other.data_) {}
Austin Schuh5131bd02020-01-08 17:25:59 -0800225
Austin Schuh03803bd2019-12-30 18:08:17 -0800226 // Move constructor.
Austin Schuh5131bd02020-01-08 17:25:59 -0800227 FlatbufferVector(FlatbufferVector<T> &&other)
228 : data_(std::move(other.data_)) {}
Austin Schuh03803bd2019-12-30 18:08:17 -0800229
Austin Schuhe309d2a2019-11-29 13:25:21 -0800230 // Copies the data from the other flatbuffer.
Austin Schuh5131bd02020-01-08 17:25:59 -0800231 FlatbufferVector &operator=(const FlatbufferVector<T> &other) {
Brian Silverman354697a2020-09-22 21:06:32 -0700232 data_ = other.data_;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800233 return *this;
234 }
Austin Schuh5131bd02020-01-08 17:25:59 -0800235 FlatbufferVector &operator=(FlatbufferVector<T> &&other) {
236 data_ = std::move(other.data_);
237 return *this;
238 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800239
Austin Schuh05b70472020-01-01 17:11:17 -0800240 // Constructs an empty flatbuffer of type T.
241 static FlatbufferVector<T> Empty() {
Brian Silverman354697a2020-09-22 21:06:32 -0700242 return FlatbufferVector<T>(ResizeableBuffer());
Austin Schuh05b70472020-01-01 17:11:17 -0800243 }
244
Austin Schuhe309d2a2019-11-29 13:25:21 -0800245 virtual ~FlatbufferVector() override {}
246
Austin Schuhadd6eb32020-11-09 21:24:26 -0800247 absl::Span<uint8_t> span() override {
248 return absl::Span<uint8_t>(data_.data(), data_.size());
249 }
250 absl::Span<const uint8_t> span() const override {
251 return absl::Span<const uint8_t>(data_.data(), data_.size());
252 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800253
254 private:
Brian Silverman354697a2020-09-22 21:06:32 -0700255 ResizeableBuffer data_;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800256};
257
Austin Schuhe93d8642019-10-13 15:27:07 -0700258// This object associates the message type with the memory storing the
259// flatbuffer. This only stores root tables.
260//
261// From a usage point of view, pointers to the data are very different than
262// pointers to the tables.
263template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800264class FlatbufferDetachedBuffer final : public NonSizePrefixedFlatbuffer<T> {
Austin Schuhe93d8642019-10-13 15:27:07 -0700265 public:
266 // Builds a Flatbuffer by taking ownership of the buffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700267 FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
Austin Schuhe93d8642019-10-13 15:27:07 -0700268 : buffer_(::std::move(buffer)) {}
269
270 // Builds a flatbuffer by taking ownership of the buffer from the other
271 // flatbuffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700272 FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
273 : buffer_(::std::move(fb.buffer_)) {}
274 FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700275 ::std::swap(buffer_, fb.buffer_);
276 return *this;
277 }
278
Alex Perrycb7da4b2019-08-28 19:35:56 -0700279 virtual ~FlatbufferDetachedBuffer() override {}
280
Austin Schuhe93d8642019-10-13 15:27:07 -0700281 // Constructs an empty flatbuffer of type T.
Austin Schuh40485ed2019-10-26 21:51:44 -0700282 static FlatbufferDetachedBuffer<T> Empty() {
Austin Schuhe93d8642019-10-13 15:27:07 -0700283 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800284 fbb.ForceDefaults(true);
Austin Schuhe93d8642019-10-13 15:27:07 -0700285 const auto end = fbb.EndTable(fbb.StartTable());
286 fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh40485ed2019-10-26 21:51:44 -0700287 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700288 }
289
290 // Returns references to the buffer, and the data.
291 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800292
293 absl::Span<uint8_t> span() override {
294 return absl::Span<uint8_t>(buffer_.data(), buffer_.size());
295 }
296 absl::Span<const uint8_t> span() const override {
297 return absl::Span<const uint8_t>(buffer_.data(), buffer_.size());
298 }
Austin Schuhe93d8642019-10-13 15:27:07 -0700299
300 private:
301 flatbuffers::DetachedBuffer buffer_;
302};
303
Tyler Chatow116edf12020-01-26 11:52:39 -0800304// Array backed flatbuffer which manages building of the flatbuffer.
305template <typename T, size_t Size>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800306class FlatbufferFixedAllocatorArray final
307 : public NonSizePrefixedFlatbuffer<T> {
Tyler Chatow116edf12020-01-26 11:52:39 -0800308 public:
Brian Silverman1715d472020-08-12 22:54:15 -0700309 FlatbufferFixedAllocatorArray() : buffer_(), allocator_(&buffer_[0], Size) {}
310
311 FlatbufferFixedAllocatorArray(const FlatbufferFixedAllocatorArray &) = delete;
Austin Schuhadd6eb32020-11-09 21:24:26 -0800312 void operator=(const NonSizePrefixedFlatbuffer<T> &) = delete;
Brian Silverman1715d472020-08-12 22:54:15 -0700313
Austin Schuhadd6eb32020-11-09 21:24:26 -0800314 void CopyFrom(const NonSizePrefixedFlatbuffer<T> &other) {
Brian Silverman1715d472020-08-12 22:54:15 -0700315 CHECK(!allocator_.is_allocated()) << ": May not overwrite while building";
316 memcpy(buffer_.begin(), other.data(), other.size());
317 data_ = buffer_.begin();
318 size_ = other.size();
Tyler Chatow116edf12020-01-26 11:52:39 -0800319 }
320
Brian Silverman341b57e2020-06-23 16:23:18 -0700321 void Reset() {
Austin Schuh9dac21b2020-10-19 10:02:48 -0700322 CHECK(!allocator_.is_allocated() || data_ != nullptr)
323 << ": May not reset while building";
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700324 fbb_ = flatbuffers::FlatBufferBuilder(Size, &allocator_);
325 fbb_.ForceDefaults(true);
Austin Schuh9dac21b2020-10-19 10:02:48 -0700326 data_ = nullptr;
327 size_ = 0;
Brian Silverman341b57e2020-06-23 16:23:18 -0700328 }
329
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700330 flatbuffers::FlatBufferBuilder *fbb() {
Brian Silverman1715d472020-08-12 22:54:15 -0700331 CHECK(!allocator_.allocated())
332 << ": Array backed flatbuffer can only be built once";
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700333 fbb_ = flatbuffers::FlatBufferBuilder(Size, &allocator_);
334 fbb_.ForceDefaults(true);
335 return &fbb_;
Tyler Chatow116edf12020-01-26 11:52:39 -0800336 }
337
338 void Finish(flatbuffers::Offset<T> root) {
Brian Silverman1715d472020-08-12 22:54:15 -0700339 CHECK(allocator_.allocated()) << ": Cannot finish if not building";
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700340 fbb_.Finish(root);
341 data_ = fbb_.GetBufferPointer();
342 size_ = fbb_.GetSize();
Brian Silverman1715d472020-08-12 22:54:15 -0700343 DCHECK_LE(size_, Size);
Tyler Chatow116edf12020-01-26 11:52:39 -0800344 }
345
Austin Schuhadd6eb32020-11-09 21:24:26 -0800346 absl::Span<uint8_t> span() override {
347 return absl::Span<uint8_t>(data_, size_);
Tyler Chatow116edf12020-01-26 11:52:39 -0800348 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800349 absl::Span<const uint8_t> span() const override {
350 return absl::Span<const uint8_t>(data_, size_);
Tyler Chatow116edf12020-01-26 11:52:39 -0800351 }
Tyler Chatow116edf12020-01-26 11:52:39 -0800352
353 private:
354 std::array<uint8_t, Size> buffer_;
355 PreallocatedAllocator allocator_;
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700356 flatbuffers::FlatBufferBuilder fbb_;
Tyler Chatow116edf12020-01-26 11:52:39 -0800357 uint8_t *data_ = nullptr;
358 size_t size_ = 0;
Tyler Chatow116edf12020-01-26 11:52:39 -0800359};
360
Austin Schuhadd6eb32020-11-09 21:24:26 -0800361template <typename T>
362class SizePrefixedFlatbuffer : public Flatbuffer<T> {
363 public:
364 const T &message() const override {
365 return *flatbuffers::GetSizePrefixedRoot<T>(
366 reinterpret_cast<const void *>(this->span().data()));
367 }
368
369 T *mutable_message() override {
370 return flatbuffers::GetMutableSizePrefixedRoot<T>(
371 reinterpret_cast<void *>(this->span().data()));
372 }
373
374 absl::Span<uint8_t> span() override = 0;
375 absl::Span<const uint8_t> span() const override = 0;
376};
377
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800378// This object associates the message type with the memory storing the
379// flatbuffer. This only stores root tables.
380//
381// From a usage point of view, pointers to the data are very different than
382// pointers to the tables.
383template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800384class SizePrefixedFlatbufferDetachedBuffer final
385 : public SizePrefixedFlatbuffer<T> {
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800386 public:
387 // Builds a Flatbuffer by taking ownership of the buffer.
388 SizePrefixedFlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
389 : buffer_(::std::move(buffer)) {
390 CHECK_GE(buffer_.size(), sizeof(flatbuffers::uoffset_t));
391 }
392
393 // Builds a flatbuffer by taking ownership of the buffer from the other
394 // flatbuffer.
395 SizePrefixedFlatbufferDetachedBuffer(
396 SizePrefixedFlatbufferDetachedBuffer &&fb)
397 : buffer_(::std::move(fb.buffer_)) {}
398 SizePrefixedFlatbufferDetachedBuffer &operator=(
399 SizePrefixedFlatbufferDetachedBuffer &&fb) {
400 ::std::swap(buffer_, fb.buffer_);
401 return *this;
402 }
403
404 virtual ~SizePrefixedFlatbufferDetachedBuffer() override {}
405
Austin Schuh2f8fd752020-09-01 22:38:28 -0700406 static SizePrefixedFlatbufferDetachedBuffer<T> Empty() {
407 flatbuffers::FlatBufferBuilder fbb;
408 fbb.ForceDefaults(true);
409 const auto end = fbb.EndTable(fbb.StartTable());
410 fbb.FinishSizePrefixed(flatbuffers::Offset<flatbuffers::Table>(end));
411 return SizePrefixedFlatbufferDetachedBuffer<T>(fbb.Release());
412 }
413
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800414 // Returns references to the buffer, and the data.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800415 absl::Span<uint8_t> span() override {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700416 return absl::Span<uint8_t>(buffer_.data(), buffer_.size());
417 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800418 absl::Span<const uint8_t> span() const override {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700419 return absl::Span<const uint8_t>(buffer_.data(), buffer_.size());
420 }
421
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800422 private:
423 flatbuffers::DetachedBuffer buffer_;
424};
Austin Schuhe93d8642019-10-13 15:27:07 -0700425
Austin Schuhadd6eb32020-11-09 21:24:26 -0800426// ResizeableBuffer backed flatbuffer.
427template <typename T>
428class SizePrefixedFlatbufferVector : public SizePrefixedFlatbuffer<T> {
429 public:
430 // Builds a Flatbuffer around a ResizeableBuffer.
431 SizePrefixedFlatbufferVector(ResizeableBuffer &&data)
432 : data_(std::move(data)) {}
433
434 // Builds a Flatbuffer by copying the data from the other flatbuffer.
435 SizePrefixedFlatbufferVector(const SizePrefixedFlatbuffer<T> &other) {
436 data_.resize(other.span().size());
437 memcpy(data_.data(), other.span().data(), data_.size());
438 }
439
440 // Copy constructor.
441 SizePrefixedFlatbufferVector(const SizePrefixedFlatbufferVector<T> &other)
442 : data_(other.data_) {}
443
444 // Move constructor.
445 SizePrefixedFlatbufferVector(SizePrefixedFlatbufferVector<T> &&other)
446 : data_(std::move(other.data_)) {}
447
448 // Copies the data from the other flatbuffer.
449 SizePrefixedFlatbufferVector &operator=(
450 const SizePrefixedFlatbufferVector<T> &other) {
451 data_ = other.data_;
452 return *this;
453 }
454 SizePrefixedFlatbufferVector &operator=(
455 SizePrefixedFlatbufferVector<T> &&other) {
456 data_ = std::move(other.data_);
457 return *this;
458 }
459
460 // Constructs an empty flatbuffer of type T.
461 static SizePrefixedFlatbufferVector<T> Empty() {
462 return SizePrefixedFlatbufferVector<T>(ResizeableBuffer());
463 }
464
465 virtual ~SizePrefixedFlatbufferVector() override {}
466
467 absl::Span<uint8_t> span() override {
468 return absl::Span<uint8_t>(data_.data(), data_.size());
469 }
470 absl::Span<const uint8_t> span() const override {
471 return absl::Span<const uint8_t>(data_.data(), data_.size());
472 }
473
474 private:
475 ResizeableBuffer data_;
476};
477
Brian Silvermanf51499a2020-09-21 12:49:08 -0700478inline flatbuffers::DetachedBuffer CopySpanAsDetachedBuffer(
479 absl::Span<const uint8_t> span) {
480 // Copy the data from the span.
481 uint8_t *buf = flatbuffers::DefaultAllocator().allocate(span.size());
482 memcpy(buf, span.data(), span.size());
483 // Then give it to a DetachedBuffer to manage.
484 return flatbuffers::DetachedBuffer(nullptr, false, buf, span.size(), buf,
485 span.size());
486}
487
Austin Schuhe93d8642019-10-13 15:27:07 -0700488} // namespace aos
489
490#endif // AOS_FLATBUFFERS_H_