blob: e5de1205b11b916daad94c65f4ae2d8a5afe0cb4 [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"
Philipp Schrader790cb542023-07-05 21:06:52 -07008#include "flatbuffers/flatbuffers.h" // IWYU pragma: export
9#include "glog/logging.h"
10
Brian Silverman354697a2020-09-22 21:06:32 -070011#include "aos/containers/resizeable_buffer.h"
Austin Schuh3c9f92c2024-04-30 17:56:42 -070012#include "aos/ipc_lib/data_alignment.h"
Tyler Chatow116edf12020-01-26 11:52:39 -080013#include "aos/macros.h"
davidjevans8b9b52f2021-09-17 08:57:30 -070014#include "aos/util/file.h"
Austin Schuhe93d8642019-10-13 15:27:07 -070015
16namespace aos {
17
Austin Schuh40485ed2019-10-26 21:51:44 -070018// This class is a base class for all sizes of array backed allocators.
19class FixedAllocatorBase : public flatbuffers::Allocator {
20 public:
Brian Silvermana1652f32020-01-29 20:41:44 -080021 ~FixedAllocatorBase() override { CHECK(!is_allocated_); }
22
Austin Schuh40485ed2019-10-26 21:51:44 -070023 // TODO(austin): Read the contract for these.
24 uint8_t *allocate(size_t) override;
25
Brian Silverman1715d472020-08-12 22:54:15 -070026 void deallocate(uint8_t *allocated_data, size_t allocated_size) override {
27 DCHECK_LE(allocated_size, size());
28 DCHECK_EQ(allocated_data, data());
29 CHECK(is_allocated_);
30 is_allocated_ = false;
31 }
Austin Schuh40485ed2019-10-26 21:51:44 -070032
33 uint8_t *reallocate_downward(uint8_t *, size_t, size_t, size_t,
34 size_t) override;
35
36 virtual const uint8_t *data() const = 0;
37 virtual uint8_t *data() = 0;
38 virtual size_t size() const = 0;
39
Brian Silverman1715d472020-08-12 22:54:15 -070040 void Reset() {
41 CHECK(!is_allocated_);
42 is_allocated_ = false;
43 }
Brian Silvermana1652f32020-01-29 20:41:44 -080044 bool is_allocated() const { return is_allocated_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070045
Tyler Chatow116edf12020-01-26 11:52:39 -080046 bool allocated() { return is_allocated_; }
47
Austin Schuh40485ed2019-10-26 21:51:44 -070048 private:
49 bool is_allocated_ = false;
50};
51
52// This class is a fixed memory allocator which holds the data for a flatbuffer
Tyler Chatow116edf12020-01-26 11:52:39 -080053// in a vector.
Austin Schuh40485ed2019-10-26 21:51:44 -070054class FixedAllocator : public FixedAllocatorBase {
55 public:
Austin Schuhe84c3ed2019-12-14 15:29:48 -080056 FixedAllocator(size_t size) : buffer_(size, 0) {}
57
Austin Schuh40485ed2019-10-26 21:51:44 -070058 uint8_t *data() override { return &buffer_[0]; }
59 const uint8_t *data() const override { return &buffer_[0]; }
60 size_t size() const override { return buffer_.size(); }
61
Austin Schuhe84c3ed2019-12-14 15:29:48 -080062 // Releases the data in the buffer.
63 std::vector<uint8_t> release() { return std::move(buffer_); }
64
Austin Schuh40485ed2019-10-26 21:51:44 -070065 private:
Austin Schuhe84c3ed2019-12-14 15:29:48 -080066 std::vector<uint8_t> buffer_;
Austin Schuh40485ed2019-10-26 21:51:44 -070067};
68
Alex Perrycb7da4b2019-08-28 19:35:56 -070069// This class adapts a preallocated memory region to an Allocator.
70class PreallocatedAllocator : public FixedAllocatorBase {
71 public:
72 PreallocatedAllocator(void *data, size_t size) : data_(data), size_(size) {}
Tyler Chatow116edf12020-01-26 11:52:39 -080073 PreallocatedAllocator(const PreallocatedAllocator &) = delete;
Brian Silvermana1652f32020-01-29 20:41:44 -080074 PreallocatedAllocator(PreallocatedAllocator &&other)
75 : data_(other.data_), size_(other.size_) {
Brian Silverman341b57e2020-06-23 16:23:18 -070076 CHECK(!is_allocated()) << ": May not overwrite in-use allocator";
Brian Silvermana1652f32020-01-29 20:41:44 -080077 CHECK(!other.is_allocated());
Alex Perrycb7da4b2019-08-28 19:35:56 -070078 }
Brian Silvermana1652f32020-01-29 20:41:44 -080079
80 PreallocatedAllocator &operator=(const PreallocatedAllocator &) = delete;
81 PreallocatedAllocator &operator=(PreallocatedAllocator &&other) {
Brian Silverman341b57e2020-06-23 16:23:18 -070082 CHECK(!is_allocated()) << ": May not overwrite in-use allocator";
Brian Silvermana1652f32020-01-29 20:41:44 -080083 CHECK(!other.is_allocated());
84 data_ = other.data_;
85 size_ = other.size_;
86 return *this;
87 }
88
89 uint8_t *data() final {
90 return reinterpret_cast<uint8_t *>(CHECK_NOTNULL(data_));
91 }
92 const uint8_t *data() const final {
93 return reinterpret_cast<const uint8_t *>(CHECK_NOTNULL(data_));
94 }
95 size_t size() const final { return size_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070096
97 private:
Brian Silvermana1652f32020-01-29 20:41:44 -080098 void *data_;
Alex Perrycb7da4b2019-08-28 19:35:56 -070099 size_t size_;
100};
101
Austin Schuh40485ed2019-10-26 21:51:44 -0700102// Base class representing an object which holds the memory representing a root
103// flatbuffer.
104template <typename T>
105class Flatbuffer {
106 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -0700107 virtual ~Flatbuffer() {}
Austin Schuh40485ed2019-10-26 21:51:44 -0700108 // Returns the MiniReflectTypeTable for T.
109 static const flatbuffers::TypeTable *MiniReflectTypeTable() {
110 return T::MiniReflectTypeTable();
111 }
112
113 // Returns a message from the buffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800114 virtual const T &message() const = 0;
Austin Schuh40485ed2019-10-26 21:51:44 -0700115 // Returns a mutable message. It can be mutated via the flatbuffer rules.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800116 virtual T *mutable_message() = 0;
Austin Schuh39580f12020-08-01 14:44:08 -0700117
118 // Wipes out the data buffer. This is handy to mark an instance as freed, and
119 // make attempts to use it fail more obviously.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800120 void Wipe() { memset(span().data(), 0, span().size()); }
Austin Schuha4fc60f2020-11-01 23:06:47 -0800121
James Kuszmaul38babac2024-01-25 14:35:08 -0800122 // Returns true if the flatbuffer is valid. Returns false if either:
123 // * The flatbuffer is incorrectly constructed (e.g., it points to memory
124 // locations outside of the current memory buffer).
125 // * The flatbuffer is too complex, and the flatbuffer verifier chosen to bail
126 // when attempting to traverse the tree of tables.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800127 bool Verify() const {
Austin Schuh977a5ed2020-12-02 23:20:04 -0800128 if (span().size() < 4u) {
129 return false;
130 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800131 flatbuffers::Verifier v(span().data(), span().size());
Austin Schuha4fc60f2020-11-01 23:06:47 -0800132 return v.VerifyTable(&message());
133 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800134
135 protected:
136 virtual absl::Span<uint8_t> span() = 0;
137 virtual absl::Span<const uint8_t> span() const = 0;
138};
139
140// Base class for non-size prefixed flatbuffers. span() means different things
141// across the 2 types, so you end up with a different GetRoot.
142template <typename T>
143class NonSizePrefixedFlatbuffer : public Flatbuffer<T> {
144 public:
145 const T &message() const override {
146 return *flatbuffers::GetRoot<T>(
147 reinterpret_cast<const void *>(this->span().data()));
148 }
149 T *mutable_message() override {
150 return flatbuffers::GetMutableRoot<T>(
151 reinterpret_cast<void *>(this->span().data()));
152 }
153
154 absl::Span<uint8_t> span() override = 0;
155 absl::Span<const uint8_t> span() const override = 0;
Austin Schuha4fc60f2020-11-01 23:06:47 -0800156};
157
158// Non-owning Span backed flatbuffer.
159template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800160class FlatbufferSpan : public NonSizePrefixedFlatbuffer<T> {
Austin Schuha4fc60f2020-11-01 23:06:47 -0800161 public:
162 // Builds a flatbuffer pointing to the contents of a span.
163 FlatbufferSpan(const absl::Span<const uint8_t> data) : data_(data) {}
164 // Builds a Flatbuffer pointing to the contents of another flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800165 FlatbufferSpan(const NonSizePrefixedFlatbuffer<T> &other) {
166 data_ = other.span();
167 }
Austin Schuha4fc60f2020-11-01 23:06:47 -0800168
169 // Copies the data from the other flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800170 FlatbufferSpan &operator=(const NonSizePrefixedFlatbuffer<T> &other) {
Austin Schuha4fc60f2020-11-01 23:06:47 -0800171 data_ = other.span();
172 return *this;
173 }
174
175 virtual ~FlatbufferSpan() override {}
176
Austin Schuhadd6eb32020-11-09 21:24:26 -0800177 absl::Span<uint8_t> span() override {
178 LOG(FATAL) << "Unimplemented";
179 return absl::Span<uint8_t>(nullptr, 0);
Austin Schuha4fc60f2020-11-01 23:06:47 -0800180 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800181 absl::Span<const uint8_t> span() const override { return data_; }
Austin Schuha4fc60f2020-11-01 23:06:47 -0800182
183 private:
184 absl::Span<const uint8_t> data_;
Austin Schuh40485ed2019-10-26 21:51:44 -0700185};
186
Austin Schuhadd6eb32020-11-09 21:24:26 -0800187// ResizeableBuffer backed flatbuffer.
Austin Schuhe309d2a2019-11-29 13:25:21 -0800188template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800189class FlatbufferVector : public NonSizePrefixedFlatbuffer<T> {
Austin Schuhe309d2a2019-11-29 13:25:21 -0800190 public:
Austin Schuhadd6eb32020-11-09 21:24:26 -0800191 // Builds a Flatbuffer around a ResizeableBuffer.
Brian Silverman354697a2020-09-22 21:06:32 -0700192 FlatbufferVector(ResizeableBuffer &&data) : data_(std::move(data)) {}
Austin Schuhe309d2a2019-11-29 13:25:21 -0800193
194 // Builds a Flatbuffer by copying the data from the other flatbuffer.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800195 FlatbufferVector(const NonSizePrefixedFlatbuffer<T> &other) {
196 data_.resize(other.span().size());
Stephan Pleines9dac6772023-06-01 13:21:41 -0700197 CHECK(other.span().data());
Austin Schuhadd6eb32020-11-09 21:24:26 -0800198 memcpy(data_.data(), other.span().data(), data_.size());
Brian Silverman354697a2020-09-22 21:06:32 -0700199 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800200
Austin Schuh5131bd02020-01-08 17:25:59 -0800201 // Copy constructor.
Brian Silverman354697a2020-09-22 21:06:32 -0700202 FlatbufferVector(const FlatbufferVector<T> &other) : data_(other.data_) {}
Austin Schuh5131bd02020-01-08 17:25:59 -0800203
Austin Schuh03803bd2019-12-30 18:08:17 -0800204 // Move constructor.
Austin Schuh5131bd02020-01-08 17:25:59 -0800205 FlatbufferVector(FlatbufferVector<T> &&other)
206 : data_(std::move(other.data_)) {}
Austin Schuh03803bd2019-12-30 18:08:17 -0800207
Austin Schuhe309d2a2019-11-29 13:25:21 -0800208 // Copies the data from the other flatbuffer.
Austin Schuh5131bd02020-01-08 17:25:59 -0800209 FlatbufferVector &operator=(const FlatbufferVector<T> &other) {
Brian Silverman354697a2020-09-22 21:06:32 -0700210 data_ = other.data_;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800211 return *this;
212 }
Austin Schuh5131bd02020-01-08 17:25:59 -0800213 FlatbufferVector &operator=(FlatbufferVector<T> &&other) {
214 data_ = std::move(other.data_);
215 return *this;
216 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800217
Austin Schuh05b70472020-01-01 17:11:17 -0800218 // Constructs an empty flatbuffer of type T.
219 static FlatbufferVector<T> Empty() {
Brian Silverman354697a2020-09-22 21:06:32 -0700220 return FlatbufferVector<T>(ResizeableBuffer());
Austin Schuh05b70472020-01-01 17:11:17 -0800221 }
222
Austin Schuhe309d2a2019-11-29 13:25:21 -0800223 virtual ~FlatbufferVector() override {}
224
Austin Schuhadd6eb32020-11-09 21:24:26 -0800225 absl::Span<uint8_t> span() override {
226 return absl::Span<uint8_t>(data_.data(), data_.size());
227 }
228 absl::Span<const uint8_t> span() const override {
229 return absl::Span<const uint8_t>(data_.data(), data_.size());
230 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800231
232 private:
Brian Silverman354697a2020-09-22 21:06:32 -0700233 ResizeableBuffer data_;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800234};
235
Austin Schuhe93d8642019-10-13 15:27:07 -0700236// This object associates the message type with the memory storing the
237// flatbuffer. This only stores root tables.
238//
239// From a usage point of view, pointers to the data are very different than
240// pointers to the tables.
241template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800242class FlatbufferDetachedBuffer final : public NonSizePrefixedFlatbuffer<T> {
Austin Schuhe93d8642019-10-13 15:27:07 -0700243 public:
244 // Builds a Flatbuffer by taking ownership of the buffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700245 FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
Austin Schuhe93d8642019-10-13 15:27:07 -0700246 : buffer_(::std::move(buffer)) {}
247
248 // Builds a flatbuffer by taking ownership of the buffer from the other
249 // flatbuffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700250 FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
251 : buffer_(::std::move(fb.buffer_)) {}
252 FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700253 ::std::swap(buffer_, fb.buffer_);
254 return *this;
255 }
256
Alex Perrycb7da4b2019-08-28 19:35:56 -0700257 virtual ~FlatbufferDetachedBuffer() override {}
258
Austin Schuhe93d8642019-10-13 15:27:07 -0700259 // Constructs an empty flatbuffer of type T.
Austin Schuh40485ed2019-10-26 21:51:44 -0700260 static FlatbufferDetachedBuffer<T> Empty() {
Austin Schuhe93d8642019-10-13 15:27:07 -0700261 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800262 fbb.ForceDefaults(true);
Austin Schuhe93d8642019-10-13 15:27:07 -0700263 const auto end = fbb.EndTable(fbb.StartTable());
264 fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh40485ed2019-10-26 21:51:44 -0700265 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700266 }
267
268 // Returns references to the buffer, and the data.
269 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800270
271 absl::Span<uint8_t> span() override {
272 return absl::Span<uint8_t>(buffer_.data(), buffer_.size());
273 }
274 absl::Span<const uint8_t> span() const override {
275 return absl::Span<const uint8_t>(buffer_.data(), buffer_.size());
276 }
Austin Schuhe93d8642019-10-13 15:27:07 -0700277
278 private:
279 flatbuffers::DetachedBuffer buffer_;
280};
281
Tyler Chatow116edf12020-01-26 11:52:39 -0800282// Array backed flatbuffer which manages building of the flatbuffer.
283template <typename T, size_t Size>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800284class FlatbufferFixedAllocatorArray final
285 : public NonSizePrefixedFlatbuffer<T> {
Tyler Chatow116edf12020-01-26 11:52:39 -0800286 public:
Brian Silverman1715d472020-08-12 22:54:15 -0700287 FlatbufferFixedAllocatorArray() : buffer_(), allocator_(&buffer_[0], Size) {}
288
289 FlatbufferFixedAllocatorArray(const FlatbufferFixedAllocatorArray &) = delete;
Austin Schuhadd6eb32020-11-09 21:24:26 -0800290 void operator=(const NonSizePrefixedFlatbuffer<T> &) = delete;
Brian Silverman1715d472020-08-12 22:54:15 -0700291
Austin Schuhadd6eb32020-11-09 21:24:26 -0800292 void CopyFrom(const NonSizePrefixedFlatbuffer<T> &other) {
Brian Silverman1715d472020-08-12 22:54:15 -0700293 CHECK(!allocator_.is_allocated()) << ": May not overwrite while building";
Austin Schuh12e77842020-11-11 20:02:55 -0800294 CHECK_LE(other.span().size(), Size)
295 << ": Source flatbuffer is larger than the target.";
296 memcpy(buffer_.begin(), other.span().data(), other.span().size());
Brian Silverman1715d472020-08-12 22:54:15 -0700297 data_ = buffer_.begin();
Austin Schuh12e77842020-11-11 20:02:55 -0800298 size_ = other.span().size();
Tyler Chatow116edf12020-01-26 11:52:39 -0800299 }
300
Brian Silverman341b57e2020-06-23 16:23:18 -0700301 void Reset() {
Austin Schuh9dac21b2020-10-19 10:02:48 -0700302 CHECK(!allocator_.is_allocated() || data_ != nullptr)
303 << ": May not reset while building";
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700304 fbb_ = flatbuffers::FlatBufferBuilder(Size, &allocator_);
305 fbb_.ForceDefaults(true);
Austin Schuh9dac21b2020-10-19 10:02:48 -0700306 data_ = nullptr;
307 size_ = 0;
Brian Silverman341b57e2020-06-23 16:23:18 -0700308 }
309
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700310 flatbuffers::FlatBufferBuilder *fbb() {
Brian Silverman1715d472020-08-12 22:54:15 -0700311 CHECK(!allocator_.allocated())
312 << ": Array backed flatbuffer can only be built once";
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700313 fbb_ = flatbuffers::FlatBufferBuilder(Size, &allocator_);
314 fbb_.ForceDefaults(true);
315 return &fbb_;
Tyler Chatow116edf12020-01-26 11:52:39 -0800316 }
317
318 void Finish(flatbuffers::Offset<T> root) {
Brian Silverman1715d472020-08-12 22:54:15 -0700319 CHECK(allocator_.allocated()) << ": Cannot finish if not building";
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700320 fbb_.Finish(root);
321 data_ = fbb_.GetBufferPointer();
322 size_ = fbb_.GetSize();
Brian Silverman1715d472020-08-12 22:54:15 -0700323 DCHECK_LE(size_, Size);
Tyler Chatow116edf12020-01-26 11:52:39 -0800324 }
325
Austin Schuhadd6eb32020-11-09 21:24:26 -0800326 absl::Span<uint8_t> span() override {
327 return absl::Span<uint8_t>(data_, size_);
Tyler Chatow116edf12020-01-26 11:52:39 -0800328 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800329 absl::Span<const uint8_t> span() const override {
330 return absl::Span<const uint8_t>(data_, size_);
Tyler Chatow116edf12020-01-26 11:52:39 -0800331 }
Tyler Chatow116edf12020-01-26 11:52:39 -0800332
333 private:
334 std::array<uint8_t, Size> buffer_;
335 PreallocatedAllocator allocator_;
Austin Schuh1bcd0e72020-08-26 21:50:45 -0700336 flatbuffers::FlatBufferBuilder fbb_;
Tyler Chatow116edf12020-01-26 11:52:39 -0800337 uint8_t *data_ = nullptr;
338 size_t size_ = 0;
Tyler Chatow116edf12020-01-26 11:52:39 -0800339};
340
Austin Schuhadd6eb32020-11-09 21:24:26 -0800341template <typename T>
342class SizePrefixedFlatbuffer : public Flatbuffer<T> {
343 public:
344 const T &message() const override {
345 return *flatbuffers::GetSizePrefixedRoot<T>(
346 reinterpret_cast<const void *>(this->span().data()));
347 }
348
349 T *mutable_message() override {
350 return flatbuffers::GetMutableSizePrefixedRoot<T>(
351 reinterpret_cast<void *>(this->span().data()));
352 }
353
354 absl::Span<uint8_t> span() override = 0;
355 absl::Span<const uint8_t> span() const override = 0;
356};
357
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800358// This object associates the message type with the memory storing the
359// flatbuffer. This only stores root tables.
360//
361// From a usage point of view, pointers to the data are very different than
362// pointers to the tables.
363template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800364class SizePrefixedFlatbufferDetachedBuffer final
365 : public SizePrefixedFlatbuffer<T> {
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800366 public:
367 // Builds a Flatbuffer by taking ownership of the buffer.
368 SizePrefixedFlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
369 : buffer_(::std::move(buffer)) {
370 CHECK_GE(buffer_.size(), sizeof(flatbuffers::uoffset_t));
371 }
372
373 // Builds a flatbuffer by taking ownership of the buffer from the other
374 // flatbuffer.
375 SizePrefixedFlatbufferDetachedBuffer(
376 SizePrefixedFlatbufferDetachedBuffer &&fb)
377 : buffer_(::std::move(fb.buffer_)) {}
378 SizePrefixedFlatbufferDetachedBuffer &operator=(
379 SizePrefixedFlatbufferDetachedBuffer &&fb) {
380 ::std::swap(buffer_, fb.buffer_);
381 return *this;
382 }
383
384 virtual ~SizePrefixedFlatbufferDetachedBuffer() override {}
385
Austin Schuh2f8fd752020-09-01 22:38:28 -0700386 static SizePrefixedFlatbufferDetachedBuffer<T> Empty() {
387 flatbuffers::FlatBufferBuilder fbb;
388 fbb.ForceDefaults(true);
389 const auto end = fbb.EndTable(fbb.StartTable());
390 fbb.FinishSizePrefixed(flatbuffers::Offset<flatbuffers::Table>(end));
391 return SizePrefixedFlatbufferDetachedBuffer<T>(fbb.Release());
392 }
393
Austin Schuh8c399962020-12-25 21:51:45 -0800394 flatbuffers::DetachedBuffer Release() {
395 flatbuffers::FlatBufferBuilder fbb;
396 fbb.ForceDefaults(true);
397 const auto end = fbb.EndTable(fbb.StartTable());
Austin Schuhfd7b6312021-07-30 18:26:51 -0700398 fbb.FinishSizePrefixed(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh8c399962020-12-25 21:51:45 -0800399 flatbuffers::DetachedBuffer result = fbb.Release();
400 std::swap(result, buffer_);
401 return result;
402 }
403
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800404 // Returns references to the buffer, and the data.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800405 absl::Span<uint8_t> span() override {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700406 return absl::Span<uint8_t>(buffer_.data(), buffer_.size());
407 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800408 absl::Span<const uint8_t> span() const override {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700409 return absl::Span<const uint8_t>(buffer_.data(), buffer_.size());
410 }
411
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800412 private:
413 flatbuffers::DetachedBuffer buffer_;
414};
Austin Schuhe93d8642019-10-13 15:27:07 -0700415
Austin Schuhadd6eb32020-11-09 21:24:26 -0800416// ResizeableBuffer backed flatbuffer.
417template <typename T>
418class SizePrefixedFlatbufferVector : public SizePrefixedFlatbuffer<T> {
419 public:
420 // Builds a Flatbuffer around a ResizeableBuffer.
421 SizePrefixedFlatbufferVector(ResizeableBuffer &&data)
422 : data_(std::move(data)) {}
423
424 // Builds a Flatbuffer by copying the data from the other flatbuffer.
Austin Schuhb929c4e2021-07-12 15:32:53 -0700425 SizePrefixedFlatbufferVector(const SizePrefixedFlatbuffer<T> &other)
426 : SizePrefixedFlatbufferVector(other.span()) {}
427
428 // Builds a flatbuffer by copying the data from the provided span.
429 SizePrefixedFlatbufferVector(const absl::Span<const uint8_t> span) {
430 data_.resize(span.size());
431 memcpy(data_.data(), span.data(), data_.size());
Austin Schuhadd6eb32020-11-09 21:24:26 -0800432 }
433
434 // Copy constructor.
435 SizePrefixedFlatbufferVector(const SizePrefixedFlatbufferVector<T> &other)
436 : data_(other.data_) {}
437
438 // Move constructor.
439 SizePrefixedFlatbufferVector(SizePrefixedFlatbufferVector<T> &&other)
440 : data_(std::move(other.data_)) {}
441
442 // Copies the data from the other flatbuffer.
443 SizePrefixedFlatbufferVector &operator=(
444 const SizePrefixedFlatbufferVector<T> &other) {
445 data_ = other.data_;
446 return *this;
447 }
448 SizePrefixedFlatbufferVector &operator=(
449 SizePrefixedFlatbufferVector<T> &&other) {
450 data_ = std::move(other.data_);
451 return *this;
452 }
453
454 // Constructs an empty flatbuffer of type T.
455 static SizePrefixedFlatbufferVector<T> Empty() {
456 return SizePrefixedFlatbufferVector<T>(ResizeableBuffer());
457 }
458
459 virtual ~SizePrefixedFlatbufferVector() override {}
460
461 absl::Span<uint8_t> span() override {
462 return absl::Span<uint8_t>(data_.data(), data_.size());
463 }
464 absl::Span<const uint8_t> span() const override {
465 return absl::Span<const uint8_t>(data_.data(), data_.size());
466 }
467
468 private:
469 ResizeableBuffer data_;
470};
471
Austin Schuh4b5c22a2020-11-30 22:58:43 -0800472// Non-owning Span backed flatbuffer.
473template <typename T>
474class SizePrefixedFlatbufferSpan : public SizePrefixedFlatbuffer<T> {
475 public:
476 // Builds a flatbuffer pointing to the contents of a span.
477 SizePrefixedFlatbufferSpan(const absl::Span<const uint8_t> data)
478 : data_(data) {}
479 // Builds a Flatbuffer pointing to the contents of another flatbuffer.
480 SizePrefixedFlatbufferSpan(const SizePrefixedFlatbuffer<T> &other) {
481 data_ = other.span();
482 }
483
484 // Points to the data in the other flatbuffer.
485 SizePrefixedFlatbufferSpan &operator=(
486 const SizePrefixedFlatbuffer<T> &other) {
487 data_ = other.span();
488 return *this;
489 }
490
491 ~SizePrefixedFlatbufferSpan() override {}
492
493 absl::Span<uint8_t> span() override {
494 LOG(FATAL) << "Unimplemented";
495 return absl::Span<uint8_t>(nullptr, 0);
496 }
497 absl::Span<const uint8_t> span() const override { return data_; }
498
499 private:
500 absl::Span<const uint8_t> data_;
501};
502
Brian Silvermanf51499a2020-09-21 12:49:08 -0700503inline flatbuffers::DetachedBuffer CopySpanAsDetachedBuffer(
504 absl::Span<const uint8_t> span) {
505 // Copy the data from the span.
506 uint8_t *buf = flatbuffers::DefaultAllocator().allocate(span.size());
507 memcpy(buf, span.data(), span.size());
508 // Then give it to a DetachedBuffer to manage.
509 return flatbuffers::DetachedBuffer(nullptr, false, buf, span.size(), buf,
510 span.size());
511}
512
davidjevans8b9b52f2021-09-17 08:57:30 -0700513// MMap a flatbuffer on disk.
514template <typename T>
515class FlatbufferMMap : public NonSizePrefixedFlatbuffer<T> {
516 public:
517 // Builds a Flatbuffer by mmaping the data from a flatbuffer saved on disk.
Austin Schuhe4d1a682021-10-01 15:04:50 -0700518 FlatbufferMMap(const std::string &flatbuffer_path,
519 util::FileOptions options = util::FileOptions::kReadable) {
520 span_ = util::MMapFile(flatbuffer_path, options);
davidjevans8b9b52f2021-09-17 08:57:30 -0700521 }
522
523 // Copies the reference to the mapped memory.
524 FlatbufferMMap(const FlatbufferMMap &) = default;
525 FlatbufferMMap &operator=(const FlatbufferMMap<T> &other) = default;
526
527 // Moves the reference to the mapped memory from one pointer to another.
528 FlatbufferMMap(FlatbufferMMap &&) = default;
529 FlatbufferMMap &operator=(FlatbufferMMap<T> &&other) = default;
530
Austin Schuhe4d1a682021-10-01 15:04:50 -0700531 absl::Span<uint8_t> span() override { return *span_; }
davidjevans8b9b52f2021-09-17 08:57:30 -0700532 absl::Span<const uint8_t> span() const override { return *span_; }
533
534 private:
535 std::shared_ptr<absl::Span<uint8_t>> span_;
536};
537
James Kuszmaul1d5d9ec2024-01-14 17:53:23 -0800538// The regular flatbuffer API makes it surprisingly irritating to unpack an
539// Object into an ObjectT without a bunch of extra lines.
540template <typename T>
541T::NativeTableType UnpackFlatbuffer(const T *fbs) {
542 typename T::NativeTableType object;
543 fbs->UnPackTo(&object);
544 return object;
545}
546
Austin Schuhe93d8642019-10-13 15:27:07 -0700547} // namespace aos
548
549#endif // AOS_FLATBUFFERS_H_