[dawn][native] Add NextNullTerminatedString

This mirrors AddNullTerminatedString and will make it easy to change the
handling of the length at the same time in both.

Done mostly with these two commands:

git grep -l "NextData<char>" | xargs sed -i "" "s/Span<const char> label = \(.*\)\.NextData<char>(\(.*\) + 1);/std::string_view label = NextNullTerminatedString(\&\1, \2);/"
git grep -l "NextData<char>" | xargs sed -i "" "s/Span<const char> label = \(.*\)\->NextData<char>(\(.*\) + 1);/std::string_view label = NextNullTerminatedString(\1, \2);/"

Also add a NextNSString used in the Metal backend.

Bug: 528305452
Change-Id: I4e2b722311ac093fcd42b3d7e1faa38d8290b371
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/324375
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/Commands.cpp b/src/dawn/native/Commands.cpp
index dd97f95..e0afbfa 100644
--- a/src/dawn/native/Commands.cpp
+++ b/src/dawn/native/Commands.cpp
@@ -448,6 +448,12 @@
     return out;
 }
 
+std::string_view NextNullTerminatedString(CommandIterator* iterator, size_t length) {
+    Span<const char> data = iterator->NextData<char>(length + 1);
+    DAWN_ASSERT(data[data.size() - 1] == '\0');  // The string is null-terminated.
+    return {data.begin(), data.end()};
+}
+
 TimestampWrites::TimestampWrites() = default;
 TimestampWrites::~TimestampWrites() = default;
 
diff --git a/src/dawn/native/Commands.h b/src/dawn/native/Commands.h
index 5f4eafd..2867e49 100644
--- a/src/dawn/native/Commands.h
+++ b/src/dawn/native/Commands.h
@@ -44,6 +44,7 @@
 namespace dawn::native {
 
 class CommandAllocator;
+class CommandIterator;
 struct TexelBlockInfo;
 struct TexelCopyTextureInfo;
 
@@ -478,6 +479,8 @@
 
 // Helper function to copy a wgpu::StringView into a safely null-terminated C-string in commands.
 const char* AddNullTerminatedString(CommandAllocator* allocator, StringView s, size_t* length);
+// Mirror function that gets the same string back as a null-terminated string_view.
+std::string_view NextNullTerminatedString(CommandIterator* iterator, size_t length);
 
 }  // namespace dawn::native
 
