* Change C++ serialization/deserialization to not be move-only operations   (with the except of |Handle|, which is move-only). * Change deserialization of structs and unions to take in a pre-initialized   struct instead of initializing it inside Deserialize_().

This is all related to issue #419.

Details on what this change has:
* Generated Serialize_(), SerializeArray_(), and related functions operate on
  pointers to their types, since these types are move-only.
* Generated [De]Serialize_() for mojom structs and unions don't operate on |StructPtr|, but
  instead on |Struct*|.  This is also true for Serialize[Array|Map]_().
* |Map| will uses iterator_util.h to help serialize its keys and values, instead
  of constructing an |Array| by moving its elements and calling
  SerializeArray_().

R=viettrungluu@chromium.org, jamesr@chromium.org

Review URL: https://codereview.chromium.org/1358353002 .
diff --git a/mojo/public/cpp/bindings/lib/array_serialization.h b/mojo/public/cpp/bindings/lib/array_serialization.h
index 9d0e7bb..dc98245 100644
--- a/mojo/public/cpp/bindings/lib/array_serialization.h
+++ b/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -6,33 +6,30 @@
 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
 
 #include <string.h>  // For |memcpy()|.
-
 #include <vector>
 
 #include "mojo/public/c/system/macros.h"
 #include "mojo/public/cpp/bindings/lib/array_internal.h"
-#include "mojo/public/cpp/bindings/lib/map_serialization.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/iterator_util.h"
+#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
+#include "mojo/public/cpp/bindings/lib/map_serialization_forward.h"
 #include "mojo/public/cpp/bindings/lib/string_serialization.h"
 #include "mojo/public/cpp/bindings/lib/template_util.h"
 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
 
 namespace mojo {
-
-template <typename E>
-inline size_t GetSerializedSize_(const Array<E>& input);
-
-template <typename E, typename F>
-inline void SerializeArray_(
-    Array<E> input,
-    internal::Buffer* buf,
-    internal::Array_Data<F>** output,
-    const internal::ArrayValidateParams* validate_params);
-
-template <typename E, typename F>
-inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output);
-
 namespace internal {
 
+// The ArraySerializer template contains static methods for serializing |Array|s
+// of various types.  These methods include:
+//   * size_t GetSerializedSize(..)
+//       Computes the size of the serialized version of the |Array|.
+//   * void SerializeElements(..)
+//       Takes an |Iterator| and a size and serializes it.
+//   * void DeserializeElements(..)
+//       Takes a pointer to an |Array_Data| and deserializes it into a given
+//       |Array|.
 template <typename E,
           typename F,
           bool is_union =
@@ -47,7 +44,9 @@
     return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E));
   }
 
-  static void SerializeElements(Array<E> input,
+  template <typename Iterator>
+  static void SerializeElements(Iterator it,
+                                size_t num_elements,
                                 Buffer* buf,
                                 Array_Data<F>* output,
                                 const ArrayValidateParams* validate_params) {
@@ -55,10 +54,25 @@
         << "Primitive type should be non-nullable";
     MOJO_DCHECK(!validate_params->element_validate_params)
         << "Primitive type should not have array validate params";
-
-    if (input.size())
-      memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E));
+    for (size_t i = 0; i < num_elements; ++i, ++it)
+      output->at(i) = *it;
   }
+
+  // We can optimize serializing PODs by |memcpy|ing directly.
+  // Note that this has precedence over its templated sibling defined above.
+  static void SerializeElements(typename Array<E>::Iterator it,
+                                size_t num_elements,
+                                Buffer* buf,
+                                Array_Data<F>* output,
+                                const ArrayValidateParams* validate_params) {
+    MOJO_DCHECK(!validate_params->element_is_nullable)
+        << "Primitive type should be non-nullable";
+    MOJO_DCHECK(!validate_params->element_validate_params)
+        << "Primitive type should not have array validate params";
+    if (num_elements)
+      memcpy(output->storage(), &(*it), num_elements * sizeof(E));
+  }
+
   static void DeserializeElements(Array_Data<F>* input, Array<E>* output) {
     std::vector<E> result(input->size());
     if (input->size())
@@ -74,7 +88,9 @@
     return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8);
   }
 
-  static void SerializeElements(Array<bool> input,
+  template <typename Iterator>
+  static void SerializeElements(Iterator it,
+                                size_t num_elements,
                                 Buffer* buf,
                                 Array_Data<bool>* output,
                                 const ArrayValidateParams* validate_params) {
@@ -84,9 +100,10 @@
         << "Primitive type should not have array validate params";
 
     // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
-    for (size_t i = 0; i < input.size(); ++i)
-      output->at(i) = input[i];
+    for (size_t i = 0; i < num_elements; ++i, ++it)
+      output->at(i) = *it;
   }
+
   static void DeserializeElements(Array_Data<bool>* input,
                                   Array<bool>* output) {
     Array<bool> result(input->size());
@@ -104,23 +121,27 @@
     return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H));
   }
 
-  static void SerializeElements(Array<ScopedHandleBase<H>> input,
+  template <typename Iterator>
+  static void SerializeElements(Iterator it,
+                                size_t num_elements,
                                 Buffer* buf,
                                 Array_Data<H>* output,
                                 const ArrayValidateParams* validate_params) {
     MOJO_DCHECK(!validate_params->element_validate_params)
         << "Handle type should not have array validate params";
 
-    for (size_t i = 0; i < input.size(); ++i) {
-      output->at(i) = input[i].release();  // Transfer ownership of the handle.
+    for (size_t i = 0; i < num_elements; ++i, ++it) {
+      // Transfer ownership of the handle.
+      output->at(i) = it->release();
       MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
           !validate_params->element_is_nullable && !output->at(i).is_valid(),
           VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
           MakeMessageWithArrayIndex(
-              "invalid handle in array expecting valid handles", input.size(),
+              "invalid handle in array expecting valid handles", num_elements,
               i));
     }
   }
+
   static void DeserializeElements(Array_Data<H>* input,
                                   Array<ScopedHandleBase<H>>* output) {
     Array<ScopedHandleBase<H>> result(input->size());
@@ -130,8 +151,9 @@
   }
 };
 
-// This template must only apply to pointer mojo entity (structs and arrays).
-// This is done by ensuring that WrapperTraits<S>::DataType is a pointer.
+// This template must only apply to pointer mojo entity (structs, arrays,
+// strings).  This is done by ensuring that WrapperTraits<S>::DataType is a
+// pointer.
 template <typename S>
 struct ArraySerializer<
     S,
@@ -144,66 +166,109 @@
     size_t size = sizeof(Array_Data<S_Data*>) +
                   input.size() * sizeof(StructPointer<S_Data>);
     for (size_t i = 0; i < input.size(); ++i)
-      size += GetSerializedSize_(input[i]);
+      size += GetSerializedSize_(*(UnwrapConstStructPtr<S>::value(input[i])));
     return size;
   }
 
-  static void SerializeElements(Array<S> input,
+  template <typename Iterator>
+  static void SerializeElements(Iterator it,
+                                size_t num_elements,
                                 Buffer* buf,
                                 Array_Data<S_Data*>* output,
                                 const ArrayValidateParams* validate_params) {
-    for (size_t i = 0; i < input.size(); ++i) {
+    for (size_t i = 0; i < num_elements; ++i, ++it) {
       S_Data* element;
-      SerializeCaller<S>::Run(input[i].Pass(), buf, &element,
-                              validate_params->element_validate_params);
+      SerializeCaller::Run(&(*it), buf, &element,
+                           validate_params->element_validate_params);
       output->at(i) = element;
       MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
           !validate_params->element_is_nullable && !element,
           VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
           MakeMessageWithArrayIndex("null in array expecting valid pointers",
-                                    input.size(), i));
+                                    num_elements, i));
     }
   }
+
   static void DeserializeElements(Array_Data<S_Data*>* input,
                                   Array<S>* output) {
     Array<S> result(input->size());
     for (size_t i = 0; i < input->size(); ++i) {
-      Deserialize_(input->at(i), &result[i]);
+      DeserializeCaller::Run(input->at(i), &result[i]);
     }
     output->Swap(&result);
   }
 
  private:
