made RawQueue options type-safe
diff --git a/aos/common/util/options.h b/aos/common/util/options.h
new file mode 100644
index 0000000..48c4fd8
--- /dev/null
+++ b/aos/common/util/options.h
@@ -0,0 +1,92 @@
+#ifndef AOS_COMMON_UTIL_OPTIONS_H_
+#define AOS_COMMON_UTIL_OPTIONS_H_
+
+#include <sys/types.h>
+
+namespace aos {
+
+template <class Owner>
+class Options;
+
+// An "option" that can be combined with other options and passed as one
+// argument. This class is designed to emulate integral constants (except be
+// type-safe), so its instances can be combined with operator| (creating an
+// Options), and an Options can be tested for membership with operator&.
+// Owner is the only class that can construct Option instances and is used to
+// differentiate between options for different classes. It is safe to only have
+// a forward declaration for Owner in scope when instantiating either of these
+// template classes.
+template <class Owner>
+class Options {
+ public:
+  // Represents a single options. Instances of this should be created as
+  // constants by Owner.
+  class Option {
+   public:
+    constexpr Options operator|(Option option) const {
+      return Options(bit_ | option.bit_);
+    }
+
+    constexpr bool operator==(Option other) const { return bit_ == other.bit_; }
+
+    constexpr unsigned int printable() const { return bit_; }
+
+   private:
+    // Bit must have exactly 1 bit set and that must be a different one for each
+    // instance.
+    explicit constexpr Option(unsigned int bit) : bit_(bit) {}
+
+    unsigned int bit_;
+
+    friend class Options;
+    friend Owner;
+  };
+
+  constexpr Options(Option option) : bits_(option.bit_) {}
+
+  constexpr bool operator&(Option option) const {
+    return (bits_ & option.bit_) != 0;
+  }
+
+  constexpr Options operator|(Option option) const {
+    return Options(bits_ | option.bit_);
+  }
+  constexpr Options operator|(Options options) const {
+    return Options(bits_ | options.bits_);
+  }
+
+  constexpr bool operator==(Options other) const {
+    return bits_ == other.bits_;
+  }
+
+  constexpr unsigned int printable() const { return bits_; }
+
+  // Returns true if no Options other than the ones in options are set.
+  // Useful for validating that no illegal options are passed.
+  constexpr bool NoOthersSet(Options options) const {
+    return (bits_ & ~options.bits_) == 0;
+  }
+
+  // Returns true if exactly 1 of the Options in options is set.
+  // Useful for validating that one of a group of mutually exclusive options has
+  // been passed.
+  constexpr bool ExactlyOneSet(Options options) const {
+    return __builtin_popcount(bits_ & options.bits_) == 1;
+  }
+
+  // Returns true if all of the Options in options are set.
+  constexpr bool AllSet(Options options) const {
+    return (bits_ & options.bits_) == options.bits_;
+  }
+
+ private:
+  explicit constexpr Options(unsigned int bits) : bits_(bits) {}
+
+  unsigned int bits_;
+
+  friend class Option;
+};
+
+}  // namespace options
+
+#endif  // AOS_COMMON_UTIL_OPTIONS_H_
diff --git a/aos/common/util/options_test.cc b/aos/common/util/options_test.cc
new file mode 100644
index 0000000..197340c
--- /dev/null
+++ b/aos/common/util/options_test.cc
@@ -0,0 +1,56 @@
+#include "aos/common/util/options.h"
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace testing {
+
+class OptionsTest : public ::testing::Test {
+ public:
+  static constexpr Options<OptionsTest>::Option kOne{1}, kTwo{2}, kThree{4},
+      kFour{8};
+};
+
+constexpr Options<OptionsTest>::Option OptionsTest::kOne, OptionsTest::kTwo,
+    OptionsTest::kThree, OptionsTest::kFour;
+
+TEST_F(OptionsTest, Basic) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three & kOne);
+  EXPECT_FALSE(one_three & kTwo);
+  EXPECT_TRUE(one_three & kThree);
+}
+
+TEST_F(OptionsTest, NoOthersSet) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three.NoOthersSet(one_three));
+  EXPECT_TRUE(one_three.NoOthersSet(kOne | kTwo | kThree));
+  EXPECT_TRUE(one_three.NoOthersSet(kOne | kThree | kFour));
+  EXPECT_TRUE(one_three.NoOthersSet(kOne | kTwo | kThree | kFour));
+  EXPECT_FALSE(one_three.NoOthersSet(kOne));
+  EXPECT_FALSE(one_three.NoOthersSet(kThree));
+  EXPECT_FALSE(one_three.NoOthersSet(kTwo | kFour));
+}
+
+TEST_F(OptionsTest, ExactlyOneSet) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three.ExactlyOneSet(kOne | kTwo));
+  EXPECT_FALSE(one_three.ExactlyOneSet(one_three));
+  EXPECT_TRUE(one_three.ExactlyOneSet(kTwo | kThree | kFour));
+  EXPECT_FALSE(one_three.ExactlyOneSet(kOne | kTwo | kThree | kFour));
+}
+
+TEST_F(OptionsTest, AllSet) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three.AllSet(one_three));
+  EXPECT_TRUE(one_three.AllSet(kOne));
+  EXPECT_FALSE(one_three.AllSet(kTwo));
+  EXPECT_TRUE(one_three.AllSet(kThree));
+  EXPECT_FALSE(one_three.AllSet(kFour));
+  EXPECT_FALSE(one_three.AllSet(kOne | kTwo | kFour));
+  EXPECT_FALSE(one_three.AllSet(kTwo | kThree | kFour));
+  EXPECT_FALSE(one_three.AllSet(kOne | kTwo | kThree | kFour));
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/util/util.gyp b/aos/common/util/util.gyp
index fb29d7f..fa1fb7f 100644
--- a/aos/common/util/util.gyp
+++ b/aos/common/util/util.gyp
@@ -127,5 +127,15 @@
         '<(EXTERNALS):gtest',
       ],
     },
+    {
+      'target_name': 'options_test',
+      'type': 'executable',
+      'sources': [
+        'options_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+      ],
+    },
   ],
 }