diff --git a/src/dawn/native/d3d12/CommandBufferD3D12.cpp b/src/dawn/native/d3d12/CommandBufferD3D12.cpp
index f40d03f..973e76d 100644
--- a/src/dawn/native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn/native/d3d12/CommandBufferD3D12.cpp
@@ -1356,7 +1356,7 @@
 
             case Command::InsertDebugMarker: {
                 InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
 
                 if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
                     // PIX color is 1 byte per channel in ARGB format
@@ -1380,7 +1380,7 @@
 
             case Command::PushDebugGroup: {
                 PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
 
                 if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
                     // PIX color is 1 byte per channel in ARGB format
@@ -1542,7 +1542,7 @@
 
             case Command::InsertDebugMarker: {
                 InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
 
                 if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
                     // PIX color is 1 byte per channel in ARGB format
@@ -1566,7 +1566,7 @@
 
             case Command::PushDebugGroup: {
                 PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
 
                 if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
                     // PIX color is 1 byte per channel in ARGB format
@@ -1940,7 +1940,7 @@
 
             case Command::InsertDebugMarker: {
                 InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = iter->NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(iter, cmd->length);
 
                 if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
                     // PIX color is 1 byte per channel in ARGB format
@@ -1964,7 +1964,7 @@
 
             case Command::PushDebugGroup: {
                 PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = iter->NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(iter, cmd->length);
 
                 if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
                     // PIX color is 1 byte per channel in ARGB format
diff --git a/src/dawn/native/metal/CommandBufferMTL.mm b/src/dawn/native/metal/CommandBufferMTL.mm
index f1f5b3a..86b047d 100644
--- a/src/dawn/native/metal/CommandBufferMTL.mm
+++ b/src/dawn/native/metal/CommandBufferMTL.mm
@@ -72,6 +72,14 @@
     }
 }
 
+NSRef<NSString> NextNSString(CommandIterator* iter, size_t length) {
+    std::string_view s = NextNullTerminatedString(iter, length);
+    DAWN_ASSERT(s[s.length() - 1] == '\0');
+    return AcquireNSRef([[NSString alloc] initWithBytes:s.data()
+                                                 length:s.length() - 1
+                                               encoding:NSUTF8StringEncoding]);
+}
+
 template <typename PassDescriptor>
 class SampleBufferAttachment {
   public:
@@ -1523,10 +1531,8 @@
 
             case Command::PushDebugGroup: {
                 PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
-                NSRef<NSString> mtlLabel =
-                    AcquireNSRef([[NSString alloc] initWithUTF8String:label.data()]);
-                [commandContext->GetCommands() pushDebugGroup:mtlLabel.Get()];
+                NSRef<NSString> label = NextNSString(&mCommands, cmd->length);
+                [commandContext->GetCommands() pushDebugGroup:label.Get()];
                 break;
             }
 
@@ -1716,10 +1722,8 @@
 
             case Command::InsertDebugMarker: {
                 InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
-                NSRef<NSString> mtlLabel =
-                    AcquireNSRef([[NSString alloc] initWithUTF8String:label.data()]);
-                [encoder insertDebugSignpost:mtlLabel.Get()];
+                NSRef<NSString> label = NextNSString(&mCommands, cmd->length);
+                [encoder insertDebugSignpost:label.Get()];
                 break;
             }
 
@@ -1732,10 +1736,8 @@
 
             case Command::PushDebugGroup: {
                 PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
-                NSRef<NSString> mtlLabel =
-                    AcquireNSRef([[NSString alloc] initWithUTF8String:label.data()]);
-                [encoder pushDebugGroup:mtlLabel.Get()];
+                NSRef<NSString> label = NextNSString(&mCommands, cmd->length);
+                [encoder pushDebugGroup:label.Get()];
                 break;
             }
 
@@ -1951,10 +1953,8 @@
 
             case Command::InsertDebugMarker: {
                 InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = iter->NextData<char>(cmd->length + 1);
-                NSRef<NSString> mtlLabel =
-                    AcquireNSRef([[NSString alloc] initWithUTF8String:label.data()]);
-                [encoder insertDebugSignpost:mtlLabel.Get()];
+                NSRef<NSString> label = NextNSString(iter, cmd->length);
+                [encoder insertDebugSignpost:label.Get()];
                 break;
             }
 
@@ -1967,10 +1967,8 @@
 
             case Command::PushDebugGroup: {
                 PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = iter->NextData<char>(cmd->length + 1);
-                NSRef<NSString> mtlLabel =
-                    AcquireNSRef([[NSString alloc] initWithUTF8String:label.data()]);
-                [encoder pushDebugGroup:mtlLabel.Get()];
+                NSRef<NSString> label = NextNSString(iter, cmd->length);
+                [encoder pushDebugGroup:label.Get()];
                 break;
             }
 
diff --git a/src/dawn/native/vulkan/CommandBufferVk.cpp b/src/dawn/native/vulkan/CommandBufferVk.cpp
index 92e938b..8d3be5a 100644
--- a/src/dawn/native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn/native/vulkan/CommandBufferVk.cpp
@@ -1468,7 +1468,7 @@
             case Command::InsertDebugMarker: {
                 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                     InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
-                    Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                    std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                     VkDebugUtilsLabelEXT utilsLabel;
                     utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                     utilsLabel.pNext = nullptr;
@@ -1498,7 +1498,7 @@
             case Command::PushDebugGroup: {
                 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                     PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                    Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                    std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                     VkDebugUtilsLabelEXT utilsLabel;
                     utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                     utilsLabel.pNext = nullptr;
@@ -1644,7 +1644,7 @@
             case Command::InsertDebugMarker: {
                 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                     InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
-                    Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                    std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                     VkDebugUtilsLabelEXT utilsLabel;
                     utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                     utilsLabel.pNext = nullptr;
@@ -1674,7 +1674,7 @@
             case Command::PushDebugGroup: {
                 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                     PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                    Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                    std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                     VkDebugUtilsLabelEXT utilsLabel;
                     utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                     utilsLabel.pNext = nullptr;
@@ -1909,7 +1909,7 @@
             case Command::InsertDebugMarker: {
                 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                     InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
-                    Span<const char> label = iter->NextData<char>(cmd->length + 1);
+                    std::string_view label = NextNullTerminatedString(iter, cmd->length);
                     VkDebugUtilsLabelEXT utilsLabel;
                     utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                     utilsLabel.pNext = nullptr;
@@ -1939,7 +1939,7 @@
             case Command::PushDebugGroup: {
                 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
                     PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
-                    Span<const char> label = iter->NextData<char>(cmd->length + 1);
+                    std::string_view label = NextNullTerminatedString(iter, cmd->length);
                     VkDebugUtilsLabelEXT utilsLabel;
                     utilsLabel.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
                     utilsLabel.pNext = nullptr;
diff --git a/src/dawn/native/webgpu/CommandBufferHelpers.cpp b/src/dawn/native/webgpu/CommandBufferHelpers.cpp
index 0d799fd..48c2a3b 100644
--- a/src/dawn/native/webgpu/CommandBufferHelpers.cpp
+++ b/src/dawn/native/webgpu/CommandBufferHelpers.cpp
@@ -84,7 +84,7 @@
     switch (type) {
         case Command::PushDebugGroup: {
             const auto& cmd = *commands.NextCommand<PushDebugGroupCmd>();
-            Span<const char> label = commands.NextData<char>(cmd.length + 1);
+            std::string_view label = NextNullTerminatedString(&commands, cmd.length);
             schema::CommandBufferCommandPushDebugGroupCmd data{{
                 .data = {{
                     .groupLabel = {label.begin(), label.end()},
@@ -100,7 +100,7 @@
         }
         case Command::InsertDebugMarker: {
             const auto& cmd = *commands.NextCommand<InsertDebugMarkerCmd>();
-            Span<const char> label = commands.NextData<char>(cmd.length + 1);
+            std::string_view label = NextNullTerminatedString(&commands, cmd.length);
             schema::CommandBufferCommandInsertDebugMarkerCmd data{{
                 .data = {{
                     .markerLabel = {label.begin(), label.end()},
diff --git a/src/dawn/native/webgpu/CommandBufferWGPU.cpp b/src/dawn/native/webgpu/CommandBufferWGPU.cpp
index c2c9b81..5a4d79c 100644
--- a/src/dawn/native/webgpu/CommandBufferWGPU.cpp
+++ b/src/dawn/native/webgpu/CommandBufferWGPU.cpp
@@ -158,7 +158,7 @@
             }
             case Command::InsertDebugMarker: {
                 auto cmd = commands.NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = commands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                 wgpu.computePassEncoderInsertDebugMarker(passEncoder, {label.data(), label.size()});
                 break;
             }
@@ -171,7 +171,7 @@
 
             case Command::PushDebugGroup: {
                 auto cmd = commands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = commands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                 wgpu.computePassEncoderPushDebugGroup(passEncoder, {label.data(), label.size()});
                 break;
             }
@@ -369,7 +369,7 @@
 
             case Command::InsertDebugMarker: {
                 auto cmd = commands.NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = commands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                 wgpu.renderPassEncoderInsertDebugMarker(passEncoder, {label.data(), label.size()});
                 break;
             }
@@ -382,7 +382,7 @@
 
             case Command::PushDebugGroup: {
                 auto cmd = commands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = commands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&commands, cmd->length);
                 wgpu.renderPassEncoderPushDebugGroup(passEncoder, {label.data(), label.size()});
                 break;
             }
@@ -1111,7 +1111,7 @@
             }
             case Command::InsertDebugMarker: {
                 auto cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                 wgpu.commandEncoderInsertDebugMarker(innerEncoder, {label.data(), label.size()});
                 break;
             }
@@ -1122,7 +1122,7 @@
             }
             case Command::PushDebugGroup: {
                 auto cmd = mCommands.NextCommand<PushDebugGroupCmd>();
-                Span<const char> label = mCommands.NextData<char>(cmd->length + 1);
+                std::string_view label = NextNullTerminatedString(&mCommands, cmd->length);
                 wgpu.commandEncoderPushDebugGroup(innerEncoder, {label.data(), label.size()});
                 break;
             }
diff --git a/src/dawn/native/webgpu/RenderBundleWGPU.cpp b/src/dawn/native/webgpu/RenderBundleWGPU.cpp
index 7ce8ba0..5dd562e 100644
--- a/src/dawn/native/webgpu/RenderBundleWGPU.cpp
+++ b/src/dawn/native/webgpu/RenderBundleWGPU.cpp
@@ -92,7 +92,7 @@
 
         case Command::InsertDebugMarker: {
             auto cmd = commands.NextCommand<InsertDebugMarkerCmd>();
-            Span<const char> label = commands.NextData<char>(cmd->length + 1);
+            std::string_view label = NextNullTerminatedString(&commands, cmd->length);
             wgpu.renderBundleEncoderInsertDebugMarker(encoder, {label.data(), label.size()});
             break;
         }
@@ -105,7 +105,7 @@
 
         case Command::PushDebugGroup: {
             auto cmd = commands.NextCommand<PushDebugGroupCmd>();
-            Span<const char> label = commands.NextData<char>(cmd->length + 1);
+            std::string_view label = NextNullTerminatedString(&commands, cmd->length);
             wgpu.renderBundleEncoderPushDebugGroup(encoder, {label.data(), label.size()});
             break;
         }