-  template <typename T>
+  // SerializeCaller template is used by |ArraySerializer| to dispatch a
+  // serialize call on a non-POD type.  This template is defined outside
+  // |ArraySerializer| since you cannot specialize a struct within a class
+  // definition.
   struct SerializeCaller {
-    static void Run(T input,
+    // This template needs to be suppressed if |T| is |String|, otherwise it
+    // takes precedence over the |String|-overloaded Run() below.
+    template <typename T,
+              typename = typename EnableIf<!IsSame<T, String>::value, T>::type>
+    static void Run(T* input,
                     Buffer* buf,
                     typename WrapperTraits<T>::DataType* output,
                     const ArrayValidateParams* validate_params) {
       MOJO_DCHECK(!validate_params)
           << "Struct type should not have array validate params";
-
-      Serialize_(input.Pass(), buf, output);
+      Serialize_(UnwrapStructPtr<T>::value(*input), buf, output);
     }
-  };
 
-  template <typename T>
-  struct SerializeCaller<Array<T>> {
-    static void Run(Array<T> input,
+    static void Run(const String* input,
+                    Buffer* buf,
+                    String_Data** output,
+                    const ArrayValidateParams* validate_params) {
+      MOJO_DCHECK(validate_params &&
+                  !validate_params->element_validate_params &&
+                  !validate_params->element_is_nullable &&
+                  validate_params->expected_num_elements == 0)
+          << "String type has unexpected array validate params";
+      SerializeString_(*input, buf, output);
+    }
+
+    template <typename T>
+    static void Run(Array<T>* input,
                     Buffer* buf,
                     typename Array<T>::Data_** output,
                     const ArrayValidateParams* validate_params) {
-      SerializeArray_(input.Pass(), buf, output, validate_params);
+      SerializeArray_(input, buf, output, validate_params);
+    }
+
+    template <typename Key, typename Value>
+    static void Run(Map<Key, Value>* input,
+                    Buffer* buf,
+                    typename Map<Key, Value>::Data_** output,
+                    const ArrayValidateParams* validate_params) {
+      SerializeMap_(input, buf, output, validate_params);
     }
   };
 
-  template <typename T, typename U>
-  struct SerializeCaller<Map<T, U>> {
-    static void Run(Map<T, U> input,
-                    Buffer* buf,
-                    typename Map<T, U>::Data_** output,
-                    const ArrayValidateParams* validate_params) {
-      SerializeMap_(input.Pass(), buf, output, validate_params);
+  struct DeserializeCaller {
+    template <typename T>
+    static void Run(typename WrapperTraits<T>::DataType input, T* output) {
+      Deserialize_(input, output);
+    }
+
+    // Since Deserialize_ takes in a |Struct*| (not |StructPtr|), we need to
+    // initialize the |StructPtr| here before deserializing into its underlying
+    // data.
+    // TODO(vardhan):  Either all containers, or just Deserialize_(), should
+    // support taking in an allocator.
+    template <typename T>
+    static void Run(typename WrapperTraits<StructPtr<T>>::DataType input,
+                    StructPtr<T>* output) {
+      *output = T::New();
+      Deserialize_(input, output->get());
+    }
+
+    template <typename T>
+    static void Run(typename WrapperTraits<InlinedStructPtr<T>>::DataType input,
+                    InlinedStructPtr<T>* output) {
+      *output = T::New();
+      Deserialize_(input, output->get());
     }
   };
 };
@@ -221,72 +286,37 @@
     return size;
   }
 
-  static void SerializeElements(Array<U> input,
+  template <typename Iterator>
+  static void SerializeElements(Iterator it,
+                                size_t num_elements,
                                 Buffer* buf,
                                 Array_Data<U_Data>* output,
                                 const ArrayValidateParams* validate_params) {
-    for (size_t i = 0; i < input.size(); ++i) {
+    for (size_t i = 0; i < num_elements; ++i, ++it) {
       U_Data* result = output->storage() + i;
-      SerializeUnion_(input[i].Pass(), buf, &result, true);
+      SerializeUnion_(it->get(), buf, &result, true);
       MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
           !validate_params->element_is_nullable && output->at(i).is_null(),
           VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
           MakeMessageWithArrayIndex("null in array expecting valid unions",
-                                    input.size(), i));
+                                    num_elements, i));
     }
   }
 
   static void DeserializeElements(Array_Data<U_Data>* input, Array<U>* output) {
     Array<U> result(input->size());
     for (size_t i = 0; i < input->size(); ++i) {
-      Deserialize_(&input->at(i), &result[i]);
+      auto& elem = input->at(i);
+      if (!elem.is_null()) {
+        using UnwrapedUnionType = typename RemoveStructPtr<U>::type;
+        result[i] = UnwrapedUnionType::New();
+        Deserialize_(&elem, result[i].get());
+      }
     }
     output->Swap(&result);
   }
 };
 
-// Handles serialization and deserialization of arrays of strings.
-template <>
-struct ArraySerializer<String, String_Data*> {
-  static size_t GetSerializedSize(const Array<String>& input) {
-    size_t size =
-        sizeof(Array_Data<String_Data*>) + input.size() * sizeof(StringPointer);
-    for (size_t i = 0; i < input.size(); ++i)
-      size += GetSerializedSize_(input[i]);
-    return size;
-  }
-
-  static void SerializeElements(Array<String> input,
-                                Buffer* buf,
-                                Array_Data<String_Data*>* output,
-                                const ArrayValidateParams* validate_params) {
-    MOJO_DCHECK(
-        validate_params->element_validate_params &&
-        !validate_params->element_validate_params->element_validate_params &&
-        !validate_params->element_validate_params->element_is_nullable &&
-        validate_params->element_validate_params->expected_num_elements == 0)
-        << "String type has unexpected array validate params";
-
-    for (size_t i = 0; i < input.size(); ++i) {
-      String_Data* element;
-      Serialize_(input[i], buf, &element);
-      output->at(i) = element;
-      MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-          !validate_params->element_is_nullable && !element,
-          VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
-          MakeMessageWithArrayIndex("null in array expecting valid strings",
-                                    input.size(), i));
-    }
-  }
-  static void DeserializeElements(Array_Data<String_Data*>* input,
-                                  Array<String>* output) {
-    Array<String> result(input->size());
-    for (size_t i = 0; i < input->size(); ++i)
-      Deserialize_(input->at(i), &result[i]);
-    output->Swap(&result);
-  }
-};
-
 }  // namespace internal
 
 template <typename E>
@@ -299,24 +329,25 @@
 
 template <typename E, typename F>
 inline void SerializeArray_(
-    Array<E> input,
+    Array<E>* input,
     internal::Buffer* buf,
     internal::Array_Data<F>** output,
     const internal::ArrayValidateParams* validate_params) {
-  if (input) {
+  MOJO_DCHECK(input);
+  if (*input) {
     MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
         validate_params->expected_num_elements != 0 &&
-            input.size() != validate_params->expected_num_elements,
+            input->size() != validate_params->expected_num_elements,
         internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
         internal::MakeMessageWithExpectedArraySize(
-            "fixed-size array has wrong number of elements", input.size(),
+            "fixed-size array has wrong number of elements", input->size(),
             validate_params->expected_num_elements));
 
     internal::Array_Data<F>* result =
-        internal::Array_Data<F>::New(input.size(), buf);
+        internal::Array_Data<F>::New(input->size(), buf);
     if (result) {
       internal::ArraySerializer<E, F>::SerializeElements(
-          internal::Forward(input), buf, result, validate_params);
+          input->begin(), input->size(), buf, result, validate_params);
     }
     *output = result;
   } else {
diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h
index bb7347e..e0a3939 100644
--- a/mojo/public/cpp/bindings/lib/bindings_internal.h
+++ b/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -105,6 +105,42 @@
 };
 
 template <typename T>
