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
8namespace 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//
147template <typename MojomType, typename T>
148struct StructTraits;
149
150}  // namespace mojo
151
152#endif  // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_
153