blob: d9fcab619629b0ff05c6858d5f66de278bdc5f20 [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 Schuhe93d8642019-10-13 15:27:07 -07007#include "flatbuffers/flatbuffers.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -08008#include "glog/logging.h"
Austin Schuhe93d8642019-10-13 15:27:07 -07009
10namespace aos {
11
Austin Schuh40485ed2019-10-26 21:51:44 -070012// This class is a base class for all sizes of array backed allocators.
13class FixedAllocatorBase : public flatbuffers::Allocator {
14 public:
Brian Silvermana1652f32020-01-29 20:41:44 -080015 ~FixedAllocatorBase() override { CHECK(!is_allocated_); }
16
Austin Schuh40485ed2019-10-26 21:51:44 -070017 // TODO(austin): Read the contract for these.
18 uint8_t *allocate(size_t) override;
19
20 void deallocate(uint8_t *, size_t) override { is_allocated_ = false; }
21
22 uint8_t *reallocate_downward(uint8_t *, size_t, size_t, size_t,
23 size_t) override;
24
25 virtual const uint8_t *data() const = 0;
26 virtual uint8_t *data() = 0;
27 virtual size_t size() const = 0;
28
Alex Perrycb7da4b2019-08-28 19:35:56 -070029 void Reset() { is_allocated_ = false; }
Brian Silvermana1652f32020-01-29 20:41:44 -080030 bool is_allocated() const { return is_allocated_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070031
Austin Schuh40485ed2019-10-26 21:51:44 -070032 private:
33 bool is_allocated_ = false;
34};
35
36// This class is a fixed memory allocator which holds the data for a flatbuffer
37// in an array.
Austin Schuh40485ed2019-10-26 21:51:44 -070038class FixedAllocator : public FixedAllocatorBase {
39 public:
Austin Schuhe84c3ed2019-12-14 15:29:48 -080040 FixedAllocator(size_t size) : buffer_(size, 0) {}
41
Austin Schuh40485ed2019-10-26 21:51:44 -070042 uint8_t *data() override { return &buffer_[0]; }
43 const uint8_t *data() const override { return &buffer_[0]; }
44 size_t size() const override { return buffer_.size(); }
45
Austin Schuhe84c3ed2019-12-14 15:29:48 -080046 // Releases the data in the buffer.
47 std::vector<uint8_t> release() { return std::move(buffer_); }
48
Austin Schuh40485ed2019-10-26 21:51:44 -070049 private:
Austin Schuhe84c3ed2019-12-14 15:29:48 -080050 std::vector<uint8_t> buffer_;
Austin Schuh40485ed2019-10-26 21:51:44 -070051};
52
Alex Perrycb7da4b2019-08-28 19:35:56 -070053// This class adapts a preallocated memory region to an Allocator.
54class PreallocatedAllocator : public FixedAllocatorBase {
55 public:
56 PreallocatedAllocator(void *data, size_t size) : data_(data), size_(size) {}
Brian Silvermana1652f32020-01-29 20:41:44 -080057 PreallocatedAllocator(const PreallocatedAllocator&) = delete;
58 PreallocatedAllocator(PreallocatedAllocator &&other)
59 : data_(other.data_), size_(other.size_) {
60 CHECK(!is_allocated());
61 CHECK(!other.is_allocated());
Alex Perrycb7da4b2019-08-28 19:35:56 -070062 }
Brian Silvermana1652f32020-01-29 20:41:44 -080063
64 PreallocatedAllocator &operator=(const PreallocatedAllocator &) = delete;
65 PreallocatedAllocator &operator=(PreallocatedAllocator &&other) {
66 CHECK(!is_allocated());
67 CHECK(!other.is_allocated());
68 data_ = other.data_;
69 size_ = other.size_;
70 return *this;
71 }
72
73 uint8_t *data() final {
74 return reinterpret_cast<uint8_t *>(CHECK_NOTNULL(data_));
75 }
76 const uint8_t *data() const final {
77 return reinterpret_cast<const uint8_t *>(CHECK_NOTNULL(data_));
78 }
79 size_t size() const final { return size_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070080
81 private:
Brian Silvermana1652f32020-01-29 20:41:44 -080082 void *data_;
Alex Perrycb7da4b2019-08-28 19:35:56 -070083 size_t size_;
84};
85
Austin Schuh40485ed2019-10-26 21:51:44 -070086// Base class representing an object which holds the memory representing a root
87// flatbuffer.
88template <typename T>
89class Flatbuffer {
90 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070091 virtual ~Flatbuffer() {}
Austin Schuh40485ed2019-10-26 21:51:44 -070092 // Returns the MiniReflectTypeTable for T.
93 static const flatbuffers::TypeTable *MiniReflectTypeTable() {
94 return T::MiniReflectTypeTable();
95 }
96
97 // Returns a message from the buffer.
98 const T &message() const {
99 return *flatbuffers::GetRoot<T>(reinterpret_cast<const void *>(data()));
100 }
101 // Returns a mutable message. It can be mutated via the flatbuffer rules.
102 T *mutable_message() {
103 return flatbuffers::GetMutableRoot<T>(reinterpret_cast<void *>(data()));
104 }
105
106 virtual const uint8_t *data() const = 0;
107 virtual uint8_t *data() = 0;
108 virtual size_t size() const = 0;
109};
110
Alex Perrycb7da4b2019-08-28 19:35:56 -0700111// String backed flatbuffer.
112template <typename T>
113class FlatbufferString : public Flatbuffer<T> {
114 public:
115 // Builds a flatbuffer using the contents of the string.
James Kuszmaul3ae42262019-11-08 12:33:41 -0800116 FlatbufferString(const std::string_view data) : data_(data) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -0700117 // Builds a Flatbuffer by copying the data from the other flatbuffer.
118 FlatbufferString(const Flatbuffer<T> &other) {
119 data_ = std::string(other.data(), other.size());
120 }
121
122 // Coppies the data from the other flatbuffer.
123 FlatbufferString &operator=(const Flatbuffer<T> &other) {
124 data_ = std::string(other.data(), other.size());
125 return *this;
126 }
127
128 virtual ~FlatbufferString() override {}
129
130 const uint8_t *data() const override {
131 return reinterpret_cast<const uint8_t *>(data_.data());
132 }
James Kuszmaul872efd22019-12-03 20:59:09 -0800133 uint8_t *data() override { return reinterpret_cast<uint8_t *>(data_.data()); }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700134 size_t size() const override { return data_.size(); }
135
136 private:
137 std::string data_;
138};
139
Austin Schuhe309d2a2019-11-29 13:25:21 -0800140// Vector backed flatbuffer.
141template <typename T>
142class FlatbufferVector : public Flatbuffer<T> {
143 public:
144 // Builds a Flatbuffer around a vector.
145 FlatbufferVector(std::vector<uint8_t> &&data) : data_(std::move(data)) {}
146
147 // Builds a Flatbuffer by copying the data from the other flatbuffer.
148 FlatbufferVector(const Flatbuffer<T> &other)
149 : data_(other.data(), other.data() + other.size()) {}
150
Austin Schuh5131bd02020-01-08 17:25:59 -0800151 // Copy constructor.
152 FlatbufferVector(const FlatbufferVector<T> &other)
153 : data_(other.data(), other.data() + other.size()) {}
154
Austin Schuh03803bd2019-12-30 18:08:17 -0800155 // Move constructor.
Austin Schuh5131bd02020-01-08 17:25:59 -0800156 FlatbufferVector(FlatbufferVector<T> &&other)
157 : data_(std::move(other.data_)) {}
Austin Schuh03803bd2019-12-30 18:08:17 -0800158
Austin Schuhe309d2a2019-11-29 13:25:21 -0800159 // Copies the data from the other flatbuffer.
Austin Schuh5131bd02020-01-08 17:25:59 -0800160 FlatbufferVector &operator=(const FlatbufferVector<T> &other) {
Austin Schuhe309d2a2019-11-29 13:25:21 -0800161 data_ = std::vector<uint8_t>(other.data(), other.data() + other.size());
162 return *this;
163 }
Austin Schuh5131bd02020-01-08 17:25:59 -0800164 FlatbufferVector &operator=(FlatbufferVector<T> &&other) {
165 data_ = std::move(other.data_);
166 return *this;
167 }
Austin Schuhe309d2a2019-11-29 13:25:21 -0800168
Austin Schuh05b70472020-01-01 17:11:17 -0800169 // Constructs an empty flatbuffer of type T.
170 static FlatbufferVector<T> Empty() {
171 return FlatbufferVector<T>(std::vector<uint8_t>{});
172 }
173
Austin Schuhe309d2a2019-11-29 13:25:21 -0800174 virtual ~FlatbufferVector() override {}
175
176 const uint8_t *data() const override { return data_.data(); }
177 uint8_t *data() override { return data_.data(); }
178 size_t size() const override { return data_.size(); }
179
180 private:
181 std::vector<uint8_t> data_;
182};
183
Austin Schuhe93d8642019-10-13 15:27:07 -0700184// This object associates the message type with the memory storing the
185// flatbuffer. This only stores root tables.
186//
187// From a usage point of view, pointers to the data are very different than
188// pointers to the tables.
189template <typename T>
James Kuszmaul3ae42262019-11-08 12:33:41 -0800190class FlatbufferDetachedBuffer final : public Flatbuffer<T> {
Austin Schuhe93d8642019-10-13 15:27:07 -0700191 public:
192 // Builds a Flatbuffer by taking ownership of the buffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700193 FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
Austin Schuhe93d8642019-10-13 15:27:07 -0700194 : buffer_(::std::move(buffer)) {}
195
196 // Builds a flatbuffer by taking ownership of the buffer from the other
197 // flatbuffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700198 FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
199 : buffer_(::std::move(fb.buffer_)) {}
200 FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700201 ::std::swap(buffer_, fb.buffer_);
202 return *this;
203 }
204
Alex Perrycb7da4b2019-08-28 19:35:56 -0700205 virtual ~FlatbufferDetachedBuffer() override {}
206
Austin Schuhe93d8642019-10-13 15:27:07 -0700207 // Constructs an empty flatbuffer of type T.
Austin Schuh40485ed2019-10-26 21:51:44 -0700208 static FlatbufferDetachedBuffer<T> Empty() {
Austin Schuhe93d8642019-10-13 15:27:07 -0700209 flatbuffers::FlatBufferBuilder fbb;
210 fbb.ForceDefaults(1);
211 const auto end = fbb.EndTable(fbb.StartTable());
212 fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh40485ed2019-10-26 21:51:44 -0700213 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700214 }
215
216 // Returns references to the buffer, and the data.
217 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
Austin Schuh40485ed2019-10-26 21:51:44 -0700218 const uint8_t *data() const override { return buffer_.data(); }
219 uint8_t *data() override { return buffer_.data(); }
220 size_t size() const override { return buffer_.size(); }
Austin Schuhe93d8642019-10-13 15:27:07 -0700221
222 private:
223 flatbuffers::DetachedBuffer buffer_;
224};
225
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800226// This object associates the message type with the memory storing the
227// flatbuffer. This only stores root tables.
228//
229// From a usage point of view, pointers to the data are very different than
230// pointers to the tables.
231template <typename T>
232class SizePrefixedFlatbufferDetachedBuffer final : public Flatbuffer<T> {
233 public:
234 // Builds a Flatbuffer by taking ownership of the buffer.
235 SizePrefixedFlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
236 : buffer_(::std::move(buffer)) {
237 CHECK_GE(buffer_.size(), sizeof(flatbuffers::uoffset_t));
238 }
239
240 // Builds a flatbuffer by taking ownership of the buffer from the other
241 // flatbuffer.
242 SizePrefixedFlatbufferDetachedBuffer(
243 SizePrefixedFlatbufferDetachedBuffer &&fb)
244 : buffer_(::std::move(fb.buffer_)) {}
245 SizePrefixedFlatbufferDetachedBuffer &operator=(
246 SizePrefixedFlatbufferDetachedBuffer &&fb) {
247 ::std::swap(buffer_, fb.buffer_);
248 return *this;
249 }
250
251 virtual ~SizePrefixedFlatbufferDetachedBuffer() override {}
252
253 // Returns references to the buffer, and the data.
254 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
255 const uint8_t *data() const override {
256 return buffer_.data() + sizeof(flatbuffers::uoffset_t);
257 }
258 uint8_t *data() override {
259 return buffer_.data() + sizeof(flatbuffers::uoffset_t);
260 }
261 size_t size() const override {
262 return buffer_.size() - sizeof(flatbuffers::uoffset_t);
263 }
264
265 private:
266 flatbuffers::DetachedBuffer buffer_;
267};
Austin Schuhe93d8642019-10-13 15:27:07 -0700268// TODO(austin): Need a way to get our hands on the max size. Can start with
269// "large" for now.
270
271} // namespace aos
272
273#endif // AOS_FLATBUFFERS_H_