• 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 namespace mojo {
9 
10 // This must be specialized for any type |T| to be serialized/deserialized as
11 // a mojom struct of type |MojomType|.
12 //
13 // Each specialization needs to implement a few things:
14 //   1. Static getters for each field in the Mojom type. These should be
15 //      of the form:
16 //
17 //        static <return type> <field name>(const T& input);
18 //
19 //      and should return a serializable form of the named field as extracted
20 //      from |input|.
21 //
22 //      Serializable form of a field:
23 //        Value or reference of the same type used in |MojomType|, or the
24 //        following alternatives:
25 //        - string:
26 //          Value or reference of any type that has a StringTraits defined.
27 //          Supported by default: base::StringPiece, std::string.
28 //
29 //        - array:
30 //          Value or reference of any type that has an ArrayTraits defined.
31 //          Supported by default: std::vector, WTF::Vector (in blink), CArray.
32 //
33 //        - map:
34 //          Value or reference of any type that has a MapTraits defined.
35 //          Supported by default: std::map.
36 //
37 //        - struct:
38 //          Value or reference of any type that has a StructTraits defined.
39 //
40 //        - enum:
41 //          Value of any type that has an EnumTraits defined.
42 //
43 //      During serialization, getters for string/struct/array/map/union fields
44 //      are called twice (one for size calculation and one for actual
45 //      serialization). If you want to return a value (as opposed to a
46 //      reference) from these getters, you have to be sure that constructing and
47 //      copying the returned object is really cheap.
48 //
49 //      Getters for fields of other types are called once.
50 //
51 //   2. A static Read() method to set the contents of a |T| instance from a
52 //      |MojomType|DataView (e.g., if |MojomType| is test::Example, the data
53 //      view will be test::ExampleDataView).
54 //
55 //        static bool Read(|MojomType|DataView data, T* output);
56 //
57 //      The generated |MojomType|DataView type provides a convenient,
58 //      inexpensive view of a serialized struct's field data.
59 //
60 //      Returning false indicates invalid incoming data and causes the message
61 //      pipe receiving it to be disconnected. Therefore, you can do custom
62 //      validation for |T| in this method.
63 //
64 //   3. [Optional] A static IsNull() method indicating whether a given |T|
65 //      instance is null:
66 //
67 //        static bool IsNull(const T& input);
68 //
69 //      If this method returns true, it is guaranteed that none of the getters
70 //      (described in section 1) will be called for the same |input|. So you
71 //      don't have to check whether |input| is null in those getters.
72 //
73 //      If it is not defined, |T| instances are always considered non-null.
74 //
75 //      [Optional] A static SetToNull() method to set the contents of a given
76 //      |T| instance to null.
77 //
78 //        static void SetToNull(T* output);
79 //
80 //      When a null serialized struct is received, the deserialization code
81 //      calls this method instead of Read().
82 //
83 //      NOTE: It is to set |*output|'s contents to a null state, not to set the
84 //      |output| pointer itself to null. "Null state" means whatever state you
85 //      think it makes sense to map a null serialized struct to.
86 //
87 //      If it is not defined, null is not allowed to be converted to |T|. In
88 //      that case, an incoming null value is considered invalid and causes the
89 //      message pipe to be disconnected.
90 //
91 //   4. [Optional] As mentioned above, getters for string/struct/array/map/union
92 //      fields are called multiple times (twice to be exact). If you need to do
93 //      some expensive calculation/conversion, you probably want to cache the
94 //      result across multiple calls. You can introduce an arbitrary context
95 //      object by adding two optional methods:
96 //        static void* SetUpContext(const T& input);
97 //        static void TearDownContext(const T& input, void* context);
98 //
99 //      And then you append a second parameter, void* context, to getters:
100 //        static <return type> <field name>(const T& input, void* context);
101 //
102 //      If a T instance is not null, the serialization code will call
103 //      SetUpContext() at the beginning, and pass the resulting context pointer
104 //      to getters. After serialization is done, it calls TearDownContext() so
105 //      that you can do any necessary cleanup.
106 //
107 // In the description above, methods having an |input| parameter define it as
108 // const reference of T. Actually, it can be a non-const reference of T too.
109 // E.g., if T contains Mojo handles or interfaces whose ownership needs to be
110 // transferred. Correspondingly, it requies you to always give non-const T
111 // reference/value to the Mojo bindings for serialization:
112 //    - if T is used in the "type_mappings" section of a typemap config file,
113 //      you need to declare it as pass-by-value:
114 //        type_mappings = [ "MojomType=T(pass_by_value)" ]
115 //    - if another type U's StructTraits has a getter for T, it needs to return
116 //      non-const reference/value.
117 //
118 // EXAMPLE:
119 //
120 // Mojom definition:
121 //   struct Bar {};
122 //   struct Foo {
123 //     int32 f_integer;
124 //     string f_string;
125 //     array<string> f_string_array;
126 //     Bar f_bar;
127 //   };
128 //
129 // StructTraits for Foo:
130 //   template <>
131 //   struct StructTraits<Foo, CustomFoo> {
132 //     // Optional methods dealing with null:
133 //     static bool IsNull(const CustomFoo& input);
134 //     static void SetToNull(CustomFoo* output);
135 //
136 //     // Field getters:
137 //     static int32_t f_integer(const CustomFoo& input);
138 //     static const std::string& f_string(const CustomFoo& input);
139 //     static const std::vector<std::string>& f_string_array(
140 //         const CustomFoo& input);
141 //     // Assuming there is a StructTraits<Bar, CustomBar> defined.
142 //     static const CustomBar& f_bar(const CustomFoo& input);
143 //
144 //     static bool Read(FooDataView data, CustomFoo* output);
145 //   };
146 //
147 template <typename MojomType, typename T>
148 struct StructTraits;
149 
150 }  // namespace mojo
151 
152 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_
153