| OLD | NEW |
| (Empty) |
| 1 {%- set class_name = struct.name ~ "_Data" %} | |
| 2 | |
| 3 {#- TODO(yzshen): Consider eliminating _validate_object() and | |
| 4 _validate_handle(). #} | |
| 5 | |
| 6 {#- Validates the specified struct field, which is supposed to be an object | |
| 7 (struct/array/string/map/union). | |
| 8 This macro is expanded by the Validate() method. #} | |
| 9 {%- macro _validate_object(struct, packed_field, err_string) %} | |
| 10 {%- set name = packed_field.field.name %} | |
| 11 {%- set kind = packed_field.field.kind %} | |
| 12 {%- set wrapper_type = kind|cpp_wrapper_type %} | |
| 13 {%- if not kind|is_nullable_kind %} | |
| 14 {%- if kind|is_union_kind %} | |
| 15 if (object->{{name}}.is_null()) { | |
| 16 {%- else %} | |
| 17 if (!object->{{name}}.offset) { | |
| 18 {%- endif %} | |
| 19 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG({{err_string}}) << | |
| 20 "null {{name}} field in {{struct.name}} struct"; | |
| 21 return mojo::internal::ValidationError::UNEXPECTED_NULL_POINTER; | |
| 22 } | |
| 23 {%- endif %} | |
| 24 {%- if not kind|is_union_kind %} | |
| 25 if (!mojo::internal::ValidateEncodedPointer(&object->{{name}}.offset)) { | |
| 26 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG({{err_string}}) << ""; | |
| 27 return mojo::internal::ValidationError::ILLEGAL_POINTER; | |
| 28 } | |
| 29 {%- endif %} | |
| 30 | |
| 31 {%- if kind|is_array_kind or kind|is_string_kind %} | |
| 32 const mojo::internal::ArrayValidateParams {{name}}_validate_params( | |
| 33 {{kind|get_array_validate_params_ctor_args|indent(6)}}); | |
| 34 auto validate_retval = | |
| 35 {{wrapper_type}}::Data_::Validate( | |
| 36 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), | |
| 37 bounds_checker, &{{name}}_validate_params, {{err_string}}); | |
| 38 if (validate_retval != mojo::internal::ValidationError::NONE) { | |
| 39 {%- elif kind|is_map_kind %} | |
| 40 const mojo::internal::ArrayValidateParams {{name}}_validate_params( | |
| 41 {{kind.value_kind|get_map_validate_params_ctor_args|indent(6)}}); | |
| 42 auto validate_retval = {{wrapper_type}}::Data_::Validate( | |
| 43 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), | |
| 44 bounds_checker, &{{name}}_validate_params, {{err_string}}); | |
| 45 if (validate_retval != mojo::internal::ValidationError::NONE) { | |
| 46 {%- elif kind|is_struct_kind %} | |
| 47 auto validate_retval = {{kind|get_name_for_kind}}::Data_::Validate( | |
| 48 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), | |
| 49 bounds_checker, {{err_string}}); | |
| 50 if (validate_retval != mojo::internal::ValidationError::NONE) { | |
| 51 {%- elif kind|is_union_kind %} | |
| 52 auto validate_retval = {{kind|get_name_for_kind}}::Data_::Validate( | |
| 53 &object->{{name}}, bounds_checker, true, {{err_string}}); | |
| 54 if (validate_retval != mojo::internal::ValidationError::NONE) { | |
| 55 {%- else %} | |
| 56 auto validate_retval = {{wrapper_type}}::Data_::Validate( | |
| 57 mojo::internal::DecodePointerRaw(&object->{{name}}.offset), | |
| 58 bounds_checker, {{err_string}}); | |
| 59 if (validate_retval != mojo::internal::ValidationError::NONE) { | |
| 60 {%- endif %} | |
| 61 return validate_retval; | |
| 62 } | |
| 63 {%- endmacro %} | |
| 64 | |
| 65 {#- Validates the specified struct field, which is supposed to be a handle or | |
| 66 contain a handle (in the case of interfaces). | |
| 67 This macro is expanded by the Validate() method. #} | |
| 68 {%- macro _validate_handle(struct, packed_field, err_string) %} | |
| 69 {%- set name = packed_field.field.name %} | |
| 70 {%- set kind = packed_field.field.kind %} | |
| 71 {%- if kind|is_interface_kind %} | |
| 72 const mojo::Handle {{name}}_handle = object->{{name}}.handle; | |
| 73 {%- else %} | |
| 74 const mojo::Handle {{name}}_handle = object->{{name}}; | |
| 75 {%- endif %} | |
| 76 {%- if not kind|is_nullable_kind %} | |
| 77 if ({{name}}_handle.value() == mojo::internal::kEncodedInvalidHandleValue) { | |
| 78 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG({{err_string}}) | |
| 79 << "invalid {{name}} field in {{struct.name}} struct"; | |
| 80 return mojo::internal::ValidationError::UNEXPECTED_INVALID_HANDLE; | |
| 81 } | |
| 82 {%- endif %} | |
| 83 if (!bounds_checker->ClaimHandle({{name}}_handle)) { | |
| 84 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG({{err_string}}) << ""; | |
| 85 return mojo::internal::ValidationError::ILLEGAL_HANDLE; | |
| 86 } | |
| 87 {%- endmacro %} | |
| 88 | |
| 89 // static | |
| 90 {{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) { | |
| 91 return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); | |
| 92 } | |
| 93 | |
| 94 // static | |
| 95 mojo::internal::ValidationError {{class_name}}::Validate( | |
| 96 const void* data, | |
| 97 mojo::internal::BoundsChecker* bounds_checker, | |
| 98 std::string* err) { | |
| 99 mojo::internal::ValidationError retval; | |
| 100 | |
| 101 if (!data) | |
| 102 return mojo::internal::ValidationError::NONE; | |
| 103 | |
| 104 retval = ValidateStructHeaderAndClaimMemory(data, bounds_checker, err); | |
| 105 if (retval != mojo::internal::ValidationError::NONE) | |
| 106 return retval; | |
| 107 | |
| 108 // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if | |
| 109 // the message comes from an older version. | |
| 110 const {{class_name}}* object = static_cast<const {{class_name}}*>(data); | |
| 111 | |
| 112 static const struct { | |
| 113 uint32_t version; | |
| 114 uint32_t num_bytes; | |
| 115 } kVersionSizes[] = { | |
| 116 {%- for version in struct.versions -%} | |
| 117 { {{version.version}}, {{version.num_bytes}} }{% if not loop.last %}, {% end
if -%} | |
| 118 {%- endfor -%} | |
| 119 }; | |
| 120 | |
| 121 if (object->header_.version <= | |
| 122 kVersionSizes[MOJO_ARRAYSIZE(kVersionSizes) - 1].version) { | |
| 123 // Scan in reverse order to optimize for more recent versions. | |
| 124 for (int i = MOJO_ARRAYSIZE(kVersionSizes) - 1; i >= 0; --i) { | |
| 125 if (object->header_.version >= kVersionSizes[i].version) { | |
| 126 if (object->header_.num_bytes == kVersionSizes[i].num_bytes) | |
| 127 break; | |
| 128 | |
| 129 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << ""; | |
| 130 return mojo::internal::ValidationError::UNEXPECTED_STRUCT_HEADER; | |
| 131 } | |
| 132 } | |
| 133 } else if (object->header_.num_bytes < | |
| 134 kVersionSizes[MOJO_ARRAYSIZE(kVersionSizes) - 1].num_bytes) { | |
| 135 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << ""; | |
| 136 return mojo::internal::ValidationError::UNEXPECTED_STRUCT_HEADER; | |
| 137 } | |
| 138 | |
| 139 {#- Before validating fields introduced at a certain version, we need to add | |
| 140 a version check, which makes sure we skip further validation if |object| | |
| 141 is from an earlier version. |last_checked_version| records the last | |
| 142 version that we have added such version check. #} | |
| 143 {%- set last_checked_version = 0 %} | |
| 144 {%- for packed_field in struct.packed.packed_fields_in_ordinal_order %} | |
| 145 {%- set kind = packed_field.field.kind %} | |
| 146 {%- if kind|is_object_kind or kind|is_any_handle_kind or kind|is_interface_kin
d %} | |
| 147 {%- if packed_field.min_version > last_checked_version %} | |
| 148 {%- set last_checked_version = packed_field.min_version %} | |
| 149 if (object->header_.version < {{packed_field.min_version}}) | |
| 150 return mojo::internal::ValidationError::NONE; | |
| 151 {%- endif %} | |
| 152 {%- if kind|is_object_kind %} | |
| 153 { | |
| 154 {{_validate_object(struct, packed_field, "err")}} | |
| 155 } | |
| 156 {%- else %} | |
| 157 { | |
| 158 {{_validate_handle(struct, packed_field, "err")}} | |
| 159 } | |
| 160 {%- endif %} | |
| 161 {%- endif %} | |
| 162 {%- endfor %} | |
| 163 | |
| 164 return mojo::internal::ValidationError::NONE; | |
| 165 } | |
| 166 | |
| 167 void {{class_name}}::EncodePointersAndHandles( | |
| 168 std::vector<mojo::Handle>* handles) { | |
| 169 MOJO_CHECK(header_.version == {{struct.versions[-1].version}}); | |
| 170 {%- for pf in struct.packed.packed_fields_in_ordinal_order %} | |
| 171 {%- if pf.field.kind|is_union_kind %} | |
| 172 {{pf.field.name}}.EncodePointersAndHandles(handles); | |
| 173 {%- elif pf.field.kind|is_object_kind %} | |
| 174 mojo::internal::Encode(&this->{{pf.field.name}}, handles); | |
| 175 {%- elif pf.field.kind|is_any_handle_kind or pf.field.kind|is_interface_kind %
} | |
| 176 mojo::internal::EncodeHandle(&this->{{pf.field.name}}, handles); | |
| 177 {%- endif %} | |
| 178 {%- endfor %} | |
| 179 } | |
| 180 | |
| 181 void {{class_name}}::DecodePointersAndHandles( | |
| 182 std::vector<mojo::Handle>* handles) { | |
| 183 // NOTE: The memory backing |this| may has be smaller than |sizeof(*this)|, if | |
| 184 // the message comes from an older version. | |
| 185 {#- Before decoding fields introduced at a certain version, we need to add | |
| 186 a version check, which makes sure we skip further decoding if |this| | |
| 187 is from an earlier version. |last_checked_version| records the last | |
| 188 version that we have added such version check. #} | |
| 189 {%- set last_checked_version = 0 %} | |
| 190 {%- for pf in struct.packed.packed_fields_in_ordinal_order %} | |
| 191 {%- set name = pf.field.name %} | |
| 192 {%- set kind = pf.field.kind %} | |
| 193 {%- if kind|is_object_kind or kind|is_any_handle_kind or kind|is_interface_kin
d %} | |
| 194 {%- if pf.min_version > last_checked_version %} | |
| 195 {%- set last_checked_version = pf.min_version %} | |
| 196 if (header_.version < {{pf.min_version}}) | |
| 197 return; | |
| 198 {%- endif %} | |
| 199 {%- if kind|is_union_kind %} | |
| 200 {{name}}.DecodePointersAndHandles(handles); | |
| 201 {%- elif kind|is_object_kind %} | |
| 202 mojo::internal::Decode(&this->{{name}}, handles); | |
| 203 {%- else %} | |
| 204 mojo::internal::DecodeHandle(&this->{{name}}, handles); | |
| 205 {%- endif %} | |
| 206 {%- endif %} | |
| 207 {%- endfor %} | |
| 208 } | |
| 209 | |
| 210 {{class_name}}::{{class_name}}() { | |
| 211 header_.num_bytes = sizeof(*this); | |
| 212 header_.version = {{struct.versions[-1].version}}; | |
| 213 } | |
| OLD | NEW |