+struct UnwrapStructPtr {
+  static T* value(T& x) { return &x; }
+};
+
+template <typename T>
+struct UnwrapStructPtr<StructPtr<T>> {
+  static T* value(StructPtr<T>& x) { return x.get(); }
+};
+
+template <typename T>
+struct UnwrapStructPtr<InlinedStructPtr<T>> {
+  static T* value(InlinedStructPtr<T>& x) { return x.get(); }
+};
+
+template <typename T>
+struct UnwrapConstStructPtr {
+  static const T* value(const T& x) { return &x; }
+};
+
+template <typename T>
+struct UnwrapConstStructPtr<StructPtr<T>> {
+  static const T* value(const StructPtr<T>& x) { return x.get(); }
+};
+
+template <typename T>
+struct UnwrapConstStructPtr<InlinedStructPtr<T>> {
+  static const T* value(const InlinedStructPtr<T>& x) { return x.get(); }
+};
+
+template <typename T>
+struct IsStructPtr {
+  static bool const value = IsSpecializationOf<StructPtr, T>::value ||
+                            IsSpecializationOf<InlinedStructPtr, T>::value;
+};
+
+template <typename T>
 struct IsUnionWrapperType {
   template <typename U>
   static YesType Test(const typename U::Data_::MojomUnionDataType*);
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc
index 5113bb0..4e7efc8 100644
--- a/mojo/public/cpp/bindings/lib/control_message_handler.cc
+++ b/mojo/public/cpp/bindings/lib/control_message_handler.cc
@@ -51,11 +51,11 @@
   response_params_ptr->query_version_result = QueryVersionResult::New();
   response_params_ptr->query_version_result->version = interface_version_;
 
-  size_t size = GetSerializedSize_(response_params_ptr);
+  size_t size = GetSerializedSize_(*response_params_ptr);
   ResponseMessageBuilder builder(kRunMessageId, size, message->request_id());
 
   RunResponseMessageParams_Data* response_params = nullptr;
-  Serialize_(response_params_ptr.Pass(), builder.buffer(), &response_params);
+  Serialize_(response_params_ptr.get(), builder.buffer(), &response_params);
   response_params->EncodePointersAndHandles(
       builder.message()->mutable_handles());
   bool ok = responder->Accept(builder.message());
@@ -71,8 +71,8 @@
           message->mutable_payload());
   params->DecodePointersAndHandles(message->mutable_handles());
 
-  RunOrClosePipeMessageParamsPtr params_ptr;
-  Deserialize_(params, &params_ptr);
+  RunOrClosePipeMessageParamsPtr params_ptr(RunOrClosePipeMessageParams::New());
+  Deserialize_(params, params_ptr.get());
 
   return interface_version_ >= params_ptr->require_version->version;
 }
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
index ad729c5..ee1e695 100644
--- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc
+++ b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -33,8 +33,8 @@
           message->mutable_payload());
   params->DecodePointersAndHandles(message->mutable_handles());
 
-  RunResponseMessageParamsPtr params_ptr;
-  Deserialize_(params, &params_ptr);
+  RunResponseMessageParamsPtr params_ptr(RunResponseMessageParams::New());
+  Deserialize_(params, params_ptr.get());
 
   callback_.Run(params_ptr->query_version_result.Pass());
   return true;
@@ -48,11 +48,11 @@
   params_ptr->reserved1 = 0u;
   params_ptr->query_version = query_version.Pass();
 
-  size_t size = GetSerializedSize_(params_ptr);
+  size_t size = GetSerializedSize_(*params_ptr);
   RequestMessageBuilder builder(kRunMessageId, size);
 
   RunMessageParams_Data* params = nullptr;
-  Serialize_(params_ptr.Pass(), builder.buffer(), &params);
+  Serialize_(params_ptr.get(), builder.buffer(), &params);
   params->EncodePointersAndHandles(builder.message()->mutable_handles());
   MessageReceiver* responder = new RunResponseForwardToCallback(callback);
   if (!receiver->AcceptWithResponder(builder.message(), responder))
@@ -66,11 +66,11 @@
   params_ptr->reserved1 = 0u;
   params_ptr->require_version = require_version.Pass();
 
-  size_t size = GetSerializedSize_(params_ptr);
+  size_t size = GetSerializedSize_(*params_ptr);
   MessageBuilder builder(kRunOrClosePipeMessageId, size);
 
   RunOrClosePipeMessageParams_Data* params = nullptr;
-  Serialize_(params_ptr.Pass(), builder.buffer(), &params);
+  Serialize_(params_ptr.get(), builder.buffer(), &params);
   params->EncodePointersAndHandles(builder.message()->mutable_handles());
   bool ok = receiver->Accept(builder.message());
   MOJO_ALLOW_UNUSED_LOCAL(ok);
diff --git a/mojo/public/cpp/bindings/lib/map_internal.h b/mojo/public/cpp/bindings/lib/map_internal.h
index 84f927c..cf3f0d9 100644
--- a/mojo/public/cpp/bindings/lib/map_internal.h
+++ b/mojo/public/cpp/bindings/lib/map_internal.h
@@ -40,20 +40,6 @@
     for (size_t i = 0; i < keys.size(); ++i)
       Insert(m, keys[i], values[i]);
   }
-  static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m,
-                               mojo::Array<Key>* keys,
-                               mojo::Array<Value>* values) {
-    keys->resize(m->size());
-    values->resize(m->size());
-    int i = 0;
-    for (typename std::map<KeyStorageType, ValueStorageType>::iterator
-             it = m->begin();
-         it != m->end();
-         ++it, ++i) {
-      (*keys)[i] = it->first;
-      (*values)[i] = it->second;
-    }
-  }
   static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) {}
   static inline ValueRefType at(std::map<KeyStorageType, ValueStorageType>* m,
                                 KeyForwardType key) {
@@ -133,20 +119,6 @@
     for (size_t i = 0; i < keys.size(); ++i)
       Insert(m, keys[i], values[i]);
   }
