Home | History | Annotate | Download | only in bindings
      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