blob: fc91cf9b37a5159930b9cecb1926019b72aa7f39 [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>
5
6#include "absl/strings/string_view.h"
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.
130 FlatbufferString(const absl::string_view data) : data_(data) {}
131 // 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 }
147 uint8_t *data() override {
148 // TODO(james): when we get c++17, can we drop the second cast?
149 return const_cast<uint8_t *>(
150 reinterpret_cast<const uint8_t *>(data_.data()));
151 }
152 size_t size() const override { return data_.size(); }
153
154 private:
155 std::string data_;
156};
157
Austin Schuhe93d8642019-10-13 15:27:07 -0700158// This object associates the message type with the memory storing the
159// flatbuffer. This only stores root tables.
160//
161// From a usage point of view, pointers to the data are very different than
162// pointers to the tables.
163template <typename T>
Austin Schuh40485ed2019-10-26 21:51:44 -0700164class FlatbufferDetachedBuffer : public Flatbuffer<T> {
Austin Schuhe93d8642019-10-13 15:27:07 -0700165 public:
166 // Builds a Flatbuffer by taking ownership of the buffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700167 FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
Austin Schuhe93d8642019-10-13 15:27:07 -0700168 : buffer_(::std::move(buffer)) {}
169
170 // Builds a flatbuffer by taking ownership of the buffer from the other
171 // flatbuffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700172 FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
173 : buffer_(::std::move(fb.buffer_)) {}
174 FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700175 ::std::swap(buffer_, fb.buffer_);
176 return *this;
177 }
178
Alex Perrycb7da4b2019-08-28 19:35:56 -0700179 virtual ~FlatbufferDetachedBuffer() override {}
180
Austin Schuhe93d8642019-10-13 15:27:07 -0700181 // Constructs an empty flatbuffer of type T.
Austin Schuh40485ed2019-10-26 21:51:44 -0700182 static FlatbufferDetachedBuffer<T> Empty() {
Austin Schuhe93d8642019-10-13 15:27:07 -0700183 flatbuffers::FlatBufferBuilder fbb;
184 fbb.ForceDefaults(1);
185 const auto end = fbb.EndTable(fbb.StartTable());
186 fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh40485ed2019-10-26 21:51:44 -0700187 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700188 }
189
190 // Returns references to the buffer, and the data.
191 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
Austin Schuh40485ed2019-10-26 21:51:44 -0700192 const uint8_t *data() const override { return buffer_.data(); }
193 uint8_t *data() override { return buffer_.data(); }
194 size_t size() const override { return buffer_.size(); }
Austin Schuhe93d8642019-10-13 15:27:07 -0700195
196 private:
197 flatbuffers::DetachedBuffer buffer_;
198};
199
Austin Schuhe93d8642019-10-13 15:27:07 -0700200// TODO(austin): Need a way to get our hands on the max size. Can start with
201// "large" for now.
202
203} // namespace aos
204
205#endif // AOS_FLATBUFFERS_H_