-  static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m,
-                               mojo::Array<Key>* keys,
-                               mojo::Array<Value>* values) {
-    keys->resize(m->size());
-    values->resize(m->size());
-    int i = 0;
-    for (typename std::map<KeyStorageType, ValueStorageType>::iterator
-             it = m->begin();
-         it != m->end();
-         ++it, ++i) {
-      (*keys)[i] = it->first;
-      (*values)[i] = GetValue(it).Pass();
-    }
-  }
   static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) {
     for (auto& pair : *m)
       reinterpret_cast<Value*>(pair.second.buf)->~Value();
diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h
index 7ca177d..8ef83b3 100644
--- a/mojo/public/cpp/bindings/lib/map_serialization.h
+++ b/mojo/public/cpp/bindings/lib/map_serialization.h
@@ -6,23 +6,15 @@
 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
 
 #include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/array_serialization.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/iterator_util.h"
 #include "mojo/public/cpp/bindings/lib/map_data_internal.h"
 #include "mojo/public/cpp/bindings/lib/map_internal.h"
 #include "mojo/public/cpp/bindings/lib/string_serialization.h"
 #include "mojo/public/cpp/bindings/map.h"
 
 namespace mojo {
-
-template <typename Key, typename Value>
-inline size_t GetSerializedSize_(const Map<Key, Value>& input);
-
-template <typename ValidateParams, typename E, typename F>
-inline void SerializeArray_(
-    Array<E> input,
-    internal::Buffer* buf,
-    internal::Array_Data<F>** output,
-    const internal::ArrayValidateParams* validate_params);
-
 namespace internal {
 
 template <typename MapType,
@@ -70,7 +62,9 @@
   static size_t GetBaseArraySize(size_t count) {
     return count * sizeof(StructPointer<S_Data>);
   }
-  static size_t GetItemSize(const S& item) { return GetSerializedSize_(item); }
+  static size_t GetItemSize(const S& item) {
+    return GetSerializedSize_(*UnwrapConstStructPtr<S>::value(item));
+  }
 };
 
 template <typename U, typename U_Data>
@@ -135,22 +129,39 @@
           typename DataKey,
           typename DataValue>
 inline void SerializeMap_(
-    Map<MapKey, MapValue> input,
+    Map<MapKey, MapValue>* input,
     internal::Buffer* buf,
     internal::Map_Data<DataKey, DataValue>** output,
     const internal::ArrayValidateParams* value_validate_params) {
-  if (input) {
+  if (input && *input) {
     internal::Map_Data<DataKey, DataValue>* result =
         internal::Map_Data<DataKey, DataValue>::New(buf);
-    if (result) {
-      Array<MapKey> keys;
-      Array<MapValue> values;
-      input.DecomposeMapTo(&keys, &values);
+    internal::Array_Data<DataKey>* keys_data =
+        internal::Array_Data<DataKey>::New(input->size(), buf);
+
+    if (result && keys_data) {
+      result->keys.ptr = keys_data;
+
+      // We *must* serialize the keys before we allocate an Array_Data for the
+      // values.
+      internal::MapKeyIterator<MapKey, MapValue> key_iter(input);
       const internal::ArrayValidateParams* key_validate_params =
           internal::MapKeyValidateParamsFactory<DataKey>::Get();
-      SerializeArray_(keys.Pass(), buf, &result->keys.ptr, key_validate_params);
-      SerializeArray_(values.Pass(), buf, &result->values.ptr,
-                      value_validate_params);
+
+      internal::ArraySerializer<MapKey, DataKey>::SerializeElements(
+          key_iter.begin(), input->size(), buf, result->keys.ptr,
+          key_validate_params);
+
+      // Now we try allocate an Array_Data for the values
+      internal::Array_Data<DataValue>* values_data =
+          internal::Array_Data<DataValue>::New(input->size(), buf);
+      if (values_data) {
+        result->values.ptr = values_data;
+        internal::MapValueIterator<MapKey, MapValue> value_iter(input);
+        internal::ArraySerializer<MapValue, DataValue>::SerializeElements(
+            value_iter.begin(), input->size(), buf, result->values.ptr,
+            value_validate_params);
+      }
     }
     *output = result;
   } else {
diff --git a/mojo/public/cpp/bindings/lib/map_serialization_forward.h b/mojo/public/cpp/bindings/lib/map_serialization_forward.h
new file mode 100644
index 0000000..40f6e8e
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/map_serialization_forward.h
@@ -0,0 +1,45 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Headers such as array_serialization.h can include this file to avoid circular
+// dependencies on map_serialization.h.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_FORWARD_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_FORWARD_H_
+
+namespace mojo {
+namespace internal {
+
+class ArrayValidateParams;
+class Buffer;
+
+template <typename Key, typename Value>
+class Map_Data;
+
+}  // namespace internal
+
+template <typename Key, typename Value>
+class Map;
+
+template <typename MapKey,
+          typename MapValue,
+          typename DataKey,
+          typename DataValue>
+void SerializeMap_(Map<MapKey, MapValue>* input,
+                   internal::Buffer* buf,
+                   internal::Map_Data<DataKey, DataValue>** output,
+                   const internal::ArrayValidateParams* value_validate_params);
+template <typename MapKey, typename MapValue>
+size_t GetSerializedSize_(const Map<MapKey, MapValue>& input);
+
+template <typename MapKey,
+          typename MapValue,
+          typename DataKey,
+          typename DataValue>
+void Deserialize_(internal::Map_Data<DataKey, DataValue>* input,
+                  Map<MapKey, MapValue>* output);
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_FORWARD_H_
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.cc b/mojo/public/cpp/bindings/lib/string_serialization.cc
index e29d6f8..11c8e77 100644
--- a/mojo/public/cpp/bindings/lib/string_serialization.cc
+++ b/mojo/public/cpp/bindings/lib/string_serialization.cc
@@ -14,9 +14,9 @@
   return internal::Align(sizeof(internal::String_Data) + input.size());
 }
 
-void Serialize_(const String& input,
-                internal::Buffer* buf,
-                internal::String_Data** output) {
+void SerializeString_(const String& input,
+                      internal::Buffer* buf,
+                      internal::String_Data** output) {
   if (input) {
     internal::String_Data* result =
         internal::String_Data::New(input.size(), buf);
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h
index 0118742..20b53b2 100644
--- a/mojo/public/cpp/bindings/lib/string_serialization.h
+++ b/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -11,9 +11,10 @@
 namespace mojo {
 
 size_t GetSerializedSize_(const String& input);
-void Serialize_(const String& input,
-                internal::Buffer* buffer,
-                internal::String_Data** output);
+void SerializeString_(const String& input,
+                      internal::Buffer* buffer,
+                      internal::String_Data** output);
+
 void Deserialize_(internal::String_Data* input, String* output);
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/map.h b/mojo/public/cpp/bindings/map.h
index f59f2f4..3a358e6 100644
--- a/mojo/public/cpp/bindings/map.h
+++ b/mojo/public/cpp/bindings/map.h
@@ -135,18 +135,6 @@
     map_.swap(*other);
   }
 
-  // Removes all contents from the Map and places them into parallel key/value
-  // arrays. Each key will be copied from the source to the destination, and
-  // values will be copied unless their type is designated move-only, in which
-  // case they will be passed by calling their Pass() method. Either way, the
-  // Map will be left in a null state.
-  void DecomposeMapTo(mojo::Array<Key>* keys, mojo::Array<Value>* values) {
-    Traits::Decompose(&map_, keys, values);
-    Traits::Finalize(&map_);
-    map_.clear();
-    is_null_ = true;
-  }
-
   // Returns a new Map that contains a copy of the contents of this map.  If the
   // values are of a type that is designated move-only, they will be cloned
   // using the Clone() method of the type. Please note that calling this method
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h
index 04a8130..b47a1ed 100644
--- a/mojo/public/cpp/bindings/struct_ptr.h
+++ b/mojo/public/cpp/bindings/struct_ptr.h
@@ -150,7 +150,7 @@
     MOJO_DCHECK(!is_null_);
     return &value_;
   }
-  Struct* get() const { return &value_; }
+  Struct* get() const { return is_null() ? nullptr : &value_; }
 
   void Swap(InlinedStructPtr* other) {
     std::swap(value_, other->value_);
diff --git a/mojo/public/cpp/bindings/tests/array_unittest.cc b/mojo/public/cpp/bindings/tests/array_unittest.cc
index bdfc4a1..ffee9cc 100644
--- a/mojo/public/cpp/bindings/tests/array_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/array_unittest.cc
@@ -161,7 +161,7 @@
   FixedBufferForTesting buf(size);
   Array_Data<int32_t>* data;
   ArrayValidateParams validate_params(0, false, nullptr);
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<int32_t> array2;
   Deserialize_(data, &array2);
@@ -179,7 +179,7 @@
   FixedBufferForTesting buf(size);
   Array_Data<int32_t>* data;
   ArrayValidateParams validate_params(0, false, nullptr);
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<int32_t> array2;
   Deserialize_(data, &array2);
@@ -202,7 +202,7 @@
   Array_Data<Array_Data<int32_t>*>* data;
   ArrayValidateParams validate_params(
       0, false, new ArrayValidateParams(0, false, nullptr));
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<Array<int32_t>> array2;
   Deserialize_(data, &array2);
@@ -227,7 +227,7 @@
   FixedBufferForTesting buf(size);
   Array_Data<bool>* data;
   ArrayValidateParams validate_params(0, false, nullptr);
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<bool> array2;
   Deserialize_(data, &array2);
@@ -255,7 +255,7 @@
   Array_Data<String_Data*>* data;
   ArrayValidateParams validate_params(
       0, false, new ArrayValidateParams(0, false, nullptr));
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<String> array2;
   Deserialize_(data, &array2);
diff --git a/mojo/public/cpp/bindings/tests/map_unittest.cc b/mojo/public/cpp/bindings/tests/map_unittest.cc
index 44100a4..9a15253 100644
--- a/mojo/public/cpp/bindings/tests/map_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/map_unittest.cc
@@ -6,6 +6,7 @@
 #include "mojo/public/cpp/bindings/lib/array_serialization.h"
 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/map_serialization.h"
 #include "mojo/public/cpp/bindings/lib/validate_params.h"
 #include "mojo/public/cpp/bindings/map.h"
 #include "mojo/public/cpp/bindings/string.h"
@@ -115,44 +116,6 @@
   }
 }
 
-TEST_F(MapTest, DecomposeMapTo) {
-  Array<String> keys(kStringIntDataSize);
-  Array<int> values(kStringIntDataSize);
-  for (size_t i = 0; i < kStringIntDataSize; ++i) {
-    keys[i] = kStringIntData[i].string_data;
-    values[i] = kStringIntData[i].int_data;
-  }
-
-  Map<String, int> map(keys.Pass(), values.Pass());
-  EXPECT_EQ(kStringIntDataSize, map.size());
-
-  Array<String> keys2;
-  Array<int> values2;
-  map.DecomposeMapTo(&keys2, &values2);
-  EXPECT_EQ(0u, map.size());
-
-  EXPECT_EQ(kStringIntDataSize, keys2.size());
-  EXPECT_EQ(kStringIntDataSize, values2.size());
-
-  for (size_t i = 0; i < kStringIntDataSize; ++i) {
-    // We are not guaranteed that the copies have the same sorting as the
-    // originals.
-    String key = kStringIntData[i].string_data;
-    int value = kStringIntData[i].int_data;
-
-    bool found = false;
-    for (size_t j = 0; j < keys2.size(); ++j) {
-      if (keys2[j] == key) {
-        EXPECT_EQ(value, values2[j]);
-        found = true;
-        break;
-      }
-    }
-
-    EXPECT_TRUE(found);
-  }
-}
-
 TEST_F(MapTest, Insert_Copyable) {
   ASSERT_EQ(0u, CopyableType::num_instances());
   mojo::Map<mojo::String, CopyableType> map;
@@ -283,7 +246,7 @@
     Array_Data<Map_Data<int32_t, int8_t>*>* data;
     ArrayValidateParams validate_params(
         0, false, new ArrayValidateParams(0, false, nullptr));
-    SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+    SerializeArray_(&array, &buf, &data, &validate_params);
 
     Array<Map<int32_t, int8_t>> deserialized_array;
     Deserialize_(data, &deserialized_array);
@@ -306,7 +269,7 @@
     ArrayValidateParams validate_params(
         0, false, new ArrayValidateParams(
                       0, false, new ArrayValidateParams(0, false, nullptr)));
-    SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+    SerializeArray_(&array, &buf, &data, &validate_params);
 
     Array<Map<String, Array<bool>>> deserialized_array;
     Deserialize_(data, &deserialized_array);
diff --git a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
index 43955cb..b61d3bc 100644
--- a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
@@ -59,9 +59,9 @@
                              mojo::internal::ValidationError expected_warning) {
     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
 
-    mojo::internal::FixedBufferForTesting buf(GetSerializedSize_(obj));
+    mojo::internal::FixedBufferForTesting buf(GetSerializedSize_(*obj));
     typename T::Data_* data;
-    Serialize_(obj.Pass(), &buf, &data);
+    Serialize_(obj.get(), &buf, &data);
 
     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
   }
@@ -74,7 +74,7 @@
 
     mojo::internal::FixedBufferForTesting buf(GetSerializedSize_(obj));
     typename T::Data_* data;
-    SerializeArray_(obj.Pass(), &buf, &data, validate_params);
+    SerializeArray_(&obj, &buf, &data, validate_params);
 
     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
   }
diff --git a/mojo/public/cpp/bindings/tests/struct_unittest.cc b/mojo/public/cpp/bindings/tests/struct_unittest.cc
index 71069d2..283dd8e 100644
--- a/mojo/public/cpp/bindings/tests/struct_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/struct_unittest.cc
@@ -51,10 +51,10 @@
   typedef typename mojo::internal::WrapperTraits<T>::DataType InputDataType;
   typedef typename mojo::internal::WrapperTraits<U>::DataType OutputDataType;
 
-  size_t size = GetSerializedSize_(input);
+  size_t size = GetSerializedSize_(*input);
   mojo::internal::FixedBufferForTesting buf(size + 32);
   InputDataType data;
-  Serialize_(input.Pass(), &buf, &data);
+  Serialize_(input.get(), &buf, &data);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -67,8 +67,9 @@
   OutputDataType output_data = reinterpret_cast<OutputDataType>(data);
   output_data->DecodePointersAndHandles(&handles);
 
-  U output;
-  Deserialize_(output_data, &output);
+  using RawUType = typename mojo::internal::RemoveStructPtr<U>::type;
+  U output(RawUType::New());
+  Deserialize_(output_data, output.get());
   return output.Pass();
 }
 
@@ -138,15 +139,15 @@
 TEST_F(StructTest, Serialization_Basic) {
   RectPtr rect(MakeRect());
 
-  size_t size = GetSerializedSize_(rect);
+  size_t size = GetSerializedSize_(*rect);
   EXPECT_EQ(8U + 16U, size);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::Rect_Data* data;
-  Serialize_(rect.Pass(), &buf, &data);
+  Serialize_(rect.get(), &buf, &data);
 
-  RectPtr rect2;
-  Deserialize_(data, &rect2);
+  RectPtr rect2(Rect::New());
+  Deserialize_(data, rect2.get());
 
   CheckRect(*rect2);
 }
@@ -171,15 +172,15 @@
   pair->first = MakeRect();
   pair->second = MakeRect();
 
-  size_t size = GetSerializedSize_(pair);
+  size_t size = GetSerializedSize_(*pair);
   EXPECT_EQ(8U + 16U + 2 * (8U + 16U), size);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::RectPair_Data* data;
-  Serialize_(pair.Pass(), &buf, &data);
+  Serialize_(pair.get(), &buf, &data);
 
-  RectPairPtr pair2;
-  Deserialize_(data, &pair2);
+  RectPairPtr pair2(RectPair::New());
+  Deserialize_(data, pair2.get());
 
   CheckRect(*pair2->first);
   CheckRect(*pair2->second);
@@ -193,7 +194,7 @@
   for (size_t i = 0; i < region->rects.size(); ++i)
     region->rects[i] = MakeRect(static_cast<int32_t>(i) + 1);
 
-  size_t size = GetSerializedSize_(region);
+  size_t size = GetSerializedSize_(*region);
   EXPECT_EQ(8U +            // header
                 8U +        // name pointer
                 8U +        // rects pointer
@@ -207,10 +208,10 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::NamedRegion_Data* data;
-  Serialize_(region.Pass(), &buf, &data);
+  Serialize_(region.get(), &buf, &data);
 
-  NamedRegionPtr region2;
-  Deserialize_(data, &region2);
+  NamedRegionPtr region2(NamedRegion::New());
+  Deserialize_(data, region2.get());
 
   EXPECT_EQ(String("region"), region2->name);
 
@@ -225,7 +226,7 @@
   EXPECT_TRUE(region->name.is_null());
   EXPECT_TRUE(region->rects.is_null());
 
-  size_t size = GetSerializedSize_(region);
+  size_t size = GetSerializedSize_(*region);
   EXPECT_EQ(8U +      // header
                 8U +  // name pointer
                 8U,   // rects pointer
@@ -233,10 +234,10 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::NamedRegion_Data* data;
-  Serialize_(region.Pass(), &buf, &data);
+  Serialize_(region.get(), &buf, &data);
 
-  NamedRegionPtr region2;
-  Deserialize_(data, &region2);
+  NamedRegionPtr region2(NamedRegion::New());
+  Deserialize_(data, region2.get());
 
   EXPECT_TRUE(region2->name.is_null());
   EXPECT_TRUE(region2->rects.is_null());
diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc
index b09957b..e79ea9f 100644
--- a/mojo/public/cpp/bindings/tests/union_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -9,6 +9,7 @@
 #include "mojo/public/cpp/bindings/lib/array_serialization.h"
 #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/map_serialization.h"
 #include "mojo/public/cpp/bindings/string.h"
 #include "mojo/public/cpp/environment/environment.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
@@ -122,10 +123,10 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  SerializeUnion_(pod1.Pass(), &buf, &data, false);
+  SerializeUnion_(pod1.get(), &buf, &data, false);
 
-  PodUnionPtr pod2;
-  Deserialize_(data, &pod2);
+  PodUnionPtr pod2(PodUnion::New());
+  Deserialize_(data, pod2.get());
 
   EXPECT_EQ(10, pod2->get_f_int8());
   EXPECT_TRUE(pod2->is_f_int8());
@@ -141,10 +142,10 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  SerializeUnion_(pod1.Pass(), &buf, &data, false);
+  SerializeUnion_(pod1.get(), &buf, &data, false);
 
-  PodUnionPtr pod2;
-  Deserialize_(data, &pod2);
+  PodUnionPtr pod2 = PodUnion::New();
+  Deserialize_(data, pod2.get());
 
   EXPECT_EQ(AN_ENUM_SECOND, pod2->get_f_enum());
   EXPECT_TRUE(pod2->is_f_enum());
@@ -160,7 +161,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  SerializeUnion_(pod.Pass(), &buf, &data, false);
+  SerializeUnion_(pod.get(), &buf, &data, false);
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
                                                static_cast<uint32_t>(size), 0);
@@ -175,7 +176,7 @@
   size_t size = GetSerializedSize_(pod, false);
   mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  SerializeUnion_(pod.Pass(), &buf, &data, false);
+  SerializeUnion_(pod.get(), &buf, &data, false);
   EXPECT_FALSE(data->is_null());
 }
 
@@ -191,12 +192,12 @@
   data->tag = PodUnion::Tag::F_UINT16;
   data->data.f_f_int16 = 20;
 
-  SerializeUnion_(pod.Pass(), &buf, &data, true);
+  SerializeUnion_(pod.get(), &buf, &data, true);
   EXPECT_TRUE(data->is_null());
 
-  PodUnionPtr pod2;
-  Deserialize_(data, &pod2);
-  EXPECT_TRUE(pod2.is_null());
+  PodUnionPtr pod2 = PodUnion::New();
+  Deserialize_(data, pod2.get());
+  EXPECT_EQ(pod2->which(), PodUnion::Tag::__UNKNOWN__);
 }
 
 TEST(UnionTest, SerializeIsNullNotInlined) {
@@ -205,7 +206,7 @@
   EXPECT_EQ(16U, size);
   mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  SerializeUnion_(pod.Pass(), &buf, &data, false);
+  SerializeUnion_(pod.get(), &buf, &data, false);
   EXPECT_EQ(nullptr, data);
 }
 
@@ -252,8 +253,8 @@
   data->size = size;
   data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100);
 
-  PodUnionPtr pod2;
-  Deserialize_(data, &pod2);
+  PodUnionPtr pod2 = PodUnion::New();
+  Deserialize_(data, pod2.get());
 
   EXPECT_TRUE(pod2->has_unknown_tag());
 }
@@ -315,14 +316,14 @@
   size_t size = GetSerializedSize_(pod1, false);
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(pod1.Pass(), &buf, &data, false);
+  SerializeUnion_(pod1.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
   data->DecodePointersAndHandles(&handles);
 
-  ObjectUnionPtr pod2;
-  Deserialize_(data, &pod2);
+  ObjectUnionPtr pod2 = ObjectUnion::New();
+  Deserialize_(data, pod2.get());
   EXPECT_EQ(hello, pod2->get_f_string());
   EXPECT_TRUE(pod2->is_f_string());
   EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING);
@@ -409,7 +410,7 @@
   mojo::internal::FixedBufferForTesting buf(size);
   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
   mojo::internal::ArrayValidateParams validate_params(0, false, nullptr);
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<PodUnionPtr> array2;
   Deserialize_(data, &array2);
@@ -434,7 +435,7 @@
   mojo::internal::FixedBufferForTesting buf(size);
   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
   mojo::internal::ArrayValidateParams validate_params(0, false, nullptr);
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
@@ -458,7 +459,7 @@
   mojo::internal::FixedBufferForTesting buf(size);
   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
   mojo::internal::ArrayValidateParams validate_params(0, true, nullptr);
-  SerializeArray_(array.Pass(), &buf, &data, &validate_params);
+  SerializeArray_(&array, &buf, &data, &validate_params);
 
   Array<PodUnionPtr> array2;
   Deserialize_(data, &array2);
@@ -488,14 +489,14 @@
   small_struct->pod_union = PodUnion::New();
   small_struct->pod_union->set_f_int32(10);
 
-  size_t size = GetSerializedSize_(small_struct);
+  size_t size = GetSerializedSize_(*small_struct);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  Serialize_(small_struct.Pass(), &buf, &data);
+  Serialize_(small_struct.get(), &buf, &data);
 
-  SmallStructPtr deserialized;
-  Deserialize_(data, &deserialized);
+  SmallStructPtr deserialized(SmallStruct::New());
+  Deserialize_(data, deserialized.get());
 
   EXPECT_EQ(10, deserialized->pod_union->get_f_int32());
 }
@@ -508,18 +509,18 @@
   String hello("hello world");
   obj_struct->obj_union->set_f_string(hello);
 
-  size_t size = GetSerializedSize_(obj_struct);
+  size_t size = GetSerializedSize_(*obj_struct);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallObjStruct_Data* data = nullptr;
-  Serialize_(obj_struct.Pass(), &buf, &data);
+  Serialize_(obj_struct.get(), &buf, &data);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
   data->DecodePointersAndHandles(&handles);
 
-  SmallObjStructPtr deserialized;
-  Deserialize_(data, &deserialized);
+  SmallObjStructPtr deserialized(SmallObjStruct::New());
+  Deserialize_(data, deserialized.get());
 
   EXPECT_EQ(hello, deserialized->obj_union->get_f_string());
 }
