OLD | NEW |
1 {# TODO(yzshen): Make these templates more readable. #} | 1 {# TODO(yzshen): Consider merging the template code for user-defined and |
| 2 parameter data structs. That way we can eliminate validate(), fields(), |
| 3 encodes() and decodes(). #} |
| 4 |
| 5 {# Validates the specified struct field, which is supposed to be an object |
| 6 (struct/array/string/map/union). |
| 7 This macro is expanded by the validate() macro. #} |
| 8 {%- macro _validate_object(struct, packed_field) %} |
| 9 {%- set name = packed_field.field.name %} |
| 10 {%- set kind = packed_field.field.kind %} |
| 11 {%- set wrapper_type = kind|cpp_wrapper_type %} |
| 12 {%- if not kind|is_nullable_kind %} |
| 13 {%- if kind|is_union_kind %} |
| 14 if (object->{{name}}.is_null()) { |
| 15 {%- else %} |
| 16 if (!object->{{name}}.offset) { |
| 17 {%- endif %} |
| 18 ReportValidationError( |
| 19 mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
| 20 "null {{name}} field in {{struct.name}} struct"); |
| 21 return false; |
| 22 } |
| 23 {%- endif %} |
| 24 {%- if not kind|is_union_kind %} |
| 25 if (!mojo::internal::ValidateEncodedPointer(&object->{{name}}.offset)) { |
| 26 ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER); |
| 27 return false; |
| 28 } |
| 29 {%- endif %} |
| 30 {%- if kind|is_array_kind or kind|is_string_kind %} |
| 31 if (!{{wrapper_type}}::Data_::Validate< |
| 32 {{kind|get_array_validate_params|indent(10)}}>( |
| 33 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), |
| 34 bounds_checker)) { |
| 35 {%- elif kind|is_map_kind %} |
| 36 if (!{{wrapper_type}}::Data_::Validate< |
| 37 {{kind.value_kind|get_map_validate_params|indent(10)}}>( |
| 38 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), |
| 39 bounds_checker)) { |
| 40 {%- elif kind|is_struct_kind %} |
| 41 if (!{{kind|get_name_for_kind}}::Data_::Validate( |
| 42 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), |
| 43 bounds_checker)) { |
| 44 {%- elif kind|is_union_kind %} |
| 45 // We already claimed the union's memory as part of the struct, so we don't |
| 46 // try to claim the union's memory when validating the union. |
| 47 if (!{{kind.name}}::Data_::Validate(&object->{{name}}, bounds_checker, true))
{ |
| 48 {%- else %} |
| 49 if (!{{wrapper_type}}::Data_::Validate( |
| 50 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), |
| 51 bounds_checker)) { |
| 52 {%- endif %} |
| 53 return false; |
| 54 } |
| 55 {%- endmacro %} |
| 56 |
| 57 {# Validates the specified struct field, which is supposed to be a handle. |
| 58 This macro is expanded by the validate() macro. #} |
| 59 {%- macro _validate_handle(struct, packed_field) %} |
| 60 {%- set name = packed_field.field.name %} |
| 61 {%- set kind = packed_field.field.kind %} |
| 62 {%- if not kind|is_nullable_kind %} |
| 63 if (object->{{name}}.value() == mojo::internal::kEncodedInvalidHandleValue) { |
| 64 ReportValidationError( |
| 65 mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, |
| 66 "invalid {{name}} field in {{struct.name}} struct"); |
| 67 return false; |
| 68 } |
| 69 {%- endif %} |
| 70 if (!bounds_checker->ClaimHandle(object->{{name}})) { |
| 71 ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_HANDLE); |
| 72 return false; |
| 73 } |
| 74 {%- endmacro %} |
| 75 |
| 76 {# Validates the specified struct. |
| 77 This macro is expanded as the body of {{struct.name}}_Data::Validate(). #} |
| 78 {%- macro validate(struct) %} |
| 79 if (!data) |
| 80 return true; |
| 81 |
| 82 if (!ValidateStructHeaderAndClaimMemory(data, bounds_checker)) |
| 83 return false; |
| 84 |
| 85 // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if |
| 86 // the message comes from an older version. |
| 87 const {{struct.name}}_Data* object = static_cast<const {{struct.name}}_Data*>(
data); |
| 88 |
| 89 static const uint32_t kVersionSizePairs[{{struct.versions|length}}][2] = { |
| 90 {%- for version in struct.versions -%} |
| 91 { {{version.version}}, {{version.num_bytes}} }{% if not loop.last %}, {% end
if -%} |
| 92 {%- endfor -%} |
| 93 }; |
| 94 |
| 95 if (object->header_.version <= {{struct.versions[-1].version}}) { |
| 96 for (size_t i = 0; i < {{struct.versions|length}}; ++i) { |
| 97 if (object->header_.version <= kVersionSizePairs[i][0]) { |
| 98 if (object->header_.num_bytes == kVersionSizePairs[i][1]) |
| 99 break; |
| 100 |
| 101 ReportValidationError( |
| 102 mojo::internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
| 103 return false; |
| 104 } |
| 105 } |
| 106 } else if (object->header_.num_bytes < {{struct.versions[-1].num_bytes}}) { |
| 107 ReportValidationError( |
| 108 mojo::internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
| 109 return false; |
| 110 } |
| 111 |
| 112 {#- Before validating fields introduced at a certain version, we need to add |
| 113 a version check, which makes sure we skip further validation if |object| |
| 114 is from an earlier version. |last_checked_version| records the last |
| 115 version that we have added such version check. #} |
| 116 {%- set last_checked_version = 0 %} |
| 117 {%- for packed_field in struct.packed.packed_fields_in_ordinal_order %} |
| 118 {%- set kind = packed_field.field.kind %} |
| 119 {%- if kind|is_object_kind or kind|is_any_handle_kind %} |
| 120 {%- if packed_field.min_version > last_checked_version %} |
| 121 {%- set last_checked_version = packed_field.min_version %} |
| 122 if (object->header_.version < {{packed_field.min_version}}) |
| 123 return true; |
| 124 {%- endif %} |
| 125 {%- if kind|is_object_kind %} |
| 126 {{_validate_object(struct, packed_field)}} |
| 127 {%- elif kind|is_any_handle_kind %} |
| 128 {{_validate_handle(struct, packed_field)}} |
| 129 {%- endif %} |
| 130 {%- endif %} |
| 131 {%- endfor %} |
| 132 |
| 133 return true; |
| 134 {%- endmacro %} |
| 135 |
| 136 {# Declares a data member for the specified struct field. |
| 137 This macro is expanded by the fields() macro. #} |
| 138 {%- macro _field_line(field) %} |
| 139 {%- set type = field.kind|cpp_field_type %} |
| 140 {%- set name = field.name -%} |
| 141 {%- if field.kind.spec == 'b' -%} |
| 142 uint8_t {{name}} : 1; |
| 143 {%- elif field.kind|is_enum_kind -%} |
| 144 int32_t {{name}}; |
| 145 {%- else -%} |
| 146 {{type}} {{name}}; |
| 147 {%- endif %} |
| 148 {%- endmacro %} |
| 149 |
| 150 {# Declares data members for the specified struct. |
| 151 This macro is expanded in the {{struct.name}}_Data class declaration. #} |
| 152 {%- macro fields(struct) %} |
| 153 {%- for packed_field in struct.packed.packed_fields %} |
| 154 {{_field_line(packed_field.field)}} |
| 155 {%- if not loop.last %} |
| 156 {%- set next_pf = struct.packed.packed_fields[loop.index0 + 1] %} |
| 157 {%- set pad = next_pf.offset - (packed_field.offset + packed_field.size) %
} |
| 158 {%- if pad > 0 %} |
| 159 uint8_t pad{{loop.index0}}_[{{pad}}]; |
| 160 {%- endif %} |
| 161 {%- endif %} |
| 162 {%- endfor -%} |
| 163 |
| 164 {%- set num_fields = struct.packed.packed_fields|length %} |
| 165 {%- if num_fields > 0 %} |
| 166 {%- set last_field = struct.packed.packed_fields[num_fields - 1] %} |
| 167 {%- set offset = last_field.offset + last_field.size %} |
| 168 {%- set pad = offset|get_pad(8) -%} |
| 169 {%- if pad > 0 %} |
| 170 uint8_t padfinal_[{{pad}}]; |
| 171 {%- endif %} |
| 172 {%- endif %} |
| 173 {%- endmacro %} |
| 174 |
| 175 {# Encodes the specified struct. |
| 176 Expands as the body of {{struct.name}}_Data::EncodePointersAndHandles(). #} |
| 177 {%- macro encodes(struct) -%} |
| 178 MOJO_CHECK(header_.version == {{struct.versions[-1].version}}); |
| 179 {%- for pf in struct.packed.packed_fields_in_ordinal_order %} |
| 180 {%- if pf.field.kind|is_object_kind %} |
| 181 {%- if pf.field.kind|is_union_kind %} |
| 182 // TODO(azani): Encode pointers and handles. |
| 183 {%- else %} |
| 184 mojo::internal::Encode(&{{pf.field.name}}, handles); |
| 185 {%- endif %} |
| 186 {%- elif pf.field.kind|is_any_handle_kind %} |
| 187 mojo::internal::EncodeHandle(&{{pf.field.name}}, handles); |
| 188 {%- endif %} |
| 189 {%- endfor %} |
| 190 {%- endmacro -%} |
| 191 |
| 192 {# Decodes the specified struct. |
| 193 This macro is expanded as the body of |
| 194 {{struct.name}}_Data:DecodePointersAndHandles(). #} |
| 195 {%- macro decodes(struct) -%} |
| 196 // NOTE: The memory backing |this| may has be smaller than |sizeof(*this)|, if |
| 197 // the message comes from an older version. |
| 198 {#- Before decoding fields introduced at a certain version, we need to add |
| 199 a version check, which makes sure we skip further decoding if |this| |
| 200 is from an earlier version. |last_checked_version| records the last |
| 201 version that we have added such version check. #} |
| 202 {%- set last_checked_version = 0 %} |
| 203 {%- for pf in struct.packed.packed_fields_in_ordinal_order %} |
| 204 {%- set name = pf.field.name %} |
| 205 {%- set kind = pf.field.kind %} |
| 206 {%- if kind|is_object_kind or kind|is_any_handle_kind %} |
| 207 {%- if pf.min_version > last_checked_version %} |
| 208 {%- set last_checked_version = pf.min_version %} |
| 209 if (header_.version < {{pf.min_version}}) |
| 210 return; |
| 211 {%- endif %} |
| 212 {%- if kind|is_object_kind %} |
| 213 {%- if pf.field.kind|is_union_kind %} |
| 214 // TODO(azani): Decode pointers and handles. |
| 215 {%- else %} |
| 216 mojo::internal::Decode(&{{name}}, handles); |
| 217 {%- endif %} |
| 218 {%- else %} |
| 219 mojo::internal::DecodeHandle(&{{name}}, handles); |
| 220 {%- endif %} |
| 221 {%- endif %} |
| 222 {%- endfor %} |
| 223 {%- endmacro -%} |
2 | 224 |
3 {# Computes the serialized size for the specified struct. | 225 {# Computes the serialized size for the specified struct. |
4 |struct| is the struct definition. | 226 |struct| is the struct definition. |
5 |input_field_pattern| should be a pattern that contains one string | 227 |input_field_pattern| should be a pattern that contains one string |
6 placeholder, for example, "input->%s", "p_%s". The placeholder will be | 228 placeholder, for example, "input->%s", "p_%s". The placeholder will be |
7 substituted with struct field names to refer to the input fields. | 229 substituted with struct field names to refer to the input fields. |
8 This macro is expanded to compute seriailized size for both: | 230 This macro is expanded to compute seriailized size for both: |
9 - user-defined structs: the input is an instance of the corresponding struct | 231 - user-defined structs: the input is an instance of the corresponding struct |
10 wrapper class. | 232 wrapper class. |
11 - method parameters/response parameters: the input is a list of | 233 - method parameters/response parameters: the input is a list of |
(...skipping 27 matching lines...) Expand all Loading... |
39 {%- set input_field = input_field_pattern|format(pf.field.name) %} | 261 {%- set input_field = input_field_pattern|format(pf.field.name) %} |
40 {%- set name = pf.field.name %} | 262 {%- set name = pf.field.name %} |
41 {%- set kind = pf.field.kind %} | 263 {%- set kind = pf.field.kind %} |
42 {%- if kind|is_object_kind %} | 264 {%- if kind|is_object_kind %} |
43 {%- if kind|is_array_kind %} | 265 {%- if kind|is_array_kind %} |
44 mojo::SerializeArray_<{{kind|get_array_validate_params|indent(24)}}>( | 266 mojo::SerializeArray_<{{kind|get_array_validate_params|indent(24)}}>( |
45 mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}
}.ptr); | 267 mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}
}.ptr); |
46 {%- elif kind|is_map_kind %} | 268 {%- elif kind|is_map_kind %} |
47 mojo::SerializeMap_<{{kind.value_kind|get_map_validate_params|indent(24)}}>( | 269 mojo::SerializeMap_<{{kind.value_kind|get_map_validate_params|indent(24)}}>( |
48 mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}
}.ptr); | 270 mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}
}.ptr); |
| 271 {%- elif kind|is_union_kind %} |
| 272 internal::{{kind.name}}_Data* {{name}}_ptr = &{{output}}->{{name}}; |
| 273 SerializeUnion_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{name}
}_ptr, true); |
49 {%- else %} | 274 {%- else %} |
50 Serialize_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->
{{name}}.ptr); | 275 Serialize_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->
{{name}}.ptr); |
51 {%- endif %} | 276 {%- endif %} |
52 {%- if not kind|is_nullable_kind %} | 277 {%- if not kind|is_nullable_kind %} |
53 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | 278 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| 279 {%- if kind|is_union_kind %} |
| 280 {{output}}->{{name}}.is_null(), |
| 281 {%- else %} |
54 !{{output}}->{{name}}.ptr, | 282 !{{output}}->{{name}}.ptr, |
| 283 {%- endif %} |
55 mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | 284 mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
56 "null {{name}} in {{struct_display_name}}"); | 285 "null {{name}} in {{struct_display_name}}"); |
57 {%- endif %} | 286 {%- endif %} |
58 {%- elif kind|is_any_handle_kind %} | 287 {%- elif kind|is_any_handle_kind %} |
59 {%- if kind|is_interface_kind or kind|is_interface_request_kind %} | 288 {%- if kind|is_interface_kind or kind|is_interface_request_kind %} |
60 {{output}}->{{name}} = {{input_field}}.PassMessagePipe().release(); | 289 {{output}}->{{name}} = {{input_field}}.PassMessagePipe().release(); |
61 {%- else %} | 290 {%- else %} |
62 {{output}}->{{name}} = {{input_field}}.release(); | 291 {{output}}->{{name}} = {{input_field}}.release(); |
63 {%- endif %} | 292 {%- endif %} |
64 {%- if not kind|is_nullable_kind %} | 293 {%- if not kind|is_nullable_kind %} |
(...skipping 30 matching lines...) Expand all Loading... |
95 {%- set last_checked_version = 0 %} | 324 {%- set last_checked_version = 0 %} |
96 {%- for pf in struct.packed.packed_fields_in_ordinal_order %} | 325 {%- for pf in struct.packed.packed_fields_in_ordinal_order %} |
97 {%- set output_field = output_field_pattern|format(pf.field.name) %} | 326 {%- set output_field = output_field_pattern|format(pf.field.name) %} |
98 {%- set name = pf.field.name %} | 327 {%- set name = pf.field.name %} |
99 {%- set kind = pf.field.kind %} | 328 {%- set kind = pf.field.kind %} |
100 {%- if pf.min_version > last_checked_version %} | 329 {%- if pf.min_version > last_checked_version %} |
101 {%- set last_checked_version = pf.min_version %} | 330 {%- set last_checked_version = pf.min_version %} |
102 if ({{input}}->header_.version < {{pf.min_version}}) | 331 if ({{input}}->header_.version < {{pf.min_version}}) |
103 break; | 332 break; |
104 {%- endif %} | 333 {%- endif %} |
105 {%- if kind|is_object_kind %} | 334 {%- if kind|is_union_kind %} |
| 335 Deserialize_(&input->{{pf.field.name}}, &result->{{pf.field.name}}); |
| 336 {%- elif kind|is_object_kind %} |
106 Deserialize_({{input}}->{{name}}.ptr, &{{output_field}}); | 337 Deserialize_({{input}}->{{name}}.ptr, &{{output_field}}); |
107 {%- elif kind|is_interface_kind or kind|is_interface_request_kind %} | 338 {%- elif kind|is_interface_kind or kind|is_interface_request_kind %} |
108 {{output_field}}.Bind(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&
{{input}}->{{name}}))); | 339 {{output_field}}.Bind(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&
{{input}}->{{name}}))); |
109 {%- elif kind|is_any_handle_kind %} | 340 {%- elif kind|is_any_handle_kind %} |
110 {{output_field}}.reset(mojo::internal::FetchAndReset(&{{input}}->{{name}})); | 341 {{output_field}}.reset(mojo::internal::FetchAndReset(&{{input}}->{{name}})); |
111 {%- elif kind|is_enum_kind %} | 342 {%- elif kind|is_enum_kind %} |
112 {{output_field}} = static_cast<{{kind|cpp_wrapper_type}}>({{input}}->{{name}
}); | 343 {{output_field}} = static_cast<{{kind|cpp_wrapper_type}}>({{input}}->{{name}
}); |
113 {%- else %} | 344 {%- else %} |
114 {{output_field}} = {{input}}->{{name}}; | 345 {{output_field}} = {{input}}->{{name}}; |
115 {%- endif %} | 346 {%- endif %} |
116 {%- endfor %} | 347 {%- endfor %} |
117 } while (false); | 348 } while (false); |
118 {%- endmacro %} | 349 {%- endmacro %} |
OLD | NEW |