blob: 448f34b7c746c53d573f3111848a70da7624ef2f [file] [log] [blame]
Austin Schuhe93d8642019-10-13 15:27:07 -07001#ifndef AOS_FLATBUFFERS_H_
2#define AOS_FLATBUFFERS_H_
3
4#include "flatbuffers/flatbuffers.h"
5
6namespace aos {
7
Austin Schuh40485ed2019-10-26 21:51:44 -07008// This class is a base class for all sizes of array backed allocators.
9class FixedAllocatorBase : public flatbuffers::Allocator {
10 public:
11 // TODO(austin): Read the contract for these.
12 uint8_t *allocate(size_t) override;
13
14 void deallocate(uint8_t *, size_t) override { is_allocated_ = false; }
15
16 uint8_t *reallocate_downward(uint8_t *, size_t, size_t, size_t,
17 size_t) override;
18
19 virtual const uint8_t *data() const = 0;
20 virtual uint8_t *data() = 0;
21 virtual size_t size() const = 0;
22
23 private:
24 bool is_allocated_ = false;
25};
26
27// This class is a fixed memory allocator which holds the data for a flatbuffer
28// in an array.
29template <size_t S>
30class FixedAllocator : public FixedAllocatorBase {
31 public:
32 uint8_t *data() override { return &buffer_[0]; }
33 const uint8_t *data() const override { return &buffer_[0]; }
34 size_t size() const override { return buffer_.size(); }
35
36 private:
37 std::array<uint8_t, S> buffer_;
38};
39
40// Base class representing an object which holds the memory representing a root
41// flatbuffer.
42template <typename T>
43class Flatbuffer {
44 public:
45 // Returns the MiniReflectTypeTable for T.
46 static const flatbuffers::TypeTable *MiniReflectTypeTable() {
47 return T::MiniReflectTypeTable();
48 }
49
50 // Returns a message from the buffer.
51 const T &message() const {
52 return *flatbuffers::GetRoot<T>(reinterpret_cast<const void *>(data()));
53 }
54 // Returns a mutable message. It can be mutated via the flatbuffer rules.
55 T *mutable_message() {
56 return flatbuffers::GetMutableRoot<T>(reinterpret_cast<void *>(data()));
57 }
58
59 virtual const uint8_t *data() const = 0;
60 virtual uint8_t *data() = 0;
61 virtual size_t size() const = 0;
62};
63
64// Array backed flatbuffer.
65template <typename T>
66class FlatbufferArray : public Flatbuffer<T> {
67 public:
68 // Builds a Flatbuffer by copying the data from the other flatbuffer.
69 FlatbufferArray(const Flatbuffer<T> &other) {
70 CHECK_LE(other.size(), data_.size());
71
72 memcpy(data_.data(), other.data(), other.size());
73 size_ = other.size();
74 }
75
76 // Coppies the data from the other flatbuffer.
77 FlatbufferArray &operator=(const Flatbuffer<T> &other) {
78 CHECK_LE(other.size(), data_.size());
79
80 memcpy(data_.data(), other.data(), other.size());
81 size_ = other.size();
82 return *this;
83 }
84
85 // Creates a builder wrapping the underlying data.
86 flatbuffers::FlatBufferBuilder FlatBufferBuilder() {
87 data_.deallocate(data_.data(), data_.size());
88 flatbuffers::FlatBufferBuilder fbb(data_.size(), &data_);
89 fbb.ForceDefaults(1);
90 return fbb;
91 }
92
93 const uint8_t *data() const override { return data_.data(); }
94 uint8_t *data() override { return data_.data(); }
95 size_t size() const override { return size_; }
96
97 private:
98 FixedAllocator<8 * 1024> data_;
99 size_t size_ = data_.size();
100};
Austin Schuhe93d8642019-10-13 15:27:07 -0700101
102// This object associates the message type with the memory storing the
103// flatbuffer. This only stores root tables.
104//
105// From a usage point of view, pointers to the data are very different than
106// pointers to the tables.
107template <typename T>
Austin Schuh40485ed2019-10-26 21:51:44 -0700108class FlatbufferDetachedBuffer : public Flatbuffer<T> {
Austin Schuhe93d8642019-10-13 15:27:07 -0700109 public:
110 // Builds a Flatbuffer by taking ownership of the buffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700111 FlatbufferDetachedBuffer(flatbuffers::DetachedBuffer &&buffer)
Austin Schuhe93d8642019-10-13 15:27:07 -0700112 : buffer_(::std::move(buffer)) {}
113
114 // Builds a flatbuffer by taking ownership of the buffer from the other
115 // flatbuffer.
Austin Schuh40485ed2019-10-26 21:51:44 -0700116 FlatbufferDetachedBuffer(FlatbufferDetachedBuffer &&fb)
117 : buffer_(::std::move(fb.buffer_)) {}
118 FlatbufferDetachedBuffer &operator=(FlatbufferDetachedBuffer &&fb) {
Austin Schuhe93d8642019-10-13 15:27:07 -0700119 ::std::swap(buffer_, fb.buffer_);
120 return *this;
121 }
122
123 // Constructs an empty flatbuffer of type T.
Austin Schuh40485ed2019-10-26 21:51:44 -0700124 static FlatbufferDetachedBuffer<T> Empty() {
Austin Schuhe93d8642019-10-13 15:27:07 -0700125 flatbuffers::FlatBufferBuilder fbb;
126 fbb.ForceDefaults(1);
127 const auto end = fbb.EndTable(fbb.StartTable());
128 fbb.Finish(flatbuffers::Offset<flatbuffers::Table>(end));
Austin Schuh40485ed2019-10-26 21:51:44 -0700129 return FlatbufferDetachedBuffer<T>(fbb.Release());
Austin Schuhe93d8642019-10-13 15:27:07 -0700130 }
131
132 // Returns references to the buffer, and the data.
133 const flatbuffers::DetachedBuffer &buffer() const { return buffer_; }
Austin Schuh40485ed2019-10-26 21:51:44 -0700134 const uint8_t *data() const override { return buffer_.data(); }
135 uint8_t *data() override { return buffer_.data(); }
136 size_t size() const override { return buffer_.size(); }
Austin Schuhe93d8642019-10-13 15:27:07 -0700137
138 private:
139 flatbuffers::DetachedBuffer buffer_;
140};
141
Austin Schuhe93d8642019-10-13 15:27:07 -0700142// TODO(austin): Need a way to get our hands on the max size. Can start with
143// "large" for now.
144
145} // namespace aos
146
147#endif // AOS_FLATBUFFERS_H_