@@ -531,11 +532,11 @@
   small_struct->pod_union = PodUnion::New();
   small_struct->pod_union->set_f_int32(10);
 
-  size_t size = GetSerializedSize_(small_struct);
+  size_t size = GetSerializedSize_(*small_struct);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  Serialize_(small_struct.Pass(), &buf, &data);
+  Serialize_(small_struct.get(), &buf, &data);
 
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
@@ -551,11 +552,11 @@
   small_struct->pod_union = PodUnion::New();
   small_struct->pod_union->set_f_int32(10);
 
-  size_t size = GetSerializedSize_(small_struct);
+  size_t size = GetSerializedSize_(*small_struct);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  Serialize_(small_struct.Pass(), &buf, &data);
+  Serialize_(small_struct.get(), &buf, &data);
   data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100);
 
   void* raw_buf = buf.Leak();
@@ -571,7 +572,7 @@
   SmallStructNonNullableUnionPtr small_struct(
       SmallStructNonNullableUnion::New());
 
-  size_t size = GetSerializedSize_(small_struct);
+  size_t size = GetSerializedSize_(*small_struct);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStructNonNullableUnion_Data* data =
@@ -590,11 +591,11 @@
   Environment environment;
   SmallStructPtr small_struct(SmallStruct::New());
 
