dawn_wire/client: Add ToAPI and FromAPI helpers.

In the client code, we often need to translate between WGPUObject (the
API type) to Object* (the internal client type). This added a bunch of
reinterpret_casts that make the code less readable and more fragile.

This CL adds FromAPI and ToAPI helpers in the autogenerated
ApiObjects_autogen.h header, that convert between API and internal types
in a type-safe way.

Bug: dawn:445

Change-Id: Ia1bf624f0315ced496b95cb660adf88abd916d71
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24063
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/generator/templates/dawn_wire/client/ApiObjects.h b/generator/templates/dawn_wire/client/ApiObjects.h
index 5c2ae3f..288c700 100644
--- a/generator/templates/dawn_wire/client/ApiObjects.h
+++ b/generator/templates/dawn_wire/client/ApiObjects.h
@@ -16,10 +16,24 @@
 #define DAWNWIRE_CLIENT_APIOBJECTS_AUTOGEN_H_
 
 namespace dawn_wire { namespace client {
-    {% for type in by_category["object"] if not type.name.CamelCase() in client_special_objects %}
-        struct {{type.name.CamelCase()}} : ObjectBase {
-            using ObjectBase::ObjectBase;
-        };
+
+    {% for type in by_category["object"] %}
+        {% set Type = type.name.CamelCase() %}
+        {% if type.name.CamelCase() in client_special_objects %}
+            class {{Type}};
+        {% else %}
+            struct {{type.name.CamelCase()}} : ObjectBase {
+                using ObjectBase::ObjectBase;
+            };
+        {% endif %}
+
+        inline {{Type}}* FromAPI(WGPU{{Type}} obj) {
+            return reinterpret_cast<{{Type}}*>(obj);
+        }
+        inline WGPU{{Type}} ToAPI({{Type}}* obj) {
+            return reinterpret_cast<WGPU{{Type}}>(obj);
+        }
+
     {% endfor %}
 }}  // namespace dawn_wire::client
 
diff --git a/src/dawn_wire/client/Buffer.cpp b/src/dawn_wire/client/Buffer.cpp
index 0b4889e..993b2b2 100644
--- a/src/dawn_wire/client/Buffer.cpp
+++ b/src/dawn_wire/client/Buffer.cpp
@@ -47,7 +47,6 @@
 
     // static
     WGPUBuffer Buffer::Create(Device* device_, const WGPUBufferDescriptor* descriptor) {
-        WGPUDevice cDevice = reinterpret_cast<WGPUDevice>(device_);
         Client* wireClient = device_->GetClient();
 
         if ((descriptor->usage & (WGPUBufferUsage_MapRead | WGPUBufferUsage_MapWrite)) != 0 &&
@@ -63,19 +62,18 @@
         buffer->mSize = descriptor->size;
 
         DeviceCreateBufferCmd cmd;
-        cmd.self = cDevice;
+        cmd.self = ToAPI(device_);
         cmd.descriptor = descriptor;
         cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
 
         wireClient->SerializeCommand(cmd);
 
-        return reinterpret_cast<WGPUBuffer>(buffer);
+        return ToAPI(buffer);
     }
 
     // static
     WGPUCreateBufferMappedResult Buffer::CreateMapped(Device* device_,
                                                       const WGPUBufferDescriptor* descriptor) {
-        WGPUDevice cDevice = reinterpret_cast<WGPUDevice>(device_);
         Client* wireClient = device_->GetClient();
 
         WGPUCreateBufferMappedResult result;
@@ -119,13 +117,13 @@
         buffer->mWriteHandle = std::move(writeHandle);
         buffer->mMappedData = result.data;
 
-        result.buffer = reinterpret_cast<WGPUBuffer>(buffer);
+        result.buffer = ToAPI(buffer);
 
         // Get the serialization size of the WriteHandle.
         size_t handleCreateInfoLength = buffer->mWriteHandle->SerializeCreateSize();
 
         DeviceCreateBufferMappedCmd cmd;
-        cmd.device = cDevice;
+        cmd.device = ToAPI(device_);
         cmd.descriptor = descriptor;
         cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
         cmd.handleCreateInfoLength = handleCreateInfoLength;
@@ -145,11 +143,11 @@
         auto* allocation = device_->GetClient()->BufferAllocator().New(device_);
 
         DeviceCreateErrorBufferCmd cmd;
-        cmd.self = reinterpret_cast<WGPUDevice>(device_);
+        cmd.self = ToAPI(device_);
         cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
         device_->GetClient()->SerializeCommand(cmd);
 
-        return reinterpret_cast<WGPUBuffer>(allocation->object.get());
+        return ToAPI(allocation->object.get());
     }
 
     Buffer::~Buffer() {
@@ -420,7 +418,7 @@
         ClearMapRequests(WGPUBufferMapAsyncStatus_Unknown);
 
         BufferUnmapCmd cmd;
-        cmd.self = reinterpret_cast<WGPUBuffer>(this);
+        cmd.self = ToAPI(this);
         device->GetClient()->SerializeCommand(cmd);
     }
 
@@ -432,7 +430,7 @@
         ClearMapRequests(WGPUBufferMapAsyncStatus_Unknown);
 
         BufferDestroyCmd cmd;
-        cmd.self = reinterpret_cast<WGPUBuffer>(this);
+        cmd.self = ToAPI(this);
         device->GetClient()->SerializeCommand(cmd);
     }
 
