Adding stack allocated protobuf arena class.

Change-Id: I1ee15b79fdb54b787b94b3d424e4df36c82ad849
diff --git a/aos/protobuf/stack_arena.h b/aos/protobuf/stack_arena.h
new file mode 100644
index 0000000..28c933c
--- /dev/null
+++ b/aos/protobuf/stack_arena.h
@@ -0,0 +1,52 @@
+#ifndef AOS_PROTOBUF_STACK_ARENA_H_
+#define AOS_PROTOBUF_STACK_ARENA_H_
+#include "google/protobuf/arena.h"
+
+namespace aos {
+namespace protobuf {
+
+void* FatalArenaBlockAlloc(size_t);
+
+void FatalArenaBlockDealloc(void*, size_t);
+
+// This class manages a protobuf arena which uses an internal buffer
+// (allocated as part of the object) of size buffer_size.
+//
+// Protos allocated from this arena must not use more than buffer_size
+// worth of data.
+//
+// Also worth noting is that sizeof(google::protobuf::Arena::Block)
+// is used up out of the buffer for internal protobuf related usage, so
+// overallocate accordingly.
+template <size_t buffer_size>
+class StackProtoArena {
+ public:
+  StackProtoArena() :
+      arena_(GetArenaOptions(&data_[0])) {}
+
+  google::protobuf::Arena* arena() { return &arena_; }
+
+  // For convienence:
+  template <typename T>
+  T* CreateMessage() {
+    return google::protobuf::Arena::CreateMessage<T>(&arena_);
+  }
+ private:
+  static google::protobuf::ArenaOptions GetArenaOptions(char* data) {
+    // Expecting RVO to kick in.
+    google::protobuf::ArenaOptions options;
+    options.initial_block = data;
+    options.initial_block_size = buffer_size;
+    options.block_alloc = &FatalArenaBlockAlloc;
+    options.block_dealloc = FatalArenaBlockDealloc;
+    return options;
+  }
+
+  char data_[buffer_size];
+  google::protobuf::Arena arena_;
+};
+
+}  // namespace protobuf
+}  // namespace aos
+
+#endif  // AOS_PROTOBUF_STACK_ARENA_H_