-  size_t size = GetSerializedSize_(small_struct);
+  size_t size = GetSerializedSize_(*small_struct);
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  Serialize_(small_struct.Pass(), &buf, &data);
+  Serialize_(small_struct.get(), &buf, &data);
 
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
@@ -634,7 +635,7 @@
   mojo::internal::Map_Data<mojo::internal::String_Data*,
                            internal::PodUnion_Data>* data;
   mojo::internal::ArrayValidateParams validate_params(0, false, nullptr);
-  SerializeMap_(map.Pass(), &buf, &data, &validate_params);
+  SerializeMap_(&map, &buf, &data, &validate_params);
 
   Map<String, PodUnionPtr> map2;
   Deserialize_(data, &map2);
@@ -658,7 +659,7 @@
   mojo::internal::Map_Data<mojo::internal::String_Data*,
                            internal::PodUnion_Data>* data;
   mojo::internal::ArrayValidateParams validate_params(0, true, nullptr);
-  SerializeMap_(map.Pass(), &buf, &data, &validate_params);
+  SerializeMap_(&map, &buf, &data, &validate_params);
 
   Map<String, PodUnionPtr> map2;
   Deserialize_(data, &map2);
@@ -690,14 +691,14 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
   data->DecodePointersAndHandles(&handles);
 
-  ObjectUnionPtr obj2;
-  Deserialize_(data, &obj2);
+  ObjectUnionPtr obj2 = ObjectUnion::New();
+  Deserialize_(data, obj2.get());
   EXPECT_EQ(8, obj2->get_f_dummy()->f_int8);
 }
 
