buffet: add C++ variant type (Any).

Any is the class that adds support for native variant types.

Any can store any C++ type which is copyable. Moveable-only
types (such as std::unique_ptr) cannot be stored directly,
however you can store pointers (or references) to such types.

Any stores small data embedded into the class itself without
having to allocate a separate storage for it. Larger data
(roughly, larger than 8 bytes) or non trivially-copyable types
are stored in a separate memory block and the pointer to that
block is stored in the Any class itself.

Any supports move semantics. You can move the stored value
from one Any into another without copying it.

At this point, there is no support for comparing the Any class
(equal or less than), so you cannot use it as a key in a map,
however you still can store it as a value.

The code that extracts the data from Any must know the exact
type stored. Calling Any::Get<T>() for incompatible type is
not supported. However you can use Any::TryGet<T>() instead
and provide a default value, which will be returned if Any
does not contain the expected data.

You can also inspect the type of the contained data by
using Any::GetType() and Any::IsTypeCompatible<T>() methods.

BUG=chromium:366709
TEST=All existing and new unit tests pass.

Change-Id: Ic47529935ddd39c792dff1db8667c76db91b16d4
Reviewed-on: https://chromium-review.googlesource.com/198590
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/any.cc b/buffet/any.cc
new file mode 100644
index 0000000..9ce0ce2
--- /dev/null
+++ b/buffet/any.cc
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "buffet/any.h"
+
+#include <algorithm>
+
+namespace buffet {
+
+Any::Any(const Any& rhs) : data_buffer_(rhs.data_buffer_) {
+}
+
+Any::~Any() {
+}
+
+Any& Any::operator=(const Any& rhs) {
+  data_buffer_ = rhs.data_buffer_;
+  return *this;
+}
+
+const std::type_info& Any::GetType() const {
+  if (!IsEmpty())
+    return data_buffer_.GetDataPtr()->GetType();
+
+  struct NullType {};  // Special helper type representing an empty variant.
+  return typeid(NullType);
+}
+
+void Any::Swap(Any& other) {
+  std::swap(data_buffer_, other.data_buffer_);
+}
+
+bool Any::IsEmpty() const {
+  return data_buffer_.IsEmpty();
+}
+
+void Any::Clear() {
+  data_buffer_.Clear();
+}
+
+bool Any::IsConvertibleToInteger() const {
+  return !IsEmpty() && data_buffer_.GetDataPtr()->IsConvertibleToInteger();
+}
+
+intmax_t Any::GetAsInteger() const {
+  CHECK(!IsEmpty()) << "Must not be called on an empty Any";
+  return data_buffer_.GetDataPtr()->GetAsInteger();
+}
+
+}  // namespace buffet
diff --git a/buffet/any.h b/buffet/any.h
new file mode 100644
index 0000000..5ab249c
--- /dev/null
+++ b/buffet/any.h
@@ -0,0 +1,174 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is an implementation of a "true" variant class in C++.
+// The buffet::Any class can hold any C++ type, but both the setter and
+// getter sites need to know the actual type of data.
+// Note that C-style arrays when stored in Any are reduced to simple
+// data pointers. Any will not copy a contents of the array.
+//    const int data[] = [1,2,3];
+//    Any v(data);  // stores const int*, effectively "Any v(&data[0]);"
+
+// buffet::Any is a value type. Which means, the data is copied into it
+// and Any owns it. The owned object (stored by value) will be destroyed
+// when Any is cleared or reassigned. The contained value type must be
+// copy-constructible. You can also store pointers and references to objects.
+// Storing pointers is trivial. In order to store a reference, you can
+// use helper functions std::ref() and std::cref() to create non-const and
+// const references respectively. In such a case, the type of contained data
+// will be std::reference_wrapper<T>. See 'References' unit tests in
+// any_unittest.cc for examples.
+
+#ifndef BUFFET_ANY_H_
+#define BUFFET_ANY_H_
+
+#include "buffet/any_internal_impl.h"
+
+#include <algorithm>
+
+namespace buffet {
+
+class Any final {
+ public:
+  Any() = default;
+  // Standard copy constructor. This is a value-class container
+  // that must be copy-constructible and movable. The copy constructors
+  // should not be marked as explicit.
+  Any(const Any& rhs);
+  // Typed constructor that stores a value of type T in the Any.
+  template<class T>
+  Any(T value) {        // NOLINT(runtime/explicit)
+    data_buffer_.Assign(std::move(value));
+  }
+
+  // Not declaring the destructor as virtual since this is a sealed class
+  // and there is no need to introduce a virtual table to it.
+  ~Any();
+
+  // Assignment operators.
+  Any& operator=(const Any& rhs);
+  template<class T>
+  Any& operator=(T value) {
+    data_buffer_.Assign(std::move(value));
+    return *this;
+  }
+
+  // Checks if the given type DestType can be obtained from the Any.
+  // For example, to check if Any has a 'double' value in it:
+  //  any.IsTypeCompatible<double>()
+  template<typename DestType>
+  bool IsTypeCompatible() const {
+    // Make sure the requested type DestType conforms to the storage
+    // requirements of Any. We always store the data by value, which means we
+    // strip away any references as well as cv-qualifiers. So, if the user
+    // stores "const int&", we actually store just an "int".
+    // When calling IsTypeCompatible, we need to do a similar "type cleansing"
+    // to make sure the requested type matches the type of data actually stored,
+    // so this "canonical" type is used for type checking below.
+    using CanonicalDestType = typename std::decay<DestType>::type;
+    const std::type_info& ContainedTypeId = GetType();
+    if (typeid(CanonicalDestType) == ContainedTypeId)
+      return true;
+
+    if (!std::is_pointer<CanonicalDestType>::value)
+      return false;
+
+    // If asking for a const pointer from a variant containing non-const
+    // pointer, still satisfy the request. So, we need to remove the pointer
+    // specification first, then strip the const/volatile qualifiers, then
+    // re-add the pointer back, so "const int*" would become "int*".
+    using NonPointer = typename std::remove_pointer<CanonicalDestType>::type;
+    using CanonicalDestTypeNoConst = typename std::add_pointer<
+        typename std::remove_const<NonPointer>::type>::type;
+    using CanonicalDestTypeNoVolatile = typename std::add_pointer<
+        typename std::remove_volatile<NonPointer>::type>::type;
+    using CanonicalDestTypeNoConstOrVolatile = typename std::add_pointer<
+        typename std::remove_cv<NonPointer>::type>::type;
+
+    return typeid(CanonicalDestTypeNoConst) == ContainedTypeId ||
+           typeid(CanonicalDestTypeNoVolatile) == ContainedTypeId ||
+           typeid(CanonicalDestTypeNoConstOrVolatile) == ContainedTypeId;
+  }
+
+  // Returns immutable data contained in Any.
+  // Aborts if Any doesn't contain a value of type T, or trivially
+  // convertible to/compatible with it.
+  template<typename T>
+  const T& Get() const {
+    CHECK(IsTypeCompatible<T>()) << "Requesting value of type "
+                                 << typeid(T).name()
+                                 << " from variant containing "
+                                 << GetType().name();
+    return data_buffer_.GetData<T>();
+  }
+
+  // Returns a pointer to mutable value of type T contained within Any.
+  // No data copying is made, the data pointed to is still owned by Any.
+  // If Any doesn't contain a value of type T, or trivially
+  // convertible/compatible to/with it, then it returns nullptr.
+  template<typename T>
+  T* GetPtr() {
+    if (!IsTypeCompatible<T>())
+      return nullptr;
+    return &(data_buffer_.GetData<T>());
+  }
+
+  // Returns immutable data contained in Any.
+  // If the Any doesn't contain a compatible value, the provided default
+  // |def_val| is returned instead.
+  template<typename T>
+  const T& TryGet(typename std::decay<T>::type const& def_val) const {
+    if (!IsTypeCompatible<T>())
+      return def_val;
+    return data_buffer_.GetData<T>();
+  }
+
+  // A convenience specialization of the above function where the default
+  // value of type T is returned in case the underlying Get() fails.
+  template<typename T>
+  const T& TryGet() const {
+    return TryGet<T>(typename std::decay<T>::type());
+  }
+
+
+  // Returns the type information about the contained data. For most cases,
+  // instead of using this function, you should be calling IsTypeCompatible<>().
+  const std::type_info& GetType() const;
+  // Swaps the value of this object with that of |other|.
+  void Swap(Any& other);
+  // Checks if Any is empty, that is, not containing a value of any type.
+  bool IsEmpty() const;
+  // Clears the Any and destroys any contained object. Makes it empty.
+  void Clear();
+  // Checks if Any contains a type convertible to integer.
+  // Any type that match std::is_integral<T> and std::is_enum<T> is accepted.
+  // That includes signed and unsigned char, short, int, long, etc as well as
+  // 'bool' and enumerated types.
+  // For 'integer' type, you can call GetAsInteger to do implicit type
+  // conversion to intmax_t.
+  bool IsConvertibleToInteger() const;
+  // For integral types and enums contained in the Any, get the integer value
+  // of data. This is a useful function to obtain an integer value when
+  // any can possibly have unspecified integer, such as 'short', 'unsigned long'
+  // and so on.
+  intmax_t GetAsInteger() const;
+
+ private:
+  // The data buffer for contained object.
+  internal_details::Buffer data_buffer_;
+};
+
+}  // namespace buffet
+
+namespace std {
+
+// Specialize std::swap() algorithm for buffet::Any class.
+inline void swap(buffet::Any& lhs, buffet::Any& rhs) {
+  lhs.Swap(rhs);
+}
+
+}  // namespace std
+
+#endif  // BUFFET_ANY_H_
+
diff --git a/buffet/any_internal_impl.h b/buffet/any_internal_impl.h
new file mode 100644
index 0000000..cbf0bb8
--- /dev/null
+++ b/buffet/any_internal_impl.h
@@ -0,0 +1,215 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Internal implementation of buffet::Any class.
+
+#ifndef BUFFET_ANY_INTERNAL_IMPL_H_
+#define BUFFET_ANY_INTERNAL_IMPL_H_
+
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+#include <base/logging.h>
+
+namespace buffet {
+
+namespace internal_details {
+
+// An extension to std::is_convertible to allow conversion from an enum to
+// an integral type which std::is_convertible does not indicate as supported.
+template <typename From, typename To>
+struct IsConvertible : public std::integral_constant<bool,
+    std::is_convertible<From, To>::value ||
+    (std::is_enum<From>::value && std::is_integral<To>::value)> {
+};
+// TryConvert is a helper function that does a safe compile-time conditional
+// type cast between data types that may not be always convertible.
+// From and To are the source and destination types.
+// The function returns true if conversion was possible/successful.
+template <typename From, typename To>
+inline typename std::enable_if<IsConvertible<From, To>::value, bool>::type
+TryConvert(const From& in, To* out) {
+  *out = static_cast<To>(in);
+  return true;
+}
+template <typename From, typename To>
+inline typename std::enable_if<!IsConvertible<From, To>::value, bool>::type
+TryConvert(const From& in, To* out) {
+  return false;
+}
+
+struct Buffer;  // Forward declaration of data buffer container.
+
+// Abstract base class for contained variant data.
+struct Data {
+  virtual ~Data() {}
+  // Returns the type information for the contained data.
+  virtual const std::type_info& GetType() const = 0;
+  // Copies the contained data to the output |buffer|.
+  virtual void CopyTo(Buffer* buffer) const = 0;
+  // Checks if the contained data is an integer type (not necessarily an 'int').
+  virtual bool IsConvertibleToInteger() const = 0;
+  // Gets the contained integral value as an integer.
+  virtual intmax_t GetAsInteger() const = 0;
+};
+
+// Concrete implementation of variant data of type T.
+template<typename T>
+struct TypedData : public Data {
+  explicit TypedData(const T& value) : value_(value) {}
+
+  virtual const std::type_info& GetType() const override { return typeid(T); }
+  virtual void CopyTo(Buffer* buffer) const override;
+  virtual bool IsConvertibleToInteger() const override {
+    return std::is_integral<T>::value || std::is_enum<T>::value;
+  }
+  virtual intmax_t GetAsInteger() const override {
+    intmax_t int_val = 0;
+    bool converted = TryConvert(value_, &int_val);
+    CHECK(converted) << "Unable to convert value of type " << typeid(T).name()
+                     << " to integer";
+    return int_val;
+  }
+  // Special method to copy data of the same type
+  // without reallocating the buffer.
+  void FastAssign(const T& source) { value_ = source; }
+
+  T value_;
+};
+
+// Buffer class that stores the contained variant data.
+// To improve performance and reduce memory fragmentation, small variants
+// are stored in pre-allocated memory buffers that are part of the Any class.
+// If the memory requirements are larger than the set limit or the type is
+// non-trivially copyable, then the contained class is allocated in a separate
+// memory block and the pointer to that memory is contained within this memory
+// buffer class.
+class Buffer {
+ public:
+  enum StorageType { kExternal, kContained };
+  Buffer() : external_ptr_(nullptr), storage_(kExternal) {}
+  ~Buffer() {
+    Clear();
+  }
+
+  Buffer(const Buffer& rhs) : Buffer() {
+    rhs.CopyTo(this);
+  }
+  Buffer& operator=(const Buffer& rhs) {
+    rhs.CopyTo(this);
+    return *this;
+  }
+
+  // Returns the underlying pointer to contained data. Uses either the pointer
+  // or the raw data depending on |storage_| type.
+  inline Data* GetDataPtr() {
+    return (storage_ == kExternal) ?
+        external_ptr_ : reinterpret_cast<Data*>(contained_buffer_);
+  }
+  inline const Data* GetDataPtr() const {
+    return (storage_ == kExternal) ?
+        external_ptr_ : reinterpret_cast<const Data*>(contained_buffer_);
+  }
+
+  // Destroys the contained object (and frees memory if needed).
+  void Clear() {
+    Data* data = GetDataPtr();
+    if (storage_ == kExternal) {
+      delete data;
+    } else {
+      // Call the destructor manually, since the object was constructed inline
+      // in the pre-allocated buffer. We still need to call the destructor
+      // to free any associated resources, but we can't call delete |data| here.
+      data->~Data();
+    }
+    external_ptr_ = nullptr;
+    storage_ = kExternal;
+  }
+
+  // Stores a value of type T.
+  template<typename T>
+  void Assign(T value) {
+    using Type = typename std::decay<T>::type;
+    using DataType = TypedData<Type>;
+    Data* ptr = GetDataPtr();
+    if (ptr && ptr->GetType() == typeid(Type)) {
+      // We assign the data to the variant container, which already
+      // has the data of the same type. Do fast copy with no memory
+      // reallocation.
+      DataType* typed_ptr = static_cast<DataType*>(ptr);
+      typed_ptr->FastAssign(value);
+    } else {
+      Clear();
+      // TODO(avakulenko): [see crbug.com/379833]
+      // Unfortunately, GCC doesn't support std::is_trivially_copyable<T> yet,
+      // so using std::is_trivial instead, which is a bit more restrictive.
+      // Once GCC has support for is_trivially_copyable, update the following.
+      if (!std::is_trivial<Type>::value ||
+          sizeof(DataType) > sizeof(contained_buffer_)) {
+        // If it is too big or not trivially copyable, allocate it separately.
+        external_ptr_ = new DataType(value);
+        storage_ = kExternal;
+      } else {
+        // Otherwise just use the pre-allocated buffer.
+        DataType* address = reinterpret_cast<DataType*>(contained_buffer_);
+        // Make sure we still call the copy constructor.
+        // Call the constructor manually by using placement 'new'.
+        new (address) DataType(value);
+        storage_ = kContained;
+      }
+    }
+  }
+
+  // Helper methods to retrieve a reference to contained data.
+  // These assume that type checking has already been performed by Any
+  // so the type cast is valid and will succeed.
+  template<typename T>
+  const T& GetData() const {
+    using DataType = internal_details::TypedData<typename std::decay<T>::type>;
+    return static_cast<const DataType*>(GetDataPtr())->value_;
+  }
+  template<typename T>
+  T& GetData() {
+    using DataType = internal_details::TypedData<typename std::decay<T>::type>;
+    return static_cast<DataType*>(GetDataPtr())->value_;
+  }
+
+  // Returns true if the buffer has no contained data.
+  bool IsEmpty() const {
+    return (storage_ == kExternal && external_ptr_ == nullptr);
+  }
+
+  // Copies the data from the current buffer into the |destination|.
+  void CopyTo(Buffer* destination) const {
+    if (IsEmpty()) {
+      destination->Clear();
+    } else {
+      GetDataPtr()->CopyTo(destination);
+    }
+  }
+
+  union {
+    // |external_ptr_| is a pointer to a larger object allocated in
+    // a separate memory block.
+    Data* external_ptr_;
+    // |contained_buffer_| is a pre-allocated buffer for smaller/simple objects.
+    // Pre-allocate enough memory to store objects as big as "double".
+    unsigned char contained_buffer_[sizeof(TypedData<double>)];
+  };
+  // Depending on a value of |storage_|, either |external_ptr_| or
+  // |contained_buffer_| above is used to get a pointer to memory containing
+  // the variant data.
+  StorageType storage_;  // Declare after the union to eliminate member padding.
+};
+
+template<typename T>
+void TypedData<T>::CopyTo(Buffer* buffer) const { buffer->Assign(value_); }
+
+}  // namespace internal_details
+
+}  // namespace buffet
+
+#endif  // BUFFET_ANY_INTERNAL_IMPL_H_
+
diff --git a/buffet/any_internal_impl_unittest.cc b/buffet/any_internal_impl_unittest.cc
new file mode 100644
index 0000000..fbc56fc
--- /dev/null
+++ b/buffet/any_internal_impl_unittest.cc
@@ -0,0 +1,114 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "buffet/any.h"
+
+using buffet::internal_details::Buffer;
+
+TEST(Buffer, Empty) {
+  Buffer buffer;
+  EXPECT_TRUE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kExternal, buffer.storage_);
+  EXPECT_EQ(nullptr, buffer.GetDataPtr());
+}
+
+TEST(Buffer, Store_Int) {
+  Buffer buffer;
+  buffer.Assign(2);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kContained, buffer.storage_);
+  EXPECT_EQ(typeid(int), buffer.GetDataPtr()->GetType());
+}
+
+TEST(Buffer, Store_Double) {
+  Buffer buffer;
+  buffer.Assign(2.3);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kContained, buffer.storage_);
+  EXPECT_EQ(typeid(double), buffer.GetDataPtr()->GetType());
+}
+
+TEST(Buffer, Store_Pointers) {
+  Buffer buffer;
+  // nullptr
+  buffer.Assign(nullptr);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kContained, buffer.storage_);
+  EXPECT_EQ(typeid(nullptr_t), buffer.GetDataPtr()->GetType());
+
+  // char *
+  buffer.Assign("abcd");
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kContained, buffer.storage_);
+  EXPECT_EQ(typeid(const char*), buffer.GetDataPtr()->GetType());
+
+  // pointer to non-trivial object
+  class NonTrivial {
+   public:
+    virtual ~NonTrivial() {}
+  } non_trivial;
+  buffer.Assign(&non_trivial);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kContained, buffer.storage_);
+  EXPECT_EQ(typeid(NonTrivial*), buffer.GetDataPtr()->GetType());
+}
+
+TEST(Buffer, Store_NonTrivialObjects) {
+  class NonTrivial {
+   public:
+    virtual ~NonTrivial() {}
+  } non_trivial;
+  Buffer buffer;
+  buffer.Assign(non_trivial);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kExternal, buffer.storage_);
+  EXPECT_EQ(typeid(NonTrivial), buffer.GetDataPtr()->GetType());
+}
+
+TEST(Buffer, Store_Objects) {
+  Buffer buffer;
+
+  struct Small {
+    double d;
+  } small = {};
+  buffer.Assign(small);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kContained, buffer.storage_);
+  EXPECT_EQ(typeid(Small), buffer.GetDataPtr()->GetType());
+
+  struct Large {
+    char c[10];
+  } large = {};
+  buffer.Assign(large);
+  EXPECT_FALSE(buffer.IsEmpty());
+  EXPECT_EQ(Buffer::kExternal, buffer.storage_);
+  EXPECT_EQ(typeid(Large), buffer.GetDataPtr()->GetType());
+}
+
+TEST(Buffer, Copy) {
+  Buffer buffer1;
+  Buffer buffer2;
+
+  buffer1.Assign(30);
+  buffer1.CopyTo(&buffer2);
+  EXPECT_FALSE(buffer1.IsEmpty());
+  EXPECT_FALSE(buffer2.IsEmpty());
+  EXPECT_EQ(typeid(int), buffer1.GetDataPtr()->GetType());
+  EXPECT_EQ(typeid(int), buffer2.GetDataPtr()->GetType());
+  EXPECT_EQ(30, buffer1.GetData<int>());
+  EXPECT_EQ(30, buffer2.GetData<int>());
+
+  buffer1.Assign(std::string("abc"));
+  buffer1.CopyTo(&buffer2);
+  EXPECT_FALSE(buffer1.IsEmpty());
+  EXPECT_FALSE(buffer2.IsEmpty());
+  EXPECT_EQ(typeid(std::string), buffer1.GetDataPtr()->GetType());
+  EXPECT_EQ(typeid(std::string), buffer2.GetDataPtr()->GetType());
+  EXPECT_EQ("abc", buffer1.GetData<std::string>());
+  EXPECT_EQ("abc", buffer2.GetData<std::string>());
+}
diff --git a/buffet/any_unittest.cc b/buffet/any_unittest.cc
new file mode 100644
index 0000000..48df826
--- /dev/null
+++ b/buffet/any_unittest.cc
@@ -0,0 +1,245 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "buffet/any.h"
+
+using buffet::Any;
+
+TEST(Any, Empty) {
+  Any val;
+  EXPECT_TRUE(val.IsEmpty());
+
+  Any val2 = val;
+  EXPECT_TRUE(val.IsEmpty());
+  EXPECT_TRUE(val2.IsEmpty());
+}
+
+TEST(Any, SimpleTypes) {
+  Any val(20);
+  EXPECT_FALSE(val.IsEmpty());
+  EXPECT_TRUE(val.IsTypeCompatible<int>());
+  EXPECT_EQ(20, val.Get<int>());
+
+  Any val2(3.1415926);
+  EXPECT_FALSE(val2.IsEmpty());
+  EXPECT_TRUE(val2.IsTypeCompatible<double>());
+  EXPECT_FALSE(val2.IsTypeCompatible<int>());
+  EXPECT_DOUBLE_EQ(3.1415926, val2.Get<double>());
+
+  Any val3(std::string("blah"));
+  EXPECT_TRUE(val3.IsTypeCompatible<std::string>());
+  EXPECT_EQ("blah", val3.Get<std::string>());
+}
+
+TEST(Any, Clear) {
+  Any val('x');
+  EXPECT_FALSE(val.IsEmpty());
+  EXPECT_EQ('x', val.Get<char>());
+
+  val.Clear();
+  EXPECT_TRUE(val.IsEmpty());
+}
+
+TEST(Any, Assignments) {
+  Any val(20);
+  EXPECT_EQ(20, val.Get<int>());
+
+  val = 3.1415926;
+  EXPECT_FALSE(val.IsEmpty());
+  EXPECT_TRUE(val.IsTypeCompatible<double>());
+  EXPECT_DOUBLE_EQ(3.1415926, val.Get<double>());
+
+  val = std::string("blah");
+  EXPECT_EQ("blah", val.Get<std::string>());
+
+  Any val2;
+  EXPECT_TRUE(val2.IsEmpty());
+  val2 = val;
+  EXPECT_FALSE(val.IsEmpty());
+  EXPECT_FALSE(val2.IsEmpty());
+  EXPECT_EQ("blah", val.Get<std::string>());
+  EXPECT_EQ("blah", val2.Get<std::string>());
+  val.Clear();
+  EXPECT_TRUE(val.IsEmpty());
+  EXPECT_EQ("blah", val2.Get<std::string>());
+  val2.Clear();
+  EXPECT_TRUE(val2.IsEmpty());
+
+  val = std::vector<int>({100, 20, 3});
+  auto v = val.Get<std::vector<int>>();
+  EXPECT_EQ(100, v[0]);
+  EXPECT_EQ(20, v[1]);
+  EXPECT_EQ(3, v[2]);
+}
+
+TEST(Any, Enums) {
+  enum class Dummy { foo, bar, baz };
+  Any val(Dummy::bar);
+  EXPECT_FALSE(val.IsEmpty());
+  EXPECT_TRUE(val.IsConvertibleToInteger());
+  EXPECT_EQ(Dummy::bar, val.Get<Dummy>());
+  EXPECT_EQ(1, val.GetAsInteger());
+
+  val = Dummy::baz;
+  EXPECT_EQ(2, val.GetAsInteger());
+
+  val = Dummy::foo;
+  EXPECT_EQ(0, val.GetAsInteger());
+}
+
+TEST(Any, Integers) {
+  Any val(14);
+  EXPECT_TRUE(val.IsConvertibleToInteger());
+  EXPECT_EQ(14, val.Get<int>());
+  EXPECT_EQ(14, val.GetAsInteger());
+
+  val = '\x40';
+  EXPECT_TRUE(val.IsConvertibleToInteger());
+  EXPECT_EQ(64, val.Get<char>());
+  EXPECT_EQ(64, val.GetAsInteger());
+
+  val = static_cast<uint16_t>(65535);
+  EXPECT_TRUE(val.IsConvertibleToInteger());
+  EXPECT_EQ(65535, val.Get<uint16_t>());
+  EXPECT_EQ(65535, val.GetAsInteger());
+
+  val = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL);
+  EXPECT_TRUE(val.IsConvertibleToInteger());
+  EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, val.Get<uint64_t>());
+  EXPECT_EQ(-1, val.GetAsInteger());
+
+  val = "abc";
+  EXPECT_FALSE(val.IsConvertibleToInteger());
+
+  int a = 5;
+  val = &a;
+  EXPECT_FALSE(val.IsConvertibleToInteger());
+}
+
+TEST(Any, Pointers) {
+  Any val("abc");  // const char*
+  EXPECT_FALSE(val.IsTypeCompatible<char*>());
+  EXPECT_TRUE(val.IsTypeCompatible<const char*>());
+  EXPECT_FALSE(val.IsTypeCompatible<volatile char*>());
+  EXPECT_TRUE(val.IsTypeCompatible<volatile const char*>());
+  EXPECT_STREQ("abc", val.Get<const char*>());
+
+  int a = 10;
+  val = &a;
+  EXPECT_TRUE(val.IsTypeCompatible<int*>());
+  EXPECT_TRUE(val.IsTypeCompatible<const int*>());
+  EXPECT_TRUE(val.IsTypeCompatible<volatile int*>());
+  EXPECT_TRUE(val.IsTypeCompatible<volatile const int*>());
+  EXPECT_EQ(10, *val.Get<const int*>());
+  *val.Get<int*>() = 3;
+  EXPECT_EQ(3, a);
+}
+
+TEST(Any, Arrays) {
+  // The following test are here to validate the array-to-pointer decay rules.
+  // Since Any does not store the contents of a C-style array, just a pointer
+  // to the data, putting array data into Any could be dangerous.
+  // Make sure the array's lifetime exceeds that of an Any containing the
+  // pointer to the array data.
+  // If you want to store the array with data, use corresponding value types
+  // such as std::vector or a struct containing C-style array as a member.
+
+  int int_array[] = {1, 2, 3};  // int*
+  Any val = int_array;
+  EXPECT_TRUE(val.IsTypeCompatible<int*>());
+  EXPECT_TRUE(val.IsTypeCompatible<const int*>());
+  EXPECT_TRUE(val.IsTypeCompatible<int[]>());
+  EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
+  EXPECT_EQ(3, val.Get<int*>()[2]);
+
+  const int const_int_array[] = {10, 20, 30};  // const int*
+  val = const_int_array;
+  EXPECT_FALSE(val.IsTypeCompatible<int*>());
+  EXPECT_TRUE(val.IsTypeCompatible<const int*>());
+  EXPECT_FALSE(val.IsTypeCompatible<int[]>());
+  EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
+  EXPECT_EQ(30, val.Get<const int*>()[2]);
+}
+
+TEST(Any, References) {
+  // Passing references to object via Any might be error-prone or the
+  // semantics could be unfamiliar to other developers. In many cases,
+  // using pointers instead of references are more conventional and easier
+  // to understand. Even though the cases of passing references are quite
+  // explicit on both storing and retrieving ends, you might want to
+  // use pointers instead anyway.
+
+  int a = 5;
+  Any val(std::ref(a));  // int&
+  EXPECT_EQ(5, val.Get<std::reference_wrapper<int>>().get());
+  val.Get<std::reference_wrapper<int>>().get() = 7;
+  EXPECT_EQ(7, val.Get<std::reference_wrapper<int>>().get());
+  EXPECT_EQ(7, a);
+
+  Any val2(std::cref(a));  // const int&
+  EXPECT_EQ(7, val2.Get<std::reference_wrapper<const int>>().get());
+
+  a = 10;
+  EXPECT_EQ(10, val.Get<std::reference_wrapper<int>>().get());
+  EXPECT_EQ(10, val2.Get<std::reference_wrapper<const int>>().get());
+}
+
+TEST(Any, CustomTypes) {
+  struct Person {
+    std::string name;
+    int age;
+  };
+  Any val(Person{"Jack", 40});  // NOLINT(whitespace/braces)
+  Any val2 = val;
+  EXPECT_EQ("Jack", val.Get<Person>().name);
+  val.GetPtr<Person>()->name = "Joe";
+  val.GetPtr<Person>()->age /= 2;
+  EXPECT_EQ("Joe", val.Get<Person>().name);
+  EXPECT_EQ(20, val.Get<Person>().age);
+  EXPECT_EQ("Jack", val2.Get<Person>().name);
+  EXPECT_EQ(40, val2.Get<Person>().age);
+}
+
+TEST(Any, Swap) {
+  Any val(12);
+  Any val2(2.7);
+  EXPECT_EQ(12, val.Get<int>());
+  EXPECT_EQ(2.7, val2.Get<double>());
+
+  val.Swap(val2);
+  EXPECT_EQ(2.7, val.Get<double>());
+  EXPECT_EQ(12, val2.Get<int>());
+
+  std::swap(val, val2);
+  EXPECT_EQ(12, val.Get<int>());
+  EXPECT_EQ(2.7, val2.Get<double>());
+}
+
+TEST(Any, TypeMismatch) {
+  Any val(12);
+  EXPECT_DEATH(val.Get<double>(),
+               "Requesting value of type \\w+ from variant containing \\w+");
+
+  val = std::string("123");
+  EXPECT_DEATH(val.GetAsInteger(),
+               "Unable to convert value of type \\w+ to integer");
+
+  Any empty;
+  EXPECT_DEATH(empty.GetAsInteger(), "Must not be called on an empty Any");
+}
+
+TEST(Any, TryGet) {
+  Any val(12);
+  Any empty;
+  EXPECT_EQ("dummy", val.TryGet<std::string>("dummy"));
+  EXPECT_EQ(12, val.TryGet<int>(17));
+  EXPECT_EQ(17, empty.TryGet<int>(17));
+}
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index 7e5c71a..f997532 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -27,6 +27,7 @@
       'target_name': 'buffet_common',
       'type': 'static_library',
       'sources': [
+        'any.cc',
         'async_event_sequencer.cc',
         'data_encoding.cc',
         'dbus_constants.cc',
@@ -75,6 +76,8 @@
       ],
       'includes': ['../common-mk/common_test.gypi'],
       'sources': [
+        'any_unittest.cc',
+        'any_internal_impl_unittest.cc',
         'async_event_sequencer_unittest.cc',
         'buffet_testrunner.cc',
         'data_encoding_unittest.cc',