blob: ff2dced967229cd8d99ce093b324ad1117924e4e [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 Schuhe93d8642019-10-13 15:27:07 -0700154// This object associates the message type with the memory storing the
155// flatbuffer. This only stores root tables.
156//
157// From a usage point of view, pointers to the data are very different than
158// pointers to the tables.
159template <typename T>
James Kuszmaul3ae42262019-11-08 12:33:41 -0800160class FlatbufferDetachedBuffer final : public Flatbuffer<T> {
Austin Schuhe93d8642019-10-13 15:27:07 -0700161 public:
162 // Builds a Flatbuffer by taking ownership of the buffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700163 FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
Austin Schuhe93d8642019-10-13 15:27:07 -0700164 : buffer_(::std::move(buffer)) {}
165
166 // Builds a flatbuffer by taking ownership of the buffer from the other
167 // flatbuffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700168 FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
169 : buffer_(::std::move(fb.buffer_)) {}
170 FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700171 ::std::swap(buffer_, fb.buffer_);
172 return *this;
173 }
174
Alex Perrycb7da4b2019-08-28 19:35:56 -0700175 virtual ~FlatbufferDetachedBuffer() override {}
176
Austin Schuhe93d8642019-10-13 15:27:07 -0700177 // Constructs an empty flatbuffer of type T.
Austin Schuh40485ed2019-10-26 21:51:44 -0700178 static FlatbufferDetachedBuffer<T> Empty() {
Austin Schuhe93d8642019-10-13 15:27:07 -0700179 flatbuffers::FlatBufferBuilder fbb;
180 fbb.ForceDefaults(1);
181 const auto end = fbb.EndTable(fbb.StartTable());
182 fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh40485ed2019-10-26 21:51:44 -0700183 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700184 }
185
186 // Returns references to the buffer, and the data.
187 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
Austin Schuh40485ed2019-10-26 21:51:44 -0700188 const uint8_t *data() const override { return buffer_.data(); }
189 uint8_t *data() override { return buffer_.data(); }
190 size_t size() const override { return buffer_.size(); }
Austin Schuhe93d8642019-10-13 15:27:07 -0700191
192 private:
193 flatbuffers::DetachedBuffer buffer_;
194};
195
Austin Schuhe93d8642019-10-13 15:27:07 -0700196// TODO(austin): Need a way to get our hands on the max size. Can start with
197// "large" for now.
198
199} // namespace aos
200
201#endif // AOS_FLATBUFFERS_H_