@@ -713,7 +714,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
@@ -734,7 +735,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
@@ -755,7 +756,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   void* raw_buf = buf.Leak();
   mojo::internal::BoundsChecker bounds_checker(data,
@@ -794,14 +795,14 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
   data->DecodePointersAndHandles(&handles);
 
-  ObjectUnionPtr obj2;
-  Deserialize_(data, &obj2);
+  ObjectUnionPtr obj2 = ObjectUnion::New();
+  Deserialize_(data, obj2.get());
 
   EXPECT_EQ(8, obj2->get_f_array_int8()[0]);
   EXPECT_EQ(9, obj2->get_f_array_int8()[1]);
@@ -820,7 +821,7 @@
   size_t size = GetSerializedSize_(obj, false);
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -861,14 +862,14 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
   data->DecodePointersAndHandles(&handles);
 
-  ObjectUnionPtr obj2;
-  Deserialize_(data, &obj2);
+  ObjectUnionPtr obj2 = ObjectUnion::New();
+  Deserialize_(data, obj2.get());
 
   EXPECT_EQ(1, obj2->get_f_map_int8()["one"]);
   EXPECT_EQ(2, obj2->get_f_map_int8()["two"]);
@@ -888,7 +889,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -925,14 +926,14 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
   data->DecodePointersAndHandles(&handles);
 
-  ObjectUnionPtr obj2;
-  Deserialize_(data, &obj2);
+  ObjectUnionPtr obj2 = ObjectUnion::New();
+  Deserialize_(data, obj2.get());
   EXPECT_EQ(10, obj2->get_f_pod_union()->get_f_int8());
 }
 
@@ -949,7 +950,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -973,7 +974,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  SerializeUnion_(obj.Pass(), &buf, &data, false);
+  SerializeUnion_(obj.get(), &buf, &data, false);
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
 
@@ -1017,7 +1018,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::HandleUnion_Data* data = nullptr;
-  SerializeUnion_(handle.Pass(), &buf, &data, false);
+  SerializeUnion_(handle.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -1025,7 +1026,7 @@
   data->DecodePointersAndHandles(&handles);
 
   HandleUnionPtr handle2(HandleUnion::New());
-  Deserialize_(data, &handle2);
+  Deserialize_(data, handle2.get());
 
   std::string golden("hello world");
   WriteTextMessage(pipe0.get(), golden);
@@ -1051,7 +1052,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::HandleUnion_Data* data = nullptr;
-  SerializeUnion_(handle.Pass(), &buf, &data, false);
+  SerializeUnion_(handle.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -1075,7 +1076,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::HandleUnion_Data* data = nullptr;
-  SerializeUnion_(handle.Pass(), &buf, &data, false);
+  SerializeUnion_(handle.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -1132,7 +1133,7 @@
 
   mojo::internal::FixedBufferForTesting buf(size);
   internal::HandleUnion_Data* data = nullptr;
-  SerializeUnion_(handle.Pass(), &buf, &data, false);
+  SerializeUnion_(handle.get(), &buf, &data, false);
 
   std::vector<Handle> handles;
   data->EncodePointersAndHandles(&handles);
@@ -1140,7 +1141,7 @@
   data->DecodePointersAndHandles(&handles);
 
   HandleUnionPtr handle2(HandleUnion::New());
-  Deserialize_(data, &handle2);
+  Deserialize_(data, handle2.get());
 
   handle2->get_f_small_cache()->SetIntValue(10);
   run_loop.RunUntilIdle();
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
index a06d849..96e7662 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -8,7 +8,7 @@
 
 {%- macro alloc_params(struct) %}
 {%-   for param in struct.packed.packed_fields_in_ordinal_order %}
-  {{param.field.kind|cpp_result_type}} p_{{param.field.name}}{};
+  {{param.field.kind|cpp_result_type}} p_{{param.field.name}} {};
 {%-   endfor %}
   {{struct_macros.deserialize(struct, "params", "p_%s")}}
 {%- endmacro %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
index 48b76e5..25a3ee4 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -16,6 +16,10 @@
 {%-   for pf in struct.packed.packed_fields_in_ordinal_order if pf.field.kind|is_object_kind %}
 {%-     if pf.field.kind|is_union_kind %}
   size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}}, true);
+{%-     elif pf.field.kind|is_struct_kind %}
+  size += {{input_field_pattern|format(pf.field.name)}}.is_null()
+              ? 0
+              : GetSerializedSize_(*{{input_field_pattern|format(pf.field.name)}});
 {%-     else %}
   size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}});
 {%-     endif %}
@@ -47,19 +51,21 @@
 {%-     if kind|is_array_kind %}
   const mojo::internal::ArrayValidateParams {{name}}_validate_params(
       {{kind|get_array_validate_params_ctor_args|indent(10)}});
