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