diff --git a/src/dawn_wire/client/Client.cpp b/src/dawn_wire/client/Client.cpp
index 1953347..ab96743 100644
--- a/src/dawn_wire/client/Client.cpp
+++ b/src/dawn_wire/client/Client.cpp
@@ -44,11 +44,11 @@
     }
 
     ReservedTexture Client::ReserveTexture(WGPUDevice cDevice) {
-        Device* device = reinterpret_cast<Device*>(cDevice);
+        Device* device = FromAPI(cDevice);
         ObjectAllocator<Texture>::ObjectAndSerial* allocation = TextureAllocator().New(device);
 
         ReservedTexture result;
-        result.texture = reinterpret_cast<WGPUTexture>(allocation->object.get());
+        result.texture = ToAPI(allocation->object.get());
         result.id = allocation->object->id;
         result.generation = allocation->generation;
         return result;
diff --git a/src/dawn_wire/client/Device.cpp b/src/dawn_wire/client/Device.cpp
index 4df6226..ce8aec4 100644
--- a/src/dawn_wire/client/Device.cpp
+++ b/src/dawn_wire/client/Device.cpp
@@ -31,7 +31,7 @@
         mDefaultQueue = allocation->object.get();
 
         DeviceGetDefaultQueueCmd cmd;
-        cmd.self = reinterpret_cast<WGPUDevice>(this);
+        cmd.self = ToAPI(this);
         cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
 
         mClient->SerializeCommand(cmd);
@@ -85,7 +85,7 @@
         mErrorScopeStackSize++;
 
         DevicePushErrorScopeCmd cmd;
-        cmd.self = reinterpret_cast<WGPUDevice>(this);
+        cmd.self = ToAPI(this);
         cmd.filter = filter;
 
         mClient->SerializeCommand(cmd);
@@ -103,7 +103,7 @@
         mErrorScopes[serial] = {callback, userdata};
 
         DevicePopErrorScopeCmd cmd;
-        cmd.device = reinterpret_cast<WGPUDevice>(this);
+        cmd.device = ToAPI(this);
         cmd.requestSerial = serial;
 
         mClient->SerializeCommand(cmd);
@@ -139,7 +139,7 @@
 
     void Device::InjectError(WGPUErrorType type, const char* message) {
         DeviceInjectErrorCmd cmd;
-        cmd.self = reinterpret_cast<WGPUDevice>(this);
+        cmd.self = ToAPI(this);
         cmd.type = type;
         cmd.message = message;
         mClient->SerializeCommand(cmd);
@@ -160,7 +160,7 @@
 
     WGPUQueue Device::GetDefaultQueue() {
         mDefaultQueue->refcount++;
-        return reinterpret_cast<WGPUQueue>(mDefaultQueue);
+        return ToAPI(mDefaultQueue);
     }
 
 }}  // namespace dawn_wire::client
diff --git a/src/dawn_wire/client/Queue.cpp b/src/dawn_wire/client/Queue.cpp
index f515f52..902aac8 100644
--- a/src/dawn_wire/client/Queue.cpp
+++ b/src/dawn_wire/client/Queue.cpp
@@ -23,18 +23,18 @@
         auto* allocation = device->GetClient()->FenceAllocator().New(device);
 
         QueueCreateFenceCmd cmd;
-        cmd.self = reinterpret_cast<WGPUQueue>(this);
+        cmd.self = ToAPI(this);
         cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
         cmd.descriptor = descriptor;
         device->GetClient()->SerializeCommand(cmd);
 
         Fence* fence = allocation->object.get();
         fence->Initialize(this, descriptor);
-        return reinterpret_cast<WGPUFence>(fence);
+        return ToAPI(fence);
     }
 
     void Queue::Signal(WGPUFence cFence, uint64_t signalValue) {
-        Fence* fence = reinterpret_cast<Fence*>(cFence);
+        Fence* fence = FromAPI(cFence);
         if (fence->GetQueue() != this) {
             device->InjectError(WGPUErrorType_Validation,
                                 "Fence must be signaled on the queue on which it was created.");
@@ -49,7 +49,7 @@
         fence->SetSignaledValue(signalValue);
 
         QueueSignalCmd cmd;
-        cmd.self = reinterpret_cast<WGPUQueue>(this);
+        cmd.self = ToAPI(this);
         cmd.fence = cFence;
         cmd.signalValue = signalValue;
 
@@ -60,7 +60,7 @@
                             uint64_t bufferOffset,
                             const void* data,
                             size_t size) {
-        Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer);
+        Buffer* buffer = FromAPI(cBuffer);
 
         QueueWriteBufferInternalCmd cmd;
         cmd.queueId = id;