Provide absl::InlinedVector specialization for N=0

Create an AOS version of the abseil InlinedVector that allows for N=0.

This provides a type that we can use to use stack-allocated memory for
the first N elements in a vector and then dynamically allocate all
subsequent memory.

Change-Id: Ia6d22a64deba1a841b188291bf79d2758ee94e99
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/containers/BUILD b/aos/containers/BUILD
index ee1bf98..c0b365c 100644
--- a/aos/containers/BUILD
+++ b/aos/containers/BUILD
@@ -42,6 +42,29 @@
 )
 
 cc_library(
+    name = "inlined_vector",
+    hdrs = [
+        "inlined_vector.h",
+    ],
+    deps = [
+        "@com_google_absl//absl/container:inlined_vector",
+    ],
+)
+
+cc_test(
+    name = "inlined_vector_test",
+    srcs = [
+        "inlined_vector_test.cc",
+    ],
+    target_compatible_with = ["@platforms//os:linux"],
+    deps = [
+        ":inlined_vector",
+        "//aos:realtime",
+        "//aos/testing:googletest",
+    ],
+)
+
+cc_library(
     name = "sized_array",
     hdrs = [
         "sized_array.h",
diff --git a/aos/containers/inlined_vector.h b/aos/containers/inlined_vector.h
new file mode 100644
index 0000000..abd375d
--- /dev/null
+++ b/aos/containers/inlined_vector.h
@@ -0,0 +1,18 @@
+#ifndef AOS_CONTAINERS_INLINED_VECTOR_H_
+#define AOS_CONTAINERS_INLINED_VECTOR_H_
+
+#include <vector>
+
+#include "absl/container/inlined_vector.h"
+
+namespace aos {
+
+template <typename T, size_t N>
+struct InlinedVector : public absl::InlinedVector<T, N> {};
+
+// Specialized for the N == 0 case because absl::InlinedVector doesn't support
+// it for some reason.
+template <typename T>
+struct InlinedVector<T, 0> : public std::vector<T> {};
+}  // namespace aos
+#endif  // AOS_CONTAINERS_INLINED_VECTOR_H_
diff --git a/aos/containers/inlined_vector_test.cc b/aos/containers/inlined_vector_test.cc
new file mode 100644
index 0000000..23266e9
--- /dev/null
+++ b/aos/containers/inlined_vector_test.cc
@@ -0,0 +1,46 @@
+#include "aos/containers/inlined_vector.h"
+
+#include "gtest/gtest.h"
+
+#include "aos/realtime.h"
+
+DECLARE_bool(die_on_malloc);
+
+namespace aos {
+namespace testing {
+
+// Checks that we don't malloc until/unless we need to increase the size of the
+// vector.
+TEST(SizedArrayTest, NoUnnecessaryMalloc) {
+  gflags::FlagSaver flag_saver;
+  FLAGS_die_on_malloc = true;
+  RegisterMallocHook();
+  InlinedVector<int, 5> a;
+  {
+    aos::ScopedRealtime realtime;
+    a.push_back(9);
+    a.push_back(7);
+    a.push_back(1);
+    a.push_back(2);
+    a.push_back(3);
+
+    // And double-check that we can actually construct a new object at realtime.
+    InlinedVector<int, 5> b;
+  }
+  EXPECT_DEATH(
+      {
+        aos::ScopedRealtime realtime;
+        a.push_back(4);
+      },
+      "Malloced");
+}
+
+// Tests that we can create/define a vector with zero statically allocated
+// elements (the absl::InlinedVector does not allow this for some reason).
+TEST(SizedArrayTest, ZeroLengthVector) {
+  InlinedVector<int, 0> zero;
+  zero.push_back(1);
+  ASSERT_EQ(1, zero[0]);
+}
+}  // namespace testing
+}  // namespace aos