-  mojo::SerializeArray_(mojo::internal::Forward({{input_field}}), {{buffer}},
+  mojo::SerializeArray_(&{{input_field}}, {{buffer}},
       &{{output}}->{{name}}.ptr, &{{name}}_validate_params);
 {%-     elif kind|is_map_kind %}
   const mojo::internal::ArrayValidateParams {{name}}_validate_params(
       {{kind.value_kind|get_map_validate_params_ctor_args|indent(10)}});
   mojo::SerializeMap_(
-      mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr,
+      &{{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr,
       &{{name}}_validate_params);
 {%-     elif kind|is_union_kind %}
   internal::{{kind.name}}_Data* {{name}}_ptr = &{{output}}->{{name}};
-  SerializeUnion_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{name}}_ptr, true);
+  SerializeUnion_({{input_field}}.get(), {{buffer}}, &{{name}}_ptr, true);
+{%-     elif kind|is_string_kind %}
+  SerializeString_({{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr);
 {%-     else %}
-  Serialize_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr);
+  Serialize_({{input_field}}.get(), {{buffer}}, &{{output}}->{{name}}.ptr);
 {%-     endif %}
 {%-     if not kind|is_nullable_kind %}
   MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
@@ -126,8 +132,15 @@
 {%-     endif %}
 {%-     if kind|is_object_kind %}
 {%-       if kind|is_union_kind %}
-    Deserialize_(&{{input}}->{{name}}, &{{output_field}});
+    {{output_field}} = {{kind|get_name_for_kind}}::New();
+    Deserialize_(&{{input}}->{{name}}, {{output_field}}.get());
+{%-       elif kind|is_struct_kind %}
+    if ({{input}}->{{name}}.ptr) {
+      {{output_field}} = {{kind|get_name_for_kind}}::New();
+      Deserialize_({{input}}->{{name}}.ptr, {{output_field}}.get());
+    }
 {%-       else %}
+{#- Arrays and Maps #}
     Deserialize_({{input}}->{{name}}.ptr, &{{output_field}});
 {%-       endif %}
 {%-     elif kind|is_interface_kind %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
index 604be86..6243372 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
@@ -1,5 +1,5 @@
-size_t GetSerializedSize_(const {{struct.name}}Ptr& input);
-void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buffer,
+size_t GetSerializedSize_(const {{struct.name}}& input);
+void Serialize_({{struct.name}}* input, mojo::internal::Buffer* buffer,
                 internal::{{struct.name}}_Data** output);
 void Deserialize_(internal::{{struct.name}}_Data* input,
-                  {{struct.name}}Ptr* output);
+                  {{struct.name}}* output);
\ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
index fe25553..eb6fcec 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
@@ -1,12 +1,10 @@
 {%- import "struct_macros.tmpl" as struct_macros %}
-size_t GetSerializedSize_(const {{struct.name}}Ptr& input) {
-  if (!input)
-    return 0;
-  {{struct_macros.get_serialized_size(struct, "input->%s")}}
+size_t GetSerializedSize_(const {{struct.name}}& input) {
+  {{struct_macros.get_serialized_size(struct, "input.%s")}}
   return size;
 }
 
-void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buf,
+void Serialize_({{struct.name}}* input, mojo::internal::Buffer* buf,
                 internal::{{struct.name}}_Data** output) {
   if (input) {
     {{struct_macros.serialize(struct, struct.name ~ " struct", "input->%s", "result", "buf")|indent(2)}}
@@ -17,12 +15,8 @@
 }
 
 void Deserialize_(internal::{{struct.name}}_Data* input,
-                  {{struct.name}}Ptr* output) {
+                  {{struct.name}}* result) {
   if (input) {
-    {{struct.name}}Ptr result({{struct.name}}::New());
     {{struct_macros.deserialize(struct, "input", "result->%s")|indent(2)}}
-    *output = result.Pass();
-  } else {
-    output->reset();
   }
 }
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
index 404eb83..588e749 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
@@ -1,5 +1,5 @@
 size_t GetSerializedSize_(const {{union.name}}Ptr& input, bool inlined);
-void SerializeUnion_({{union.name}}Ptr input, mojo::internal::Buffer* buffer,
-                     internal::{{union.name}}_Data** output, bool inlined);
+void SerializeUnion_({{union.name}}* input, mojo::internal::Buffer* buffer,
+                         internal::{{union.name}}_Data** output, bool inlined);
 void Deserialize_(internal::{{union.name}}_Data* input,
-                  {{union.name}}Ptr* output);
+                  {{union.name}}* output);
\ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
index 918e460..53b2126 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
@@ -14,6 +14,8 @@
     case {{union.name}}::Tag::{{field.name|upper}}:
 {%      if field.kind|is_union_kind %}
       size += GetSerializedSize_(*(input_acc.data()->{{field.name}}), false);
+{%      elif field.kind|is_struct_kind %}
+      size += GetSerializedSize_(*(input_acc.data()->{{field.name}}->get()));
 {%      else %}
       size += GetSerializedSize_(*(input_acc.data()->{{field.name}}));
 {%      endif %}
@@ -26,14 +28,14 @@
   return size;
 }
 
-void SerializeUnion_({{union.name}}Ptr input, mojo::internal::Buffer* buf,
+void SerializeUnion_({{union.name}}* input, mojo::internal::Buffer* buf,
                      internal::{{union.name}}_Data** output, bool inlined) {
   internal::{{union.name}}_Data* result = *output;
   if (input) {
     if (!inlined) {
       result = internal::{{union.name}}_Data::New(buf);
     }
-    mojo::internal::UnionAccessor<{{union.name}}> input_acc(input.get());
+    mojo::internal::UnionAccessor<{{union.name}}> input_acc(input);
     // TODO(azani): Handle unknown and objects.
     // Set the not-null flag.
     result->size = 16;
@@ -43,28 +45,28 @@
       case {{union.name}}::Tag::{{field.name|upper}}: {
 {%    if field.kind|is_object_kind %}
 {%      if field.kind|is_string_kind %}
-        Serialize_(
-            *(input_acc.data()->{{field.name}}),
+        SerializeString_(
+            *input_acc.data()->{{field.name}},
             buf, &result->data.f_{{field.name}}.ptr);
 {%      elif field.kind|is_struct_kind %}
         Serialize_(
-            mojo::internal::Forward(*(input_acc.data()->{{field.name}})),
+            input_acc.data()->{{field.name}}->get(),
             buf, &result->data.f_{{field.name}}.ptr);
 {%      elif field.kind|is_union_kind %}
         SerializeUnion_(
-            mojo::internal::Forward(*(input_acc.data()->{{field.name}})),
+            input_acc.data()->{{field.name}}->get(),
             buf, &result->data.f_{{field.name}}.ptr, false);
 {%      elif field.kind|is_array_kind %}
         const mojo::internal::ArrayValidateParams {{field.name}}_validate_params(
             {{field.kind|get_array_validate_params_ctor_args|indent(16)}});
         SerializeArray_(
-            mojo::internal::Forward(*(input_acc.data()->{{field.name}})),
+            input_acc.data()->{{field.name}},
             buf, &result->data.f_{{field.name}}.ptr, &{{field.name}}_validate_params);
 {%      elif field.kind|is_map_kind %}
         const mojo::internal::ArrayValidateParams {{field.name}}_validate_params(
             {{field.kind.value_kind|get_map_validate_params_ctor_args|indent(16)}});
         SerializeMap_(
-            mojo::internal::Forward(*(input_acc.data()->{{field.name}})),
+            input_acc.data()->{{field.name}},
             buf, &result->data.f_{{field.name}}.ptr, &{{field.name}}_validate_params);
 {%-     endif %}
 {%    elif field.kind|is_any_handle_kind %}
@@ -95,20 +97,28 @@
 }
 
 void Deserialize_(internal::{{union.name}}_Data* input,
-                  {{union.name}}Ptr* output) {
+                  {{union.name}}* output) {
   if (input && !input->is_null()) {
-    {{union.name}}Ptr result({{union.name}}::New());
-    mojo::internal::UnionAccessor<{{union.name}}> result_acc(result.get());
+    mojo::internal::UnionAccessor<{{union.name}}> result_acc(output);
     switch (input->tag) {
+{#- TODO(vardhan):  There is a lot of overlap with struct_macros.deserialize()
+    here, is it possible to merge? (currently looks very hairy) #}
 {%  for field in union.fields %}
       case {{union.name}}::Tag::{{field.name|upper}}: {
 {%    if field.kind|is_object_kind %}
         result_acc.SwitchActive({{union.name}}::Tag::{{field.name|upper}});
+{%      if field.kind|is_struct_kind or field.kind|is_union_kind %}
+        *result_acc.data()->{{field.name}} =
+            {{field.kind|get_name_for_kind}}::New();
+        Deserialize_(input->data.f_{{field.name}}.ptr,
+            result_acc.data()->{{field.name}}->get());
+{%      else %}
         Deserialize_(input->data.f_{{field.name}}.ptr, result_acc.data()->{{field.name}});
+{%      endif %}
 {%    elif field.kind|is_any_handle_kind %}
         {{field.kind|cpp_wrapper_type}}* {{field.name}} =
             reinterpret_cast<{{field.kind|cpp_wrapper_type}}*>(&input->data.f_{{field.name}});
-        result->set_{{field.name}}({{field.name}}->Pass());
+        output->set_{{field.name}}({{field.name}}->Pass());
 {%    elif field.kind|is_interface_kind %}
         {{field.kind|cpp_wrapper_type}} {{field.name}}_out;
         mojo::internal::Interface_Data* {{field.name}}_in =
@@ -116,11 +126,11 @@
                 &input->data.f_{{field.name}});
         mojo::internal::InterfaceDataToPointer(
             {{field.name}}_in, &{{field.name}}_out);
-        result->set_{{field.name}}({{field.name}}_out.Pass());
+        output->set_{{field.name}}({{field.name}}_out.Pass());
 {%    elif field.kind|is_enum_kind %}
-        result->set_{{field.name}}(static_cast<{{field.kind|cpp_wrapper_type}}>(input->data.f_{{field.name}}));
+        output->set_{{field.name}}(static_cast<{{field.kind|cpp_wrapper_type}}>(input->data.f_{{field.name}}));
 {%    else %}
-        result->set_{{field.name}}(input->data.f_{{field.name}});
+        output->set_{{field.name}}(input->data.f_{{field.name}});
 {%-   endif %}
         break;
       }
@@ -130,8 +140,5 @@
         // No way to deserialize the data when we encounter an unknown tag.
         break;
     }
-    *output = result.Pass();
-  } else {
-    output->reset();
   }
-}
+}
\ No newline at end of file
diff --git a/services/url_response_disk_cache/url_response_disk_cache_db.cc b/services/url_response_disk_cache/url_response_disk_cache_db.cc
index 1991b62..f7eb587 100644
--- a/services/url_response_disk_cache/url_response_disk_cache_db.cc
+++ b/services/url_response_disk_cache/url_response_disk_cache_db.cc
@@ -28,7 +28,7 @@
 template <typename T>
 void Serialize(T input, std::string* output) {
   typedef typename mojo::internal::WrapperTraits<T>::DataType DataType;
-  size_t size = GetSerializedSize_(input);
+  size_t size = GetSerializedSize_(*input);
 
   output->clear();
   output->resize(size);
@@ -37,7 +37,7 @@
   buf.Initialize(&output->at(0), size);
 
   DataType data_type;
-  Serialize_(input.Pass(), &buf, &data_type);
+  Serialize_(input.get(), &buf, &data_type);
   std::vector<Handle> handles;
   data_type->EncodePointersAndHandles(&handles);
 }
@@ -52,7 +52,8 @@
   DataType data_type = reinterpret_cast<DataType>(data);
   std::vector<Handle> handles;
   data_type->DecodePointersAndHandles(&handles);
-  Deserialize_(data_type, output);
+  *output = mojo::internal::RemoveStructPtr<T>::type::New();
+  Deserialize_(data_type, output->get());
   return true;
 }