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 |