• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_
7 
8 #include "mojo/public/cpp/bindings/lib/template_util.h"
9 
10 namespace mojo {
11 
12 // This must be specialized for any type |T| to be serialized/deserialized as
13 // a mojom struct. |DataViewType| is the corresponding data view type of the
14 // mojom struct. For example, if the mojom struct is example.Foo,
15 // |DataViewType| will be example::FooDataView, which can also be referred to by
16 // example::Foo::DataView (in chromium) and example::blink::Foo::DataView (in
17 // blink).
18 //
19 // Each specialization needs to implement a few things:
20 //   1. Static getters for each field in the Mojom type. These should be
21 //      of the form:
22 //
23 //        static <return type> <field name>(const T& input);
24 //
25 //      and should return a serializable form of the named field as extracted
26 //      from |input|.
27 //
28 //      Serializable form of a field:
29 //        Value or reference of the same type used in the generated stuct
30 //        wrapper type, or the following alternatives:
31 //        - string:
32 //          Value or reference of any type that has a StringTraits defined.
33 //          Supported by default: base::StringPiece, std::string,
34 //          WTF::String (in blink).
35 //
36 //        - array:
37 //          Value or reference of any type that has an ArrayTraits defined.
38 //          Supported by default: std::vector, CArray, WTF::Vector (in blink)
39 //
40 //        - map:
41 //          Value or reference of any type that has a MapTraits defined.
42 //          Supported by default: std::map, std::unordered_map, base::flat_map,
43 //          WTF::HashMap (in blink).
44 //
45 //        - struct:
46 //          Value or reference of any type that has a StructTraits defined.
47 //
48 //        - enum:
49 //          Value of any type that has an EnumTraits defined.
50 //
51 //      For any nullable string/struct/array/map/union field you could also
52 //      return value or reference of base::Optional<T>, if T has the right
53 //      *Traits defined.
54 //
55 //      During serialization, getters for all fields are called exactly once. It
56 //      is therefore reasonably effecient for a getter to construct and return
57 //      temporary value in the event that it cannot return a readily
58 //      serializable reference to some existing object.
59 //
60 //   2. A static Read() method to set the contents of a |T| instance from a
61 //      DataViewType.
62 //
63 //        static bool Read(DataViewType data, T* output);
64 //
65 //      The generated DataViewType provides a convenient, inexpensive view of a
66 //      serialized struct's field data. The caller guarantees that
67 //      |!data.is_null()|.
68 //
69 //      Returning false indicates invalid incoming data and causes the message
70 //      pipe receiving it to be disconnected. Therefore, you can do custom
71 //      validation for |T| in this method.
72 //
73 //   3. [Optional] A static IsNull() method indicating whether a given |T|
74 //      instance is null:
75 //
76 //        static bool IsNull(const T& input);
77 //
78 //      This method is called exactly once during serialization, and if it
79 //      returns |true|, it is guaranteed that none of the getters (described in
80 //      section 1) will be called for the same |input|. So you don't have to
81 //      check whether |input| is null in those getters.
82 //
83 //      If it is not defined, |T| instances are always considered non-null.
84 //
85 //      [Optional] A static SetToNull() method to set the contents of a given
86 //      |T| instance to null.
87 //
88 //        static void SetToNull(T* output);
89 //
90 //      When a null serialized struct is received, the deserialization code
91 //      calls this method instead of Read().
92 //
93 //      NOTE: It is to set |*output|'s contents to a null state, not to set the
94 //      |output| pointer itself to null. "Null state" means whatever state you
95 //      think it makes sense to map a null serialized struct to.
96 //
97 //      If it is not defined, null is not allowed to be converted to |T|. In
98 //      that case, an incoming null value is considered invalid and causes the
99 //      message pipe to be disconnected.
100 //
101 //   4. [Optional] As mentioned above, getters for string/struct/array/map/union
102 //      fields are called multiple times (twice to be exact). If you need to do
103 //      some expensive calculation/conversion, you probably want to cache the
104 //      result across multiple calls. You can introduce an arbitrary context
105 //      object by adding two optional methods:
106 //        static void* SetUpContext(const T& input);
107 //        static void TearDownContext(const T& input, void* context);
108 //
109 //      And then you append a second parameter, void* context, to getters:
110 //        static <return type> <field name>(const T& input, void* context);
111 //
112 //      If a T instance is not null, the serialization code will call
113 //      SetUpContext() at the beginning, and pass the resulting context pointer
114 //      to getters. After serialization is done, it calls TearDownContext() so
115 //      that you can do any necessary cleanup.
116 //
117 // In the description above, methods having an |input| parameter define it as
118 // const reference of T. Actually, it can be a non-const reference of T too.
119 // E.g., if T contains Mojo handles or interfaces whose ownership needs to be
120 // transferred. Correspondingly, it requies you to always give non-const T
121 // reference/value to the Mojo bindings for serialization:
122 //    - if T is used in the "type_mappings" section of a typemap config file,
123 //      you need to declare it as pass-by-value:
124 //        type_mappings = [ "MojomType=T[move_only]" ]
125 //      or
126 //        type_mappings = [ "MojomType=T[copyable_pass_by_value]" ]
127 //
128 //    - if another type U's StructTraits/UnionTraits has a getter for T, it
129 //      needs to return non-const reference/value.
130 //
131 // EXAMPLE:
132 //
133 // Mojom definition:
134 //   struct Bar {};
135 //   struct Foo {
136 //     int32 f_integer;
137 //     string f_string;
138 //     array<string> f_string_array;
139 //     Bar f_bar;
140 //   };
141 //
142 // StructTraits for Foo:
143 //   template <>
144 //   struct StructTraits<FooDataView, CustomFoo> {
145 //     // Optional methods dealing with null:
146 //     static bool IsNull(const CustomFoo& input);
147 //     static void SetToNull(CustomFoo* output);
148 //
149 //     // Field getters:
150 //     static int32_t f_integer(const CustomFoo& input);
151 //     static const std::string& f_string(const CustomFoo& input);
152 //     static const std::vector<std::string>& f_string_array(
153 //         const CustomFoo& input);
154 //     // Assuming there is a StructTraits<Bar, CustomBar> defined.
155 //     static const CustomBar& f_bar(const CustomFoo& input);
156 //
157 //     static bool Read(FooDataView data, CustomFoo* output);
158 //   };
159 //
160 template <typename DataViewType, typename T>
161 struct StructTraits {
162   static_assert(internal::AlwaysFalse<T>::value,
163                 "Cannot find the mojo::StructTraits specialization. Did you "
164                 "forget to include the corresponding header file?");
165 };
166 
167 }  // namespace mojo
168 
169 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_
170