blob: 630741f2a9b19c8208b80ad62a9f933c5989ac77 [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"
8
9namespace aos {
10
Austin Schuh40485ed2019-10-26 21:51:44 -070011// This class is a base class for all sizes of array backed allocators.
12class FixedAllocatorBase : public flatbuffers::Allocator {
13 public:
14 // TODO(austin): Read the contract for these.
15 uint8_t *allocate(size_t) override;
16
17 void deallocate(uint8_t *, size_t) override { is_allocated_ = false; }
18
19 uint8_t *reallocate_downward(uint8_t *, size_t, size_t, size_t,
20 size_t) override;
21
22 virtual const uint8_t *data() const = 0;
23 virtual uint8_t *data() = 0;
24 virtual size_t size() const = 0;
25
Alex Perrycb7da4b2019-08-28 19:35:56 -070026 void Reset() { is_allocated_ = false; }
27
Austin Schuh40485ed2019-10-26 21:51:44 -070028 private:
29 bool is_allocated_ = false;
30};
31
32// This class is a fixed memory allocator which holds the data for a flatbuffer
33// in an array.
34template <size_t S>
35class FixedAllocator : public FixedAllocatorBase {
36 public:
37 uint8_t *data() override { return &buffer_[0]; }
38 const uint8_t *data() const override { return &buffer_[0]; }
39 size_t size() const override { return buffer_.size(); }
40
41 private:
42 std::array<uint8_t, S> buffer_;
43};
44
Alex Perrycb7da4b2019-08-28 19:35:56 -070045// This class adapts a preallocated memory region to an Allocator.
46class PreallocatedAllocator : public FixedAllocatorBase {
47 public:
48 PreallocatedAllocator(void *data, size_t size) : data_(data), size_(size) {}
49 uint8_t *data() override { return reinterpret_cast<uint8_t *>(data_); }
50 const uint8_t *data() const override {
51 return reinterpret_cast<const uint8_t *>(data_);
52 }
53 size_t size() const override { return size_; }
54
55 private:
56 void* data_;
57 size_t size_;
58};
59
Austin Schuh40485ed2019-10-26 21:51:44 -070060// Base class representing an object which holds the memory representing a root
61// flatbuffer.
62template <typename T>
63class Flatbuffer {
64 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 virtual ~Flatbuffer() {}
Austin Schuh40485ed2019-10-26 21:51:44 -070066 // Returns the MiniReflectTypeTable for T.
67 static const flatbuffers::TypeTable *MiniReflectTypeTable() {
68 return T::MiniReflectTypeTable();
69 }
70
71 // Returns a message from the buffer.
72 const T &message() const {
73 return *flatbuffers::GetRoot<T>(reinterpret_cast<const void *>(data()));
74 }
75 // Returns a mutable message. It can be mutated via the flatbuffer rules.
76 T *mutable_message() {
77 return flatbuffers::GetMutableRoot<T>(reinterpret_cast<void *>(data()));
78 }
79
80 virtual const uint8_t *data() const = 0;
81 virtual uint8_t *data() = 0;
82 virtual size_t size() const = 0;
83};
84
85// Array backed flatbuffer.
86template <typename T>
87class FlatbufferArray : public Flatbuffer<T> {
88 public:
89 // Builds a Flatbuffer by copying the data from the other flatbuffer.
90 FlatbufferArray(const Flatbuffer<T> &other) {
91 CHECK_LE(other.size(), data_.size());
92
93 memcpy(data_.data(), other.data(), other.size());
94 size_ = other.size();
95 }
96
97 // Coppies the data from the other flatbuffer.
98 FlatbufferArray &operator=(const Flatbuffer<T> &other) {
99 CHECK_LE(other.size(), data_.size());
100
101 memcpy(data_.data(), other.data(), other.size());
102 size_ = other.size();
103 return *this;
104 }
105
Alex Perrycb7da4b2019-08-28 19:35:56 -0700106 virtual ~FlatbufferArray() override {}
107
Austin Schuh40485ed2019-10-26 21:51:44 -0700108 // Creates a builder wrapping the underlying data.
109 flatbuffers::FlatBufferBuilder FlatBufferBuilder() {
110 data_.deallocate(data_.data(), data_.size());
111 flatbuffers::FlatBufferBuilder fbb(data_.size(), &data_);
112 fbb.ForceDefaults(1);
113 return fbb;
114 }
115
116 const uint8_t *data() const override { return data_.data(); }
117 uint8_t *data() override { return data_.data(); }
118 size_t size() const override { return size_; }
119
120 private:
121 FixedAllocator<8 * 1024> data_;
122 size_t size_ = data_.size();
123};
Austin Schuhe93d8642019-10-13 15:27:07 -0700124
Alex Perrycb7da4b2019-08-28 19:35:56 -0700125// String backed flatbuffer.
126template <typename T>
127class FlatbufferString : public Flatbuffer<T> {
128 public:
129 // Builds a flatbuffer using the contents of the string.
James Kuszmaul3ae42262019-11-08 12:33:41 -0800130 FlatbufferString(const std::string_view data) : data_(data) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -0700131 // Builds a Flatbuffer by copying the data from the other flatbuffer.
132 FlatbufferString(const Flatbuffer<T> &other) {
133 data_ = std::string(other.data(), other.size());
134 }
135
136 // Coppies the data from the other flatbuffer.
137 FlatbufferString &operator=(const Flatbuffer<T> &other) {
138 data_ = std::string(other.data(), other.size());
139 return *this;
140 }
141
142 virtual ~FlatbufferString() override {}
143
144 const uint8_t *data() const override {
145 return reinterpret_cast<const uint8_t *>(data_.data());
146 }
James Kuszmaul872efd22019-12-03 20:59:09 -0800147 uint8_t *data() override { return reinterpret_cast<uint8_t *>(data_.data()); }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700148 size_t size() const override { return data_.size(); }
149
150 private:
151 std::string data_;
152};
153
Austin Schuhe309d2a2019-11-29 13:25:21 -0800154// Vector backed flatbuffer.
155template <typename T>
156class FlatbufferVector : public Flatbuffer<T> {
157 public:
158 // Builds a Flatbuffer around a vector.
159 FlatbufferVector(std::vector<uint8_t> &&data) : data_(std::move(data)) {}
160
161 // Builds a Flatbuffer by copying the data from the other flatbuffer.
162 FlatbufferVector(const Flatbuffer<T> &other)
163 : data_(other.data(), other.data() + other.size()) {}
164
Austin Schuh03803bd2019-12-30 18:08:17 -0800165 // Move constructor.
166 FlatbufferVector(Flatbuffer<T> &&other) : data_(std::move(other.data())) {}
167
Austin Schuhe309d2a2019-11-29 13:25:21 -0800168 // Copies the data from the other flatbuffer.
169 FlatbufferVector &operator=(const Flatbuffer<T> &other) {
170 data_ = std::vector<uint8_t>(other.data(), other.data() + other.size());
171 return *this;
172 }
173
174 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 Schuhe93d8642019-10-13 15:27:07 -0700226// TODO(austin): Need a way to get our hands on the max size. Can start with
227// "large" for now.
228
229} // namespace aos
230
231#endif // AOS_FLATBUFFERS_H_