| Index: mojo/public/cpp/bindings/lib/serialization_forward.h | 
| diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h | 
| index 7f73932c85f44edbd5f1321026a462f908c9b789..5bed126da59282d01fee9f50fd3ffe6d012af215 100644 | 
| --- a/mojo/public/cpp/bindings/lib/serialization_forward.h | 
| +++ b/mojo/public/cpp/bindings/lib/serialization_forward.h | 
| @@ -5,8 +5,10 @@ | 
| #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ | 
| #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ | 
|  | 
| +#include "base/optional.h" | 
| #include "mojo/public/cpp/bindings/array_traits.h" | 
| #include "mojo/public/cpp/bindings/enum_traits.h" | 
| +#include "mojo/public/cpp/bindings/lib/template_util.h" | 
| #include "mojo/public/cpp/bindings/map_traits.h" | 
| #include "mojo/public/cpp/bindings/string_traits.h" | 
| #include "mojo/public/cpp/bindings/struct_traits.h" | 
| @@ -22,11 +24,23 @@ namespace internal { | 
| template <typename MojomType, typename MaybeConstUserType> | 
| struct Serializer; | 
|  | 
| +template <typename T> | 
| +struct IsOptionalWrapper { | 
| +  static const bool value = IsSpecializationOf< | 
| +      base::Optional, | 
| +      typename std::remove_const< | 
| +          typename std::remove_reference<T>::type>::type>::value; | 
| +}; | 
| + | 
| // PrepareToSerialize() must be matched by a Serialize() for the same input | 
| // later. Moreover, within the same SerializationContext if PrepareToSerialize() | 
| // is called for |input_1|, ..., |input_n|, Serialize() must be called for | 
| // those objects in the exact same order. | 
| -template <typename MojomType, typename InputUserType, typename... Args> | 
| +template <typename MojomType, | 
| +          typename InputUserType, | 
| +          typename... Args, | 
| +          typename std::enable_if< | 
| +              !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> | 
| size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { | 
| return Serializer<MojomType, | 
| typename std::remove_reference<InputUserType>::type>:: | 
| @@ -34,7 +48,11 @@ size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { | 
| std::forward<Args>(args)...); | 
| } | 
|  | 
| -template <typename MojomType, typename InputUserType, typename... Args> | 
| +template <typename MojomType, | 
| +          typename InputUserType, | 
| +          typename... Args, | 
| +          typename std::enable_if< | 
| +              !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> | 
| void Serialize(InputUserType&& input, Args&&... args) { | 
| Serializer<MojomType, typename std::remove_reference<InputUserType>::type>:: | 
| Serialize(std::forward<InputUserType>(input), | 
| @@ -44,12 +62,60 @@ void Serialize(InputUserType&& input, Args&&... args) { | 
| template <typename MojomType, | 
| typename DataType, | 
| typename InputUserType, | 
| -          typename... Args> | 
| +          typename... Args, | 
| +          typename std::enable_if< | 
| +              !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> | 
| bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { | 
| return Serializer<MojomType, InputUserType>::Deserialize( | 
| std::forward<DataType>(input), output, std::forward<Args>(args)...); | 
| } | 
|  | 
| +// Specialization that unwraps base::Optional<>. | 
| +template <typename MojomType, | 
| +          typename InputUserType, | 
| +          typename... Args, | 
| +          typename std::enable_if< | 
| +              IsOptionalWrapper<InputUserType>::value>::type* = nullptr> | 
| +size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { | 
| +  if (!input) | 
| +    return 0; | 
| +  return PrepareToSerialize<MojomType>(*input, std::forward<Args>(args)...); | 
| +} | 
| + | 
| +template <typename MojomType, | 
| +          typename InputUserType, | 
| +          typename DataType, | 
| +          typename... Args, | 
| +          typename std::enable_if< | 
| +              IsOptionalWrapper<InputUserType>::value>::type* = nullptr> | 
| +void Serialize(InputUserType&& input, | 
| +               Buffer* buffer, | 
| +               DataType** output, | 
| +               Args&&... args) { | 
| +  if (!input) { | 
| +    *output = nullptr; | 
| +    return; | 
| +  } | 
| +  Serialize<MojomType>(*input, buffer, output, std::forward<Args>(args)...); | 
| +} | 
| + | 
| +template <typename MojomType, | 
| +          typename DataType, | 
| +          typename InputUserType, | 
| +          typename... Args, | 
| +          typename std::enable_if< | 
| +              IsOptionalWrapper<InputUserType>::value>::type* = nullptr> | 
| +bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { | 
| +  if (!input) { | 
| +    *output = base::nullopt; | 
| +    return true; | 
| +  } | 
| +  if (!*output) | 
| +    output->emplace(); | 
| +  return Deserialize<MojomType>(std::forward<DataType>(input), &output->value(), | 
| +                                std::forward<Args>(args)...); | 
| +} | 
| + | 
| }  // namespace internal | 
| }  // namespace mojo | 
|  | 
|  |