blob: c9dc5e2ceb32bb76270b2d922f35e511da49ebbc [file] [log] [blame]
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02001//* Copyright 2017 The Dawn Authors
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04002//*
3//* Licensed under the Apache License, Version 2.0 (the "License");
4//* you may not use this file except in compliance with the License.
5//* You may obtain a copy of the License at
6//*
7//* http://www.apache.org/licenses/LICENSE-2.0
8//*
9//* Unless required by applicable law or agreed to in writing, software
10//* distributed under the License is distributed on an "AS IS" BASIS,
11//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//* See the License for the specific language governing permissions and
13//* limitations under the License.
14
Austin Engc7f416c2019-01-15 20:49:53 +000015#include "dawn_wire/WireCmd_autogen.h"
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040016
Corentin Wallez40e72d72018-06-08 18:30:50 +020017#include "common/Assert.h"
Austin Eng65a903b2021-02-01 16:48:18 +000018#include "common/Log.h"
Austin Engbd3f5862021-02-25 20:21:25 +000019#include "dawn_wire/BufferConsumer_impl.h"
Jiawei Shao5c2f5f32019-10-20 03:01:56 +000020#include "dawn_wire/Wire.h"
Corentin Wallez40e72d72018-06-08 18:30:50 +020021
Austin Eng8eb83852019-10-07 20:38:47 +000022#include <algorithm>
Corentin Wallez88fb8fa2018-06-06 17:36:49 +020023#include <cstring>
Corentin Walleza19c7592019-01-04 09:54:10 +000024#include <limits>
Corentin Wallez88fb8fa2018-06-06 17:36:49 +020025
Corentin Wallez40e72d72018-06-08 18:30:50 +020026//* Helper macros so that the main [de]serialization functions can be written in a generic manner.
27
28//* Outputs an rvalue that's the number of elements a pointer member points to.
29{% macro member_length(member, record_accessor) -%}
30 {%- if member.length == "constant" -%}
Austin Eng51db53f2021-02-18 19:28:29 +000031 {{member.constant_length}}u
Corentin Wallez40e72d72018-06-08 18:30:50 +020032 {%- else -%}
33 {{record_accessor}}{{as_varName(member.length.name)}}
34 {%- endif -%}
35{%- endmacro %}
36
37//* Outputs the type that will be used on the wire for the member
38{% macro member_transfer_type(member) -%}
39 {%- if member.type.category == "object" -%}
40 ObjectId
41 {%- elif member.type.category == "structure" -%}
42 {{as_cType(member.type.name)}}Transfer
Corentin Wallez919812e2019-10-17 08:46:07 +000043 {%- elif member.type.category == "bitmask" -%}
44 {{as_cType(member.type.name)}}Flags
Corentin Wallez40e72d72018-06-08 18:30:50 +020045 {%- else -%}
Austin Engf104fea2021-02-18 22:36:19 +000046 {{ assert(as_cType(member.type.name) != "size_t") }}
Corentin Wallez40e72d72018-06-08 18:30:50 +020047 {{as_cType(member.type.name)}}
48 {%- endif -%}
49{%- endmacro %}
50
51//* Outputs the size of one element of the type that will be used on the wire for the member
52{% macro member_transfer_sizeof(member) -%}
53 sizeof({{member_transfer_type(member)}})
54{%- endmacro %}
55
56//* Outputs the serialization code to put `in` in `out`
57{% macro serialize_member(member, in, out) %}
58 {%- if member.type.category == "object" -%}
Austin Engc7f416c2019-01-15 20:49:53 +000059 {%- set Optional = "Optional" if member.optional else "" -%}
Austin Engdc7971c2021-09-10 20:36:20 +000060 WIRE_TRY(provider.Get{{Optional}}Id({{in}}, &{{out}}));
Yunchao Hec0f31e72019-01-21 08:29:01 +000061 {% elif member.type.category == "structure"%}
Austin Eng76a8d0b2020-04-03 17:37:48 +000062 {%- set Provider = ", provider" if member.type.may_have_dawn_object else "" -%}
Yunchao Hec0f31e72019-01-21 08:29:01 +000063 {% if member.annotation == "const*const*" %}
Austin Engbd3f5862021-02-25 20:21:25 +000064 WIRE_TRY({{as_cType(member.type.name)}}Serialize(*{{in}}, &{{out}}, buffer{{Provider}}));
Yunchao Hec0f31e72019-01-21 08:29:01 +000065 {% else %}
Austin Engbd3f5862021-02-25 20:21:25 +000066 WIRE_TRY({{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}}));
Yunchao Hec0f31e72019-01-21 08:29:01 +000067 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +020068 {%- else -%}
69 {{out}} = {{in}};
70 {%- endif -%}
71{% endmacro %}
72
73//* Outputs the deserialization code to put `in` in `out`
74{% macro deserialize_member(member, in, out) %}
75 {%- if member.type.category == "object" -%}
Austin Engc7f416c2019-01-15 20:49:53 +000076 {%- set Optional = "Optional" if member.optional else "" -%}
Austin Engbd3f5862021-02-25 20:21:25 +000077 WIRE_TRY(resolver.Get{{Optional}}FromId({{in}}, &{{out}}));
Austin Engc7f416c2019-01-15 20:49:53 +000078 {%- elif member.type.category == "structure" -%}
Austin Engbd3f5862021-02-25 20:21:25 +000079 WIRE_TRY({{as_cType(member.type.name)}}Deserialize(&{{out}}, &{{in}}, deserializeBuffer, allocator
Austin Eng76a8d0b2020-04-03 17:37:48 +000080 {%- if member.type.may_have_dawn_object -%}
Austin Engc7f416c2019-01-15 20:49:53 +000081 , resolver
82 {%- endif -%}
83 ));
Corentin Wallez40e72d72018-06-08 18:30:50 +020084 {%- else -%}
Austin Engf104fea2021-02-18 22:36:19 +000085 static_assert(sizeof({{out}}) >= sizeof({{in}}), "Deserialize assignment may not narrow.");
Corentin Wallez40e72d72018-06-08 18:30:50 +020086 {{out}} = {{in}};
87 {%- endif -%}
88{% endmacro %}
89
Austin Eng76a8d0b2020-04-03 17:37:48 +000090namespace {
91
92 struct WGPUChainedStructTransfer {
93 WGPUSType sType;
94 bool hasNext;
95 };
96
97} // anonymous namespace
98
Corentin Wallez40e72d72018-06-08 18:30:50 +020099//* The main [de]serialization macro
Corentin Wallez40e72d72018-06-08 18:30:50 +0200100//* Methods are very similar to structures that have one member corresponding to each arguments.
101//* This macro takes advantage of the similarity to output [de]serialization code for a record
102//* that is either a structure or a method, with some special cases for each.
Corentin Wallezcb2c64f2019-04-01 21:04:17 +0000103{% macro write_record_serialization_helpers(record, name, members, is_cmd=False, is_return_command=False) %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200104 {% set Return = "Return" if is_return_command else "" %}
Austin Engc7f416c2019-01-15 20:49:53 +0000105 {% set Cmd = "Cmd" if is_cmd else "" %}
Austin Engcac04422020-10-13 22:35:34 +0000106 {% set Inherits = " : CmdHeader" if is_cmd else "" %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200107
108 //* Structure for the wire format of each of the records. Members that are values
109 //* are embedded directly in the structure. Other members are assumed to be in the
110 //* memory directly following the structure in the buffer.
Austin Engcac04422020-10-13 22:35:34 +0000111 struct {{Return}}{{name}}Transfer{{Inherits}} {
Austin Eng76a8d0b2020-04-03 17:37:48 +0000112 static_assert({{[is_cmd, record.extensible, record.chained].count(True)}} <= 1,
113 "Record must be at most one of is_cmd, extensible, and chained.");
Austin Engc7f416c2019-01-15 20:49:53 +0000114 {% if is_cmd %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200115 //* Start the transfer structure with the command ID, so that casting to WireCmd gives the ID.
Corentin Wallezbdc86772018-07-26 15:07:57 +0200116 {{Return}}WireCmd commandId;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000117 {% elif record.extensible %}
118 bool hasNextInChain;
119 {% elif record.chained %}
120 WGPUChainedStructTransfer chain;
Corentin Wallez40e72d72018-06-08 18:30:50 +0200121 {% endif %}
122
123 //* Value types are directly in the command, objects being replaced with their IDs.
124 {% for member in members if member.annotation == "value" %}
125 {{member_transfer_type(member)}} {{as_varName(member.name)}};
126 {% endfor %}
127
128 //* const char* have their length embedded directly in the command.
129 {% for member in members if member.length == "strlen" %}
Austin Engf104fea2021-02-18 22:36:19 +0000130 uint64_t {{as_varName(member.name)}}Strlen;
Corentin Wallez40e72d72018-06-08 18:30:50 +0200131 {% endfor %}
Corentin Wallezf872e692019-02-13 10:15:38 +0000132
Austin Eng4379e8f2019-10-02 06:35:08 +0000133 {% for member in members if member.optional and member.annotation != "value" and member.type.category != "object" %}
Corentin Wallezf872e692019-02-13 10:15:38 +0000134 bool has_{{as_varName(member.name)}};
135 {% endfor %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200136 };
137
Austin Engcac04422020-10-13 22:35:34 +0000138 {% if is_cmd %}
139 static_assert(offsetof({{Return}}{{name}}Transfer, commandSize) == 0, "");
140 static_assert(offsetof({{Return}}{{name}}Transfer, commandId) == sizeof(CmdHeader), "");
141 {% endif %}
142
Austin Eng76a8d0b2020-04-03 17:37:48 +0000143 {% if record.chained %}
144 static_assert(offsetof({{Return}}{{name}}Transfer, chain) == 0, "");
145 {% endif %}
146
Corentin Wallez40e72d72018-06-08 18:30:50 +0200147 //* Returns the required transfer size for `record` in addition to the transfer structure.
Austin Engc7f416c2019-01-15 20:49:53 +0000148 DAWN_DECLARE_UNUSED size_t {{Return}}{{name}}GetExtraRequiredSize(const {{Return}}{{name}}{{Cmd}}& record) {
Corentin Wallez83a9c9d2018-07-18 13:37:54 +0200149 DAWN_UNUSED(record);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200150
151 size_t result = 0;
152
Austin Eng76a8d0b2020-04-03 17:37:48 +0000153 //* Gather how much space will be needed for the extension chain.
154 {% if record.extensible %}
155 if (record.nextInChain != nullptr) {
156 result += GetChainedStructExtraRequiredSize(record.nextInChain);
157 }
158 {% endif %}
159
Corentin Wallez40e72d72018-06-08 18:30:50 +0200160 //* Special handling of const char* that have their length embedded directly in the command
161 {% for member in members if member.length == "strlen" %}
François Beaufortf622a442019-09-27 21:25:43 +0000162 {% set memberName = as_varName(member.name) %}
163
164 {% if member.optional %}
165 bool has_{{memberName}} = record.{{memberName}} != nullptr;
166 if (has_{{memberName}})
167 {% endif %}
168 {
169 result += std::strlen(record.{{memberName}});
170 }
Corentin Wallez40e72d72018-06-08 18:30:50 +0200171 {% endfor %}
172
173 //* Gather how much space will be needed for pointer members.
Corentin Wallezc6c7a422019-09-05 09:35:07 +0000174 {% for member in members if member.length != "strlen" and not member.skip_serialize %}
Corentin Wallezf872e692019-02-13 10:15:38 +0000175 {% if member.type.category != "object" and member.optional %}
176 if (record.{{as_varName(member.name)}} != nullptr)
177 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200178 {
Corentin Wallezc6c7a422019-09-05 09:35:07 +0000179 {% if member.annotation != "value" %}
Austin Eng51db53f2021-02-18 19:28:29 +0000180 auto memberLength = {{member_length(member, "record.")}};
Corentin Wallezc6c7a422019-09-05 09:35:07 +0000181 result += memberLength * {{member_transfer_sizeof(member)}};
182 //* Structures might contain more pointers so we need to add their extra size as well.
183 {% if member.type.category == "structure" %}
Austin Eng51db53f2021-02-18 19:28:29 +0000184 for (decltype(memberLength) i = 0; i < memberLength; ++i) {
Corentin Wallezc6c7a422019-09-05 09:35:07 +0000185 {% if member.annotation == "const*const*" %}
186 result += {{as_cType(member.type.name)}}GetExtraRequiredSize(*record.{{as_varName(member.name)}}[i]);
187 {% else %}
188 {{assert(member.annotation == "const*")}}
189 result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}}[i]);
190 {% endif %}
191 }
192 {% endif %}
193 {% elif member.type.category == "structure" %}
194 result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}});
Corentin Wallez40e72d72018-06-08 18:30:50 +0200195 {% endif %}
196 }
197 {% endfor %}
198
199 return result;
200 }
Corentin Wallez03e18132018-09-17 22:59:08 +0000201 // GetExtraRequiredSize isn't used for structures that are value members of other structures
202 // because we assume they cannot contain pointers themselves.
Austin Engc7f416c2019-01-15 20:49:53 +0000203 DAWN_UNUSED_FUNC({{Return}}{{name}}GetExtraRequiredSize);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200204
205 //* Serializes `record` into `transfer`, using `buffer` to get more space for pointed-to data
206 //* and `provider` to serialize objects.
Austin Engbd3f5862021-02-25 20:21:25 +0000207 DAWN_DECLARE_UNUSED WireResult {{Return}}{{name}}Serialize(const {{Return}}{{name}}{{Cmd}}& record, {{Return}}{{name}}Transfer* transfer,
Austin Eng1b31dc02021-02-17 22:14:56 +0000208 SerializeBuffer* buffer
Austin Eng76a8d0b2020-04-03 17:37:48 +0000209 {%- if record.may_have_dawn_object -%}
Austin Engc7f416c2019-01-15 20:49:53 +0000210 , const ObjectIdProvider& provider
211 {%- endif -%}
212 ) {
Corentin Wallez83a9c9d2018-07-18 13:37:54 +0200213 DAWN_UNUSED(buffer);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200214
215 //* Handle special transfer members of methods.
Austin Engc7f416c2019-01-15 20:49:53 +0000216 {% if is_cmd %}
Corentin Wallezbdc86772018-07-26 15:07:57 +0200217 transfer->commandId = {{Return}}WireCmd::{{name}};
Corentin Wallez40e72d72018-06-08 18:30:50 +0200218 {% endif %}
219
220 //* Value types are directly in the transfer record, objects being replaced with their IDs.
221 {% for member in members if member.annotation == "value" %}
222 {% set memberName = as_varName(member.name) %}
223 {{serialize_member(member, "record." + memberName, "transfer->" + memberName)}}
224 {% endfor %}
225
Austin Eng76a8d0b2020-04-03 17:37:48 +0000226 {% if record.extensible %}
227 if (record.nextInChain != nullptr) {
228 transfer->hasNextInChain = true;
Austin Engbd3f5862021-02-25 20:21:25 +0000229 WIRE_TRY(SerializeChainedStruct(record.nextInChain, buffer, provider));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000230 } else {
231 transfer->hasNextInChain = false;
232 }
233 {% endif %}
234
235 {% if record.chained %}
236 //* Should be set by the root descriptor's call to SerializeChainedStruct.
237 ASSERT(transfer->chain.sType == {{as_cEnum(types["s type"].name, record.name)}});
238 ASSERT(transfer->chain.hasNext == (record.chain.next != nullptr));
239 {% endif %}
240
Corentin Wallez40e72d72018-06-08 18:30:50 +0200241 //* Special handling of const char* that have their length embedded directly in the command
242 {% for member in members if member.length == "strlen" %}
243 {% set memberName = as_varName(member.name) %}
François Beaufortf622a442019-09-27 21:25:43 +0000244
François Beaufortf622a442019-09-27 21:25:43 +0000245 {% if member.optional %}
Austin Eng4379e8f2019-10-02 06:35:08 +0000246 bool has_{{memberName}} = record.{{memberName}} != nullptr;
247 transfer->has_{{memberName}} = has_{{memberName}};
François Beaufortf622a442019-09-27 21:25:43 +0000248 if (has_{{memberName}})
249 {% endif %}
250 {
Austin Eng1b31dc02021-02-17 22:14:56 +0000251 transfer->{{memberName}}Strlen = std::strlen(record.{{memberName}});
Corentin Wallez40e72d72018-06-08 18:30:50 +0200252
Austin Eng1b31dc02021-02-17 22:14:56 +0000253 char* stringInBuffer;
Austin Engbd3f5862021-02-25 20:21:25 +0000254 WIRE_TRY(buffer->NextN(transfer->{{memberName}}Strlen, &stringInBuffer));
Austin Eng1b31dc02021-02-17 22:14:56 +0000255 memcpy(stringInBuffer, record.{{memberName}}, transfer->{{memberName}}Strlen);
François Beaufortf622a442019-09-27 21:25:43 +0000256 }
Corentin Wallez40e72d72018-06-08 18:30:50 +0200257 {% endfor %}
258
259 //* Allocate space and write the non-value arguments in it.
Austin Eng6a5418a2019-07-19 16:01:48 +0000260 {% for member in members if member.annotation != "value" and member.length != "strlen" and not member.skip_serialize %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200261 {% set memberName = as_varName(member.name) %}
Corentin Wallezf872e692019-02-13 10:15:38 +0000262
263 {% if member.type.category != "object" and member.optional %}
264 bool has_{{memberName}} = record.{{memberName}} != nullptr;
265 transfer->has_{{memberName}} = has_{{memberName}};
266 if (has_{{memberName}})
267 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200268 {
Austin Eng51db53f2021-02-18 19:28:29 +0000269 auto memberLength = {{member_length(member, "record.")}};
Austin Eng1b31dc02021-02-17 22:14:56 +0000270
271 {{member_transfer_type(member)}}* memberBuffer;
Austin Engbd3f5862021-02-25 20:21:25 +0000272 WIRE_TRY(buffer->NextN(memberLength, &memberBuffer));
Corentin Wallezc6c7a422019-09-05 09:35:07 +0000273
Austin Eng5eb496b2021-02-24 18:39:31 +0000274 //* This loop cannot overflow because it iterates up to |memberLength|. Even if
275 //* memberLength were the maximum integer value, |i| would become equal to it just before
276 //* exiting the loop, but not increment past or wrap around.
Austin Eng51db53f2021-02-18 19:28:29 +0000277 for (decltype(memberLength) i = 0; i < memberLength; ++i) {
Corentin Wallez40e72d72018-06-08 18:30:50 +0200278 {{serialize_member(member, "record." + memberName + "[i]", "memberBuffer[i]" )}}
279 }
Corentin Wallez40e72d72018-06-08 18:30:50 +0200280 }
281 {% endfor %}
Austin Engbd3f5862021-02-25 20:21:25 +0000282 return WireResult::Success;
Corentin Wallez40e72d72018-06-08 18:30:50 +0200283 }
Austin Eng740995c2019-05-15 18:55:22 +0000284 DAWN_UNUSED_FUNC({{Return}}{{name}}Serialize);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200285
286 //* Deserializes `transfer` into `record` getting more serialized data from `buffer` and `size`
287 //* if needed, using `allocator` to store pointed-to values and `resolver` to translate object
288 //* Ids to actual objects.
Austin Engbd3f5862021-02-25 20:21:25 +0000289 DAWN_DECLARE_UNUSED WireResult {{Return}}{{name}}Deserialize({{Return}}{{name}}{{Cmd}}* record, const volatile {{Return}}{{name}}Transfer* transfer,
Austin Eng51db53f2021-02-18 19:28:29 +0000290 DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator
Austin Eng76a8d0b2020-04-03 17:37:48 +0000291 {%- if record.may_have_dawn_object -%}
Austin Engc7f416c2019-01-15 20:49:53 +0000292 , const ObjectIdResolver& resolver
293 {%- endif -%}
294 ) {
Corentin Wallez83a9c9d2018-07-18 13:37:54 +0200295 DAWN_UNUSED(allocator);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200296
Austin Engc7f416c2019-01-15 20:49:53 +0000297 {% if is_cmd %}
298 ASSERT(transfer->commandId == {{Return}}WireCmd::{{name}});
299 {% endif %}
300
Corentin Wallezcb2c64f2019-04-01 21:04:17 +0000301 {% if record.derived_method %}
302 record->selfId = transfer->self;
303 {% endif %}
304
Corentin Wallez40e72d72018-06-08 18:30:50 +0200305 //* Value types are directly in the transfer record, objects being replaced with their IDs.
306 {% for member in members if member.annotation == "value" %}
307 {% set memberName = as_varName(member.name) %}
308 {{deserialize_member(member, "transfer->" + memberName, "record->" + memberName)}}
309 {% endfor %}
310
Austin Eng76a8d0b2020-04-03 17:37:48 +0000311 {% if record.extensible %}
312 record->nextInChain = nullptr;
313 if (transfer->hasNextInChain) {
Austin Engbd3f5862021-02-25 20:21:25 +0000314 WIRE_TRY(DeserializeChainedStruct(&record->nextInChain, deserializeBuffer, allocator, resolver));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000315 }
316 {% endif %}
317
318 {% if record.chained %}
319 //* Should be set by the root descriptor's call to DeserializeChainedStruct.
320 //* Don't check |record->chain.next| matches because it is not set until the
321 //* next iteration inside DeserializeChainedStruct.
322 ASSERT(record->chain.sType == {{as_cEnum(types["s type"].name, record.name)}});
323 ASSERT(record->chain.next == nullptr);
324 {% endif %}
325
Corentin Wallez40e72d72018-06-08 18:30:50 +0200326 //* Special handling of const char* that have their length embedded directly in the command
327 {% for member in members if member.length == "strlen" %}
328 {% set memberName = as_varName(member.name) %}
François Beaufortf622a442019-09-27 21:25:43 +0000329
Austin Eng4379e8f2019-10-02 06:35:08 +0000330 {% if member.optional %}
Austin Eng8eb83852019-10-07 20:38:47 +0000331 bool has_{{memberName}} = transfer->has_{{memberName}};
332 record->{{memberName}} = nullptr;
333 if (has_{{memberName}})
Austin Eng4379e8f2019-10-02 06:35:08 +0000334 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200335 {
Austin Engf104fea2021-02-18 22:36:19 +0000336 uint64_t stringLength64 = transfer->{{memberName}}Strlen;
337 if (stringLength64 >= std::numeric_limits<size_t>::max()) {
338 //* Cannot allocate space for the string. It can be at most
339 //* size_t::max() - 1. We need 1 byte for the null-terminator.
Austin Engbd3f5862021-02-25 20:21:25 +0000340 return WireResult::FatalError;
Austin Engb921b7d2021-02-18 18:45:09 +0000341 }
Austin Engf104fea2021-02-18 22:36:19 +0000342 size_t stringLength = static_cast<size_t>(stringLength64);
Austin Engb921b7d2021-02-18 18:45:09 +0000343
Austin Eng51db53f2021-02-18 19:28:29 +0000344 const volatile char* stringInBuffer;
Austin Engbd3f5862021-02-25 20:21:25 +0000345 WIRE_TRY(deserializeBuffer->ReadN(stringLength, &stringInBuffer));
Corentin Wallez40e72d72018-06-08 18:30:50 +0200346
Austin Eng51db53f2021-02-18 19:28:29 +0000347 char* copiedString;
Austin Engbd3f5862021-02-25 20:21:25 +0000348 WIRE_TRY(GetSpace(allocator, stringLength + 1, &copiedString));
Austin Engf104fea2021-02-18 22:36:19 +0000349 //* We can cast away the volatile qualifier because DeserializeBuffer::ReadN already
350 //* validated that the range [stringInBuffer, stringInBuffer + stringLength) is valid.
Austin Engb921b7d2021-02-18 18:45:09 +0000351 //* memcpy may have an unknown access pattern, but this is fine since the string is only
352 //* data and won't affect control flow of this function.
353 memcpy(copiedString, const_cast<const char*>(stringInBuffer), stringLength);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200354 copiedString[stringLength] = '\0';
355 record->{{memberName}} = copiedString;
356 }
357 {% endfor %}
358
359 //* Get extra buffer data, and copy pointed to values in extra allocated space.
360 {% for member in members if member.annotation != "value" and member.length != "strlen" %}
361 {% set memberName = as_varName(member.name) %}
Corentin Wallezf872e692019-02-13 10:15:38 +0000362
363 {% if member.type.category != "object" and member.optional %}
Corentin Wallez75f554d2021-06-17 16:04:29 +0000364 //* Non-constant length optional members use length=0 to denote they aren't present.
365 //* Otherwise we could have length=N and has_member=false, causing reads from an
366 //* uninitialized pointer.
367 {{ assert(member.length == "constant") }}
Corentin Wallezf872e692019-02-13 10:15:38 +0000368 bool has_{{memberName}} = transfer->has_{{memberName}};
369 record->{{memberName}} = nullptr;
370 if (has_{{memberName}})
371 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200372 {
Austin Eng51db53f2021-02-18 19:28:29 +0000373 auto memberLength = {{member_length(member, "record->")}};
374 const volatile {{member_transfer_type(member)}}* memberBuffer;
Austin Engbd3f5862021-02-25 20:21:25 +0000375 WIRE_TRY(deserializeBuffer->ReadN(memberLength, &memberBuffer));
Corentin Wallez40e72d72018-06-08 18:30:50 +0200376
Austin Eng51db53f2021-02-18 19:28:29 +0000377 {{as_cType(member.type.name)}}* copiedMembers;
Austin Engbd3f5862021-02-25 20:21:25 +0000378 WIRE_TRY(GetSpace(allocator, memberLength, &copiedMembers));
Yunchao Hec0f31e72019-01-21 08:29:01 +0000379 {% if member.annotation == "const*const*" %}
Austin Eng51db53f2021-02-18 19:28:29 +0000380 {{as_cType(member.type.name)}}** pointerArray;
Austin Engbd3f5862021-02-25 20:21:25 +0000381 WIRE_TRY(GetSpace(allocator, memberLength, &pointerArray));
382
Austin Eng5eb496b2021-02-24 18:39:31 +0000383 //* This loop cannot overflow because it iterates up to |memberLength|. Even if
384 //* memberLength were the maximum integer value, |i| would become equal to it just before
385 //* exiting the loop, but not increment past or wrap around.
Austin Eng51db53f2021-02-18 19:28:29 +0000386 for (decltype(memberLength) i = 0; i < memberLength; ++i) {
Yunchao Hec0f31e72019-01-21 08:29:01 +0000387 pointerArray[i] = &copiedMembers[i];
388 }
389 record->{{memberName}} = pointerArray;
390 {% else %}
391 record->{{memberName}} = copiedMembers;
392 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200393
Austin Eng5eb496b2021-02-24 18:39:31 +0000394 //* This loop cannot overflow because it iterates up to |memberLength|. Even if
395 //* memberLength were the maximum integer value, |i| would become equal to it just before
396 //* exiting the loop, but not increment past or wrap around.
Austin Eng51db53f2021-02-18 19:28:29 +0000397 for (decltype(memberLength) i = 0; i < memberLength; ++i) {
Corentin Wallez40e72d72018-06-08 18:30:50 +0200398 {{deserialize_member(member, "memberBuffer[i]", "copiedMembers[i]")}}
399 }
400 }
401 {% endfor %}
402
Austin Engbd3f5862021-02-25 20:21:25 +0000403 return WireResult::Success;
Corentin Wallez40e72d72018-06-08 18:30:50 +0200404 }
Austin Eng740995c2019-05-15 18:55:22 +0000405 DAWN_UNUSED_FUNC({{Return}}{{name}}Deserialize);
Corentin Wallez40e72d72018-06-08 18:30:50 +0200406{% endmacro %}
407
Austin Engc7f416c2019-01-15 20:49:53 +0000408{% macro write_command_serialization_methods(command, is_return) %}
409 {% set Return = "Return" if is_return else "" %}
410 {% set Name = Return + command.name.CamelCase() %}
411 {% set Cmd = Name + "Cmd" %}
412
413 size_t {{Cmd}}::GetRequiredSize() const {
414 size_t size = sizeof({{Name}}Transfer) + {{Name}}GetExtraRequiredSize(*this);
415 return size;
416 }
417
Austin Engbd3f5862021-02-25 20:21:25 +0000418 WireResult {{Cmd}}::Serialize(size_t commandSize, SerializeBuffer* buffer
Austin Engdc7971c2021-09-10 20:36:20 +0000419 {%- if command.may_have_dawn_object -%}
420 , const ObjectIdProvider& provider
Austin Engc7f416c2019-01-15 20:49:53 +0000421 {%- endif -%}
422 ) const {
Austin Eng1b31dc02021-02-17 22:14:56 +0000423 {{Name}}Transfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000424 WIRE_TRY(buffer->Next(&transfer));
Austin Engcac04422020-10-13 22:35:34 +0000425 transfer->commandSize = commandSize;
Austin Engc7f416c2019-01-15 20:49:53 +0000426
Austin Engbd3f5862021-02-25 20:21:25 +0000427 WIRE_TRY({{Name}}Serialize(*this, transfer, buffer
Austin Eng76a8d0b2020-04-03 17:37:48 +0000428 {%- if command.may_have_dawn_object -%}
Austin Engdc7971c2021-09-10 20:36:20 +0000429 , provider
Austin Engc7f416c2019-01-15 20:49:53 +0000430 {%- endif -%}
Austin Eng1b31dc02021-02-17 22:14:56 +0000431 ));
Austin Engbd3f5862021-02-25 20:21:25 +0000432 return WireResult::Success;
Austin Engc7f416c2019-01-15 20:49:53 +0000433 }
434
Austin Engbd3f5862021-02-25 20:21:25 +0000435 WireResult {{Cmd}}::Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator
Austin Eng76a8d0b2020-04-03 17:37:48 +0000436 {%- if command.may_have_dawn_object -%}
Austin Engc7f416c2019-01-15 20:49:53 +0000437 , const ObjectIdResolver& resolver
438 {%- endif -%}
439 ) {
Austin Eng51db53f2021-02-18 19:28:29 +0000440 const volatile {{Name}}Transfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000441 WIRE_TRY(deserializeBuffer->Read(&transfer));
Austin Engc7f416c2019-01-15 20:49:53 +0000442
Austin Eng51db53f2021-02-18 19:28:29 +0000443 return {{Name}}Deserialize(this, transfer, deserializeBuffer, allocator
Austin Eng76a8d0b2020-04-03 17:37:48 +0000444 {%- if command.may_have_dawn_object -%}
Austin Engc7f416c2019-01-15 20:49:53 +0000445 , resolver
446 {%- endif -%}
447 );
448 }
449{% endmacro %}
450
Corentin Wallezbdc86772018-07-26 15:07:57 +0200451namespace dawn_wire {
Corentin Wallez88fb8fa2018-06-06 17:36:49 +0200452
Austin Eng8eb83852019-10-07 20:38:47 +0000453 ObjectHandle::ObjectHandle() = default;
Austin Eng518c8e72020-04-13 17:50:51 +0000454 ObjectHandle::ObjectHandle(ObjectId id, ObjectGeneration generation)
455 : id(id), generation(generation) {
456 }
Corentin Wallez00b90ea2020-04-24 17:02:53 +0000457
Austin Eng518c8e72020-04-13 17:50:51 +0000458 ObjectHandle::ObjectHandle(const volatile ObjectHandle& rhs)
459 : id(rhs.id), generation(rhs.generation) {
460 }
Corentin Wallez00b90ea2020-04-24 17:02:53 +0000461 ObjectHandle& ObjectHandle::operator=(const volatile ObjectHandle& rhs) {
462 id = rhs.id;
463 generation = rhs.generation;
464 return *this;
465 }
466
Austin Engb0cdf952019-10-15 07:30:35 +0000467 ObjectHandle& ObjectHandle::AssignFrom(const ObjectHandle& rhs) {
468 id = rhs.id;
Austin Eng518c8e72020-04-13 17:50:51 +0000469 generation = rhs.generation;
Austin Engb0cdf952019-10-15 07:30:35 +0000470 return *this;
471 }
472 ObjectHandle& ObjectHandle::AssignFrom(const volatile ObjectHandle& rhs) {
Austin Eng8eb83852019-10-07 20:38:47 +0000473 id = rhs.id;
Austin Eng518c8e72020-04-13 17:50:51 +0000474 generation = rhs.generation;
Austin Eng8eb83852019-10-07 20:38:47 +0000475 return *this;
476 }
477
Corentin Wallez40e72d72018-06-08 18:30:50 +0200478 namespace {
Corentin Wallez40e72d72018-06-08 18:30:50 +0200479 // Allocates enough space from allocator to countain T[count] and return it in out.
480 // Return FatalError if the allocator couldn't allocate the memory.
Austin Eng51db53f2021-02-18 19:28:29 +0000481 // Always writes to |out| on success.
482 template <typename T, typename N>
Austin Engbd3f5862021-02-25 20:21:25 +0000483 WireResult GetSpace(DeserializeAllocator* allocator, N count, T** out) {
Corentin Walleza19c7592019-01-04 09:54:10 +0000484 constexpr size_t kMaxCountWithoutOverflows = std::numeric_limits<size_t>::max() / sizeof(T);
485 if (count > kMaxCountWithoutOverflows) {
Austin Engbd3f5862021-02-25 20:21:25 +0000486 return WireResult::FatalError;
Corentin Walleza19c7592019-01-04 09:54:10 +0000487 }
488
Corentin Wallez40e72d72018-06-08 18:30:50 +0200489 size_t totalSize = sizeof(T) * count;
490 *out = static_cast<T*>(allocator->GetSpace(totalSize));
491 if (*out == nullptr) {
Austin Engbd3f5862021-02-25 20:21:25 +0000492 return WireResult::FatalError;
Corentin Wallez40e72d72018-06-08 18:30:50 +0200493 }
Corentin Wallez88fb8fa2018-06-06 17:36:49 +0200494
Austin Engbd3f5862021-02-25 20:21:25 +0000495 return WireResult::Success;
Corentin Wallez88fb8fa2018-06-06 17:36:49 +0200496 }
497
Austin Eng76a8d0b2020-04-03 17:37:48 +0000498 size_t GetChainedStructExtraRequiredSize(const WGPUChainedStruct* chainedStruct);
Austin Engbffc9662021-09-17 15:36:00 +0000499 DAWN_NO_DISCARD WireResult SerializeChainedStruct(const WGPUChainedStruct* chainedStruct,
Austin Engbd3f5862021-02-25 20:21:25 +0000500 SerializeBuffer* buffer,
501 const ObjectIdProvider& provider);
502 WireResult DeserializeChainedStruct(const WGPUChainedStruct** outChainNext,
Austin Engbffc9662021-09-17 15:36:00 +0000503 DeserializeBuffer* deserializeBuffer,
504 DeserializeAllocator* allocator,
505 const ObjectIdResolver& resolver);
506
507 size_t GetChainedStructExtraRequiredSize(WGPUChainedStructOut* chainedStruct);
508 DAWN_NO_DISCARD WireResult SerializeChainedStruct(WGPUChainedStructOut* chainedStruct,
509 SerializeBuffer* buffer,
510 const ObjectIdProvider& provider);
511 WireResult DeserializeChainedStruct(WGPUChainedStructOut** outChainNext,
512 DeserializeBuffer* deserializeBuffer,
513 DeserializeAllocator* allocator,
514 const ObjectIdResolver& resolver);
Austin Eng76a8d0b2020-04-03 17:37:48 +0000515
Austin Engc7f416c2019-01-15 20:49:53 +0000516 //* Output structure [de]serialization first because it is used by commands.
Corentin Wallez40e72d72018-06-08 18:30:50 +0200517 {% for type in by_category["structure"] %}
518 {% set name = as_cType(type.name) %}
Corentin Wallez67ab1ea2019-06-06 16:19:15 +0000519 {% if type.name.CamelCase() not in client_side_structures %}
520 {{write_record_serialization_helpers(type, name, type.members,
521 is_cmd=False)}}
522 {% endif %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200523 {% endfor %}
524
Austin Engbffc9662021-09-17 15:36:00 +0000525{% macro make_chained_struct_serialization_helpers(out) %}
526 {% set ChainedStructPtr = "WGPUChainedStructOut*" if out else "const WGPUChainedStruct*" %}
527 {% set ChainedStruct = "WGPUChainedStructOut" if out else "WGPUChainedStruct" %}
528 size_t GetChainedStructExtraRequiredSize({{ChainedStructPtr}} chainedStruct) {
Austin Eng76a8d0b2020-04-03 17:37:48 +0000529 ASSERT(chainedStruct != nullptr);
530 size_t result = 0;
531 while (chainedStruct != nullptr) {
532 switch (chainedStruct->sType) {
Austin Engbffc9662021-09-17 15:36:00 +0000533 {% for sType in types["s type"].values if (
534 sType.valid and
535 (sType.name.CamelCase() not in client_side_structures) and
536 (types[sType.name.get()].output == out)
537 ) %}
Austin Eng76a8d0b2020-04-03 17:37:48 +0000538 case {{as_cEnum(types["s type"].name, sType.name)}}: {
539 const auto& typedStruct = *reinterpret_cast<{{as_cType(sType.name)}} const *>(chainedStruct);
540 result += sizeof({{as_cType(sType.name)}}Transfer);
541 result += {{as_cType(sType.name)}}GetExtraRequiredSize(typedStruct);
542 chainedStruct = typedStruct.chain.next;
543 break;
544 }
545 {% endfor %}
Austin Engbffc9662021-09-17 15:36:00 +0000546 // Explicitly list the Invalid enum. MSVC complains about no case labels.
547 case WGPUSType_Invalid:
Austin Eng76a8d0b2020-04-03 17:37:48 +0000548 default:
549 // Invalid enum. Reserve space just for the transfer header (sType and hasNext).
Austin Eng76a8d0b2020-04-03 17:37:48 +0000550 result += sizeof(WGPUChainedStructTransfer);
Austin Eng65a903b2021-02-01 16:48:18 +0000551 chainedStruct = chainedStruct->next;
552 break;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000553 }
554 }
555 return result;
556 }
557
Austin Engbffc9662021-09-17 15:36:00 +0000558 DAWN_NO_DISCARD WireResult SerializeChainedStruct({{ChainedStructPtr}} chainedStruct,
Austin Engbd3f5862021-02-25 20:21:25 +0000559 SerializeBuffer* buffer,
560 const ObjectIdProvider& provider) {
Austin Eng76a8d0b2020-04-03 17:37:48 +0000561 ASSERT(chainedStruct != nullptr);
562 ASSERT(buffer != nullptr);
563 do {
564 switch (chainedStruct->sType) {
Austin Engbffc9662021-09-17 15:36:00 +0000565 {% for sType in types["s type"].values if (
566 sType.valid and
567 (sType.name.CamelCase() not in client_side_structures) and
568 (types[sType.name.get()].output == out)
569 ) %}
Austin Eng76a8d0b2020-04-03 17:37:48 +0000570 {% set CType = as_cType(sType.name) %}
571 case {{as_cEnum(types["s type"].name, sType.name)}}: {
572
Austin Eng1b31dc02021-02-17 22:14:56 +0000573 {{CType}}Transfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000574 WIRE_TRY(buffer->Next(&transfer));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000575 transfer->chain.sType = chainedStruct->sType;
576 transfer->chain.hasNext = chainedStruct->next != nullptr;
577
Austin Engbd3f5862021-02-25 20:21:25 +0000578 WIRE_TRY({{CType}}Serialize(*reinterpret_cast<{{CType}} const*>(chainedStruct), transfer, buffer
Austin Eng76a8d0b2020-04-03 17:37:48 +0000579 {%- if types[sType.name.get()].may_have_dawn_object -%}
580 , provider
581 {%- endif -%}
Austin Eng1b31dc02021-02-17 22:14:56 +0000582 ));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000583
584 chainedStruct = chainedStruct->next;
585 } break;
586 {% endfor %}
Austin Engbffc9662021-09-17 15:36:00 +0000587 // Explicitly list the Invalid enum. MSVC complains about no case labels.
588 case WGPUSType_Invalid:
Austin Eng76a8d0b2020-04-03 17:37:48 +0000589 default: {
590 // Invalid enum. Serialize just the transfer header with Invalid as the sType.
591 // TODO(crbug.com/dawn/369): Unknown sTypes are silently discarded.
Austin Eng65a903b2021-02-01 16:48:18 +0000592 if (chainedStruct->sType != WGPUSType_Invalid) {
593 dawn::WarningLog() << "Unknown sType " << chainedStruct->sType << " discarded.";
594 }
595
Austin Eng1b31dc02021-02-17 22:14:56 +0000596 WGPUChainedStructTransfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000597 WIRE_TRY(buffer->Next(&transfer));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000598 transfer->sType = WGPUSType_Invalid;
Austin Eng65a903b2021-02-01 16:48:18 +0000599 transfer->hasNext = chainedStruct->next != nullptr;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000600
Austin Eng65a903b2021-02-01 16:48:18 +0000601 // Still move on in case there are valid structs after this.
602 chainedStruct = chainedStruct->next;
603 break;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000604 }
605 }
606 } while (chainedStruct != nullptr);
Austin Engbd3f5862021-02-25 20:21:25 +0000607 return WireResult::Success;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000608 }
609
Austin Engbffc9662021-09-17 15:36:00 +0000610 WireResult DeserializeChainedStruct({{ChainedStructPtr}}* outChainNext,
611 DeserializeBuffer* deserializeBuffer,
612 DeserializeAllocator* allocator,
613 const ObjectIdResolver& resolver) {
Austin Eng76a8d0b2020-04-03 17:37:48 +0000614 bool hasNext;
615 do {
Austin Eng51db53f2021-02-18 19:28:29 +0000616 const volatile WGPUChainedStructTransfer* header;
Austin Engbd3f5862021-02-25 20:21:25 +0000617 WIRE_TRY(deserializeBuffer->Peek(&header));
Austin Eng51db53f2021-02-18 19:28:29 +0000618 WGPUSType sType = header->sType;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000619 switch (sType) {
Austin Engbffc9662021-09-17 15:36:00 +0000620 {% for sType in types["s type"].values if (
621 sType.valid and
622 (sType.name.CamelCase() not in client_side_structures) and
623 (types[sType.name.get()].output == out)
624 ) %}
Austin Eng76a8d0b2020-04-03 17:37:48 +0000625 {% set CType = as_cType(sType.name) %}
626 case {{as_cEnum(types["s type"].name, sType.name)}}: {
Austin Eng51db53f2021-02-18 19:28:29 +0000627 const volatile {{CType}}Transfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000628 WIRE_TRY(deserializeBuffer->Read(&transfer));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000629
Austin Eng51db53f2021-02-18 19:28:29 +0000630 {{CType}}* outStruct;
Austin Engbd3f5862021-02-25 20:21:25 +0000631 WIRE_TRY(GetSpace(allocator, sizeof({{CType}}), &outStruct));
Austin Eng76a8d0b2020-04-03 17:37:48 +0000632 outStruct->chain.sType = sType;
633 outStruct->chain.next = nullptr;
634
635 *outChainNext = &outStruct->chain;
636 outChainNext = &outStruct->chain.next;
637
Austin Engbd3f5862021-02-25 20:21:25 +0000638 WIRE_TRY({{CType}}Deserialize(outStruct, transfer, deserializeBuffer, allocator
Austin Eng76a8d0b2020-04-03 17:37:48 +0000639 {%- if types[sType.name.get()].may_have_dawn_object -%}
640 , resolver
641 {%- endif -%}
642 ));
643
644 hasNext = transfer->chain.hasNext;
645 } break;
646 {% endfor %}
Austin Engbffc9662021-09-17 15:36:00 +0000647 // Explicitly list the Invalid enum. MSVC complains about no case labels.
648 case WGPUSType_Invalid:
Austin Eng65a903b2021-02-01 16:48:18 +0000649 default: {
650 // Invalid enum. Deserialize just the transfer header with Invalid as the sType.
651 // TODO(crbug.com/dawn/369): Unknown sTypes are silently discarded.
652 if (sType != WGPUSType_Invalid) {
653 dawn::WarningLog() << "Unknown sType " << sType << " discarded.";
654 }
655
Austin Eng51db53f2021-02-18 19:28:29 +0000656 const volatile WGPUChainedStructTransfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000657 WIRE_TRY(deserializeBuffer->Read(&transfer));
Austin Eng65a903b2021-02-01 16:48:18 +0000658
Austin Engbffc9662021-09-17 15:36:00 +0000659 {{ChainedStruct}}* outStruct;
660 WIRE_TRY(GetSpace(allocator, sizeof({{ChainedStruct}}), &outStruct));
Austin Eng65a903b2021-02-01 16:48:18 +0000661 outStruct->sType = WGPUSType_Invalid;
662 outStruct->next = nullptr;
663
664 // Still move on in case there are valid structs after this.
665 *outChainNext = outStruct;
666 outChainNext = &outStruct->next;
667 hasNext = transfer->hasNext;
668 break;
669 }
Austin Eng76a8d0b2020-04-03 17:37:48 +0000670 }
671 } while (hasNext);
672
Austin Engbd3f5862021-02-25 20:21:25 +0000673 return WireResult::Success;
Austin Eng76a8d0b2020-04-03 17:37:48 +0000674 }
Austin Engbffc9662021-09-17 15:36:00 +0000675{% endmacro %}
676
677{{ make_chained_struct_serialization_helpers(False) }}
678{{ make_chained_struct_serialization_helpers(True) }}
Austin Eng76a8d0b2020-04-03 17:37:48 +0000679
Austin Engc7f416c2019-01-15 20:49:53 +0000680 //* Output [de]serialization helpers for commands
681 {% for command in cmd_records["command"] %}
682 {% set name = command.name.CamelCase() %}
683 {{write_record_serialization_helpers(command, name, command.members,
Corentin Wallezcb2c64f2019-04-01 21:04:17 +0000684 is_cmd=True)}}
Austin Engc7f416c2019-01-15 20:49:53 +0000685 {% endfor %}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200686
Austin Engc7f416c2019-01-15 20:49:53 +0000687 //* Output [de]serialization helpers for return commands
688 {% for command in cmd_records["return command"] %}
689 {% set name = command.name.CamelCase() %}
690 {{write_record_serialization_helpers(command, name, command.members,
Corentin Wallezcb2c64f2019-04-01 21:04:17 +0000691 is_cmd=True, is_return_command=True)}}
Corentin Wallez40e72d72018-06-08 18:30:50 +0200692 {% endfor %}
693 } // anonymous namespace
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400694
Austin Engc7f416c2019-01-15 20:49:53 +0000695 {% for command in cmd_records["command"] %}
696 {{ write_command_serialization_methods(command, False) }}
697 {% endfor %}
Corentin Wallez88fb8fa2018-06-06 17:36:49 +0200698
Austin Engc7f416c2019-01-15 20:49:53 +0000699 {% for command in cmd_records["return command"] %}
700 {{ write_command_serialization_methods(command, True) }}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400701 {% endfor %}
702
Austin Engdc7971c2021-09-10 20:36:20 +0000703 // Implementation of ObjectIdResolver that always errors.
704 // Used when the generator adds a provider argument because of a chained
705 // struct, but in practice, a chained struct in that location is invalid.
706 class ErrorObjectIdResolver final : public ObjectIdResolver {
707 public:
708 {% for type in by_category["object"] %}
709 WireResult GetFromId(ObjectId id, {{as_cType(type.name)}}* out) const override {
710 return WireResult::FatalError;
711 }
712 WireResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const override {
713 return WireResult::FatalError;
714 }
715 {% endfor %}
716 };
717
718 // Implementation of ObjectIdProvider that always errors.
719 // Used when the generator adds a provider argument because of a chained
720 // struct, but in practice, a chained struct in that location is invalid.
721 class ErrorObjectIdProvider final : public ObjectIdProvider {
722 public:
723 {% for type in by_category["object"] %}
724 WireResult GetId({{as_cType(type.name)}} object, ObjectId* out) const override {
725 return WireResult::FatalError;
726 }
727 WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const override {
728 return WireResult::FatalError;
729 }
730 {% endfor %}
731 };
732
Corentin Wallez1fdcb162019-10-24 22:27:27 +0000733 // Implementations of serialization/deserialization of WPGUDeviceProperties.
734 size_t SerializedWGPUDevicePropertiesSize(const WGPUDeviceProperties* deviceProperties) {
735 return sizeof(WGPUDeviceProperties) +
Corentin Wallez2c8b5c62019-10-21 20:04:10 +0000736 WGPUDevicePropertiesGetExtraRequiredSize(*deviceProperties);
Jiawei Shao5c2f5f32019-10-20 03:01:56 +0000737 }
738
Corentin Wallez1fdcb162019-10-24 22:27:27 +0000739 void SerializeWGPUDeviceProperties(const WGPUDeviceProperties* deviceProperties,
Austin Eng1b31dc02021-02-17 22:14:56 +0000740 char* buffer) {
741 SerializeBuffer serializeBuffer(buffer, SerializedWGPUDevicePropertiesSize(deviceProperties));
Jiawei Shao5c2f5f32019-10-20 03:01:56 +0000742
Austin Eng1b31dc02021-02-17 22:14:56 +0000743 WGPUDevicePropertiesTransfer* transfer;
Austin Engbd3f5862021-02-25 20:21:25 +0000744
745 WireResult result = serializeBuffer.Next(&transfer);
746 ASSERT(result == WireResult::Success);
747
Austin Eng02fbf162021-09-13 18:49:09 +0000748 ErrorObjectIdProvider provider;
749 result = WGPUDevicePropertiesSerialize(*deviceProperties, transfer, &serializeBuffer, provider);
Austin Engbd3f5862021-02-25 20:21:25 +0000750 ASSERT(result == WireResult::Success);
Jiawei Shao5c2f5f32019-10-20 03:01:56 +0000751 }
752
Corentin Wallez1fdcb162019-10-24 22:27:27 +0000753 bool DeserializeWGPUDeviceProperties(WGPUDeviceProperties* deviceProperties,
Austin Eng51db53f2021-02-18 19:28:29 +0000754 const volatile char* buffer,
755 size_t size) {
756 const volatile WGPUDevicePropertiesTransfer* transfer;
757 DeserializeBuffer deserializeBuffer(buffer, size);
Austin Engbd3f5862021-02-25 20:21:25 +0000758 if (deserializeBuffer.Read(&transfer) != WireResult::Success) {
Jiawei Shao5c2f5f32019-10-20 03:01:56 +0000759 return false;
760 }
761
Austin Eng02fbf162021-09-13 18:49:09 +0000762 ErrorObjectIdResolver resolver;
Corentin Wallez2c8b5c62019-10-21 20:04:10 +0000763 return WGPUDevicePropertiesDeserialize(deviceProperties, transfer, &deserializeBuffer,
Austin Eng02fbf162021-09-13 18:49:09 +0000764 nullptr, resolver) == WireResult::Success;
Jiawei Shao5c2f5f32019-10-20 03:01:56 +0000765 }
766
Austin Engbffc9662021-09-17 15:36:00 +0000767 size_t SerializedWGPUSupportedLimitsSize(const WGPUSupportedLimits* supportedLimits) {
768 return sizeof(WGPUSupportedLimits) +
769 WGPUSupportedLimitsGetExtraRequiredSize(*supportedLimits);
770 }
771
772 void SerializeWGPUSupportedLimits(
773 const WGPUSupportedLimits* supportedLimits,
774 char* buffer) {
775 SerializeBuffer serializeBuffer(buffer, SerializedWGPUSupportedLimitsSize(supportedLimits));
776
777 WGPUSupportedLimitsTransfer* transfer;
778
779 WireResult result = serializeBuffer.Next(&transfer);
780 ASSERT(result == WireResult::Success);
781
782 ErrorObjectIdProvider provider;
783 result = WGPUSupportedLimitsSerialize(*supportedLimits, transfer, &serializeBuffer, provider);
784 ASSERT(result == WireResult::Success);
785 }
786
787 bool DeserializeWGPUSupportedLimits(WGPUSupportedLimits* supportedLimits,
788 const volatile char* buffer,
789 size_t size) {
790 const volatile WGPUSupportedLimitsTransfer* transfer;
791 DeserializeBuffer deserializeBuffer(buffer, size);
792 if (deserializeBuffer.Read(&transfer) != WireResult::Success) {
793 return false;
794 }
795
796 ErrorObjectIdResolver resolver;
797 return WGPUSupportedLimitsDeserialize(supportedLimits, transfer, &deserializeBuffer,
798 nullptr, resolver) == WireResult::Success;
799 }
800
Corentin Wallezbdc86772018-07-26 15:07:57 +0200801} // namespace dawn_wire