Import Tint changes from Dawn

Changes:
  - cbcc0ce28b0b9692eccd3ff1c58fcda79f2c8f53 [tint][utils] Flesh out bytes utilities by Ben Clayton <bclayton@google.com>
  - 55dfb797443039e7858a3f0ecfa09e9cd823c058 clang-format by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: cbcc0ce28b0b9692eccd3ff1c58fcda79f2c8f53
Change-Id: I9c926a6ef9dfb7c775292b7c089022b880ddf952
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/167860
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/utils/bytes/BUILD.bazel b/src/tint/utils/bytes/BUILD.bazel
index 2bfa708..3b0bb76 100644
--- a/src/tint/utils/bytes/BUILD.bazel
+++ b/src/tint/utils/bytes/BUILD.bazel
@@ -41,12 +41,15 @@
   srcs = [
     "bytes.cc",
     "reader.cc",
+    "writer.cc",
   ],
   hdrs = [
+    "buffer_writer.h",
     "decoder.h",
     "endianness.h",
     "reader.h",
     "swap.h",
+    "writer.h",
   ],
   deps = [
     "//src/tint/utils/containers",
@@ -68,6 +71,7 @@
   name = "test",
   alwayslink = True,
   srcs = [
+    "buffer_writer_test.cc",
     "decoder_test.cc",
     "reader_test.cc",
     "swap_test.cc",
diff --git a/src/tint/utils/bytes/BUILD.cmake b/src/tint/utils/bytes/BUILD.cmake
index a3997fd..6d919d3 100644
--- a/src/tint/utils/bytes/BUILD.cmake
+++ b/src/tint/utils/bytes/BUILD.cmake
@@ -39,12 +39,15 @@
 # Kind:      lib
 ################################################################################
 tint_add_target(tint_utils_bytes lib
+  utils/bytes/buffer_writer.h
   utils/bytes/bytes.cc
   utils/bytes/decoder.h
   utils/bytes/endianness.h
   utils/bytes/reader.cc
   utils/bytes/reader.h
   utils/bytes/swap.h
+  utils/bytes/writer.cc
+  utils/bytes/writer.h
 )
 
 tint_target_add_dependencies(tint_utils_bytes lib
@@ -66,6 +69,7 @@
 # Kind:      test
 ################################################################################
 tint_add_target(tint_utils_bytes_test test
+  utils/bytes/buffer_writer_test.cc
   utils/bytes/decoder_test.cc
   utils/bytes/reader_test.cc
   utils/bytes/swap_test.cc
diff --git a/src/tint/utils/bytes/BUILD.gn b/src/tint/utils/bytes/BUILD.gn
index c10512f..d3babe2 100644
--- a/src/tint/utils/bytes/BUILD.gn
+++ b/src/tint/utils/bytes/BUILD.gn
@@ -44,12 +44,15 @@
 
 libtint_source_set("bytes") {
   sources = [
+    "buffer_writer.h",
     "bytes.cc",
     "decoder.h",
     "endianness.h",
     "reader.cc",
     "reader.h",
     "swap.h",
+    "writer.cc",
+    "writer.h",
   ]
   deps = [
     "${tint_src_dir}/utils/containers",
@@ -68,6 +71,7 @@
 if (tint_build_unittests) {
   tint_unittests_source_set("unittests") {
     sources = [
+      "buffer_writer_test.cc",
       "decoder_test.cc",
       "reader_test.cc",
       "swap_test.cc",
diff --git a/src/tint/utils/bytes/buffer_writer.h b/src/tint/utils/bytes/buffer_writer.h
new file mode 100644
index 0000000..8ba37dc
--- /dev/null
+++ b/src/tint/utils/bytes/buffer_writer.h
@@ -0,0 +1,68 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_UTILS_BYTES_BUFFER_WRITER_H_
+#define SRC_TINT_UTILS_BYTES_BUFFER_WRITER_H_
+
+#include <stdint.h>
+
+#include "src/tint/utils/bytes/writer.h"
+
+namespace tint::bytes {
+
+/// BufferWriter is an implementation of the Writer interface backed by a buffer.
+template <size_t N>
+class BufferWriter final : public Writer {
+  public:
+    /// @copydoc Writer::Write
+    Result<SuccessType> Write(const std::byte* in, size_t count) override {
+        size_t at = buffer.Length();
+        buffer.Resize(at + count);
+        memcpy(&buffer[at], in, count);
+        return Success;
+    }
+
+    /// @returns the buffer content as a string view
+    std::string_view BufferString() const {
+        if (buffer.IsEmpty()) {
+            return "";
+        }
+        auto* data = reinterpret_cast<const char*>(&buffer[0]);
+        static_assert(sizeof(std::byte) == sizeof(char), "length needs calculation");
+        return std::string_view(data, buffer.Length());
+    }
+
+    /// The buffer holding the written data
+    Vector<std::byte, N> buffer;
+};
+
+/// Deduction guide for BufferWriter
+BufferWriter() -> BufferWriter<32>;
+
+}  // namespace tint::bytes
+
+#endif  // SRC_TINT_UTILS_BYTES_BUFFER_WRITER_H_
diff --git a/src/tint/utils/bytes/buffer_writer_test.cc b/src/tint/utils/bytes/buffer_writer_test.cc
new file mode 100644
index 0000000..7862e28
--- /dev/null
+++ b/src/tint/utils/bytes/buffer_writer_test.cc
@@ -0,0 +1,66 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/utils/bytes/buffer_writer.h"
+
+#include "gmock/gmock.h"
+#include "src/tint/utils/containers/transform.h"
+
+namespace tint::bytes {
+namespace {
+
+template <typename T, typename U, size_t N>
+Vector<T, N> Cast(const Vector<U, N>& in) {
+    return Transform(in, [](auto el) { return static_cast<T>(el); });
+}
+
+TEST(BufferWriterTest, IntegerBigEndian) {
+    BufferWriter<16> writer;
+    EXPECT_TRUE(writer.Int(0x10203040u, Endianness::kBig));
+    EXPECT_THAT(Cast<int>(writer.buffer), testing::ElementsAre(0x10, 0x20, 0x30, 0x40));
+}
+
+TEST(BufferWriterTest, IntegerLittleEndian) {
+    BufferWriter<16> writer;
+    EXPECT_TRUE(writer.Int(0x10203040u, Endianness::kLittle));
+    EXPECT_THAT(Cast<int>(writer.buffer), testing::ElementsAre(0x40, 0x30, 0x20, 0x10));
+}
+
+TEST(BufferWriterTest, Float) {
+    BufferWriter<16> writer;
+    EXPECT_TRUE(writer.Float<float>(8.5f));
+    EXPECT_THAT(Cast<int>(writer.buffer), testing::ElementsAre(0x00, 0x00, 0x08, 0x41));
+}
+
+TEST(BufferWriterTest, Bool) {
+    BufferWriter<16> writer;
+    EXPECT_TRUE(writer.Bool(true));
+    EXPECT_THAT(Cast<int>(writer.buffer), testing::ElementsAre(0x01));
+}
+
+}  // namespace
+}  // namespace tint::bytes
diff --git a/src/tint/utils/bytes/decoder.h b/src/tint/utils/bytes/decoder.h
index 4496ad9..b107497 100644
--- a/src/tint/utils/bytes/decoder.h
+++ b/src/tint/utils/bytes/decoder.h
@@ -34,6 +34,7 @@
 #include <utility>
 
 #include "src/tint/utils/bytes/reader.h"
+#include "src/tint/utils/reflection/reflection.h"
 
 namespace tint::bytes {
 
diff --git a/src/tint/utils/bytes/reader.cc b/src/tint/utils/bytes/reader.cc
index 42e0176..9c28d1d 100644
--- a/src/tint/utils/bytes/reader.cc
+++ b/src/tint/utils/bytes/reader.cc
@@ -30,6 +30,15 @@
 namespace tint::bytes {
 
 Reader::~Reader() = default;
+
 BufferReader::~BufferReader() = default;
 
+size_t BufferReader::Read(std::byte* out, size_t count) {
+    size_t n = std::min(count, bytes_remaining_);
+    memcpy(out, data_, n);
+    data_ += n;
+    bytes_remaining_ -= n;
+    return n;
+}
+
 }  // namespace tint::bytes
diff --git a/src/tint/utils/bytes/reader.h b/src/tint/utils/bytes/reader.h
index 9e58c15..59e1864 100644
--- a/src/tint/utils/bytes/reader.h
+++ b/src/tint/utils/bytes/reader.h
@@ -35,7 +35,6 @@
 #include "src/tint/utils/bytes/endianness.h"
 #include "src/tint/utils/bytes/swap.h"
 #include "src/tint/utils/containers/slice.h"
-#include "src/tint/utils/reflection/reflection.h"
 #include "src/tint/utils/result/result.h"
 
 namespace tint::bytes {
@@ -43,6 +42,9 @@
 /// A binary stream reader interface
 class Reader {
   public:
+    /// Destructor
+    virtual ~Reader();
+
     /// Read reads bytes from the stream, blocking until there are @p count bytes available, or the
     /// end of the stream has been reached.
     /// @param out a pointer to the byte buffer that will be filled with the read data. Must be at
@@ -52,9 +54,6 @@
     /// then the end of the stream has been reached.
     virtual size_t Read(std::byte* out, size_t count) = 0;
 
-    // Destructor
-    virtual ~Reader();
-
     /// Reads an integer from the stream, performing byte swapping if the stream's endianness
     /// differs from the native endianness.
     /// If there are too few bytes remaining in the stream, then a failure is returned.
@@ -126,6 +125,12 @@
     }
 
     /// Constructor
+    /// @param string the string to read from
+    explicit BufferReader(std::string_view string)
+        : data_(reinterpret_cast<const std::byte*>(string.data())),
+          bytes_remaining_(string.length()) {}
+
+    /// Constructor
     /// @param slice the byte slice to read from
     explicit BufferReader(Slice<const std::byte> slice)
         : data_(slice.data), bytes_remaining_(slice.len) {
@@ -133,13 +138,7 @@
     }
 
     /// @copydoc Reader::Read
-    size_t Read(std::byte* out, size_t count) override {
-        size_t n = std::min(count, bytes_remaining_);
-        memcpy(out, data_, n);
-        data_ += n;
-        bytes_remaining_ -= n;
-        return n;
-    }
+    size_t Read(std::byte* out, size_t count) override;
 
   private:
     /// The data to read from
diff --git a/src/tint/utils/bytes/writer.cc b/src/tint/utils/bytes/writer.cc
new file mode 100644
index 0000000..005c5fc
--- /dev/null
+++ b/src/tint/utils/bytes/writer.cc
@@ -0,0 +1,34 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/utils/bytes/writer.h"
+
+namespace tint::bytes {
+
+Writer::~Writer() = default;
+
+}
diff --git a/src/tint/utils/bytes/writer.h b/src/tint/utils/bytes/writer.h
new file mode 100644
index 0000000..3f9ce97
--- /dev/null
+++ b/src/tint/utils/bytes/writer.h
@@ -0,0 +1,96 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_UTILS_BYTES_WRITER_H_
+#define SRC_TINT_UTILS_BYTES_WRITER_H_
+
+#include <algorithm>
+#include <cstdint>
+#include <string>
+
+#include "src/tint/utils/bytes/endianness.h"
+#include "src/tint/utils/bytes/swap.h"
+#include "src/tint/utils/containers/slice.h"
+#include "src/tint/utils/result/result.h"
+
+namespace tint::bytes {
+
+/// A binary stream writer interface
+class Writer {
+  public:
+    /// Destructor
+    virtual ~Writer();
+
+    /// Write writes bytes to the stream, blocking until the write has finished.
+    /// @param in the byte data to write to the stream
+    /// @param count the number of bytes to write. Must be greater than 0
+    /// @returns the result of the write
+    virtual Result<SuccessType> Write(const std::byte* in, size_t count) = 0;
+
+    /// Writes an integer to the stream, performing byte swapping if the stream's endianness
+    /// differs from the native endianness.
+    /// @param value the integer value to write
+    /// @param endianness the endianness of the integer in the stream
+    /// @returns the result of the write
+    template <typename T>
+    Result<SuccessType> Int(T value, Endianness endianness = Endianness::kLittle) {
+        static_assert(std::is_integral_v<T>);
+        if (NativeEndianness() != endianness) {
+            value = Swap(value);
+        }
+        return Write(reinterpret_cast<const std::byte*>(&value), sizeof(T));
+    }
+
+    /// Writes a float to the stream.
+    /// @param value the float value to write
+    /// @returns the result of the write
+    template <typename T>
+    Result<SuccessType> Float(T value) {
+        static_assert(std::is_floating_point_v<T>);
+        return Write(reinterpret_cast<const std::byte*>(&value), sizeof(T));
+    }
+
+    /// Writes a boolean to the stream
+    /// @param value the boolean value to write
+    /// @returns the result of the write
+    Result<SuccessType> Bool(bool value) {
+        auto b = value ? std::byte{1} : std::byte{0};
+        return Write(&b, 1);
+    }
+
+    /// Writes a string of @p len bytes to the stream.
+    /// @param value the string to write
+    /// @returns the result of the write
+    Result<SuccessType> String(std::string_view value) {
+        static_assert(sizeof(std::byte) == sizeof(char), "length needs calculation");
+        return Write(reinterpret_cast<const std::byte*>(value.data()), value.length());
+    }
+};
+
+}  // namespace tint::bytes
+
+#endif  // SRC_TINT_UTILS_BYTES_WRITER_H_
diff --git a/src/tint/utils/macros/compiler.h b/src/tint/utils/macros/compiler.h
index 623e4c4..dd56cde 100644
--- a/src/tint/utils/macros/compiler.h
+++ b/src/tint/utils/macros/compiler.h
@@ -99,8 +99,8 @@
     _Pragma("clang diagnostic ignored \"-Wextra-semi-stmt\"")
 #define TINT_DISABLE_WARNING_ZERO_AS_NULLPTR \
     _Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
-#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE                                   \
-    _Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"")                  \
+#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE                  \
+    _Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"") \
         _Pragma("clang diagnostic ignored \"-Winconsistent-missing-destructor-override\"")
 
 // clang-format off
diff --git a/src/tint/utils/traits/traits.h b/src/tint/utils/traits/traits.h
index b28cbf1..669a254 100644
--- a/src/tint/utils/traits/traits.h
+++ b/src/tint/utils/traits/traits.h
@@ -190,11 +190,12 @@
 template <typename T>
 using PtrElTy = Decay<std::remove_pointer_t<Decay<T>>>;
 
-/// Evaluates to true if `T` decayed is a `std::string`, `std::string_view` or `const char*`
+/// Evaluates to true if `T` decayed is a `std::string`, `std::string_view`, `const char*` or
+/// `char*`
 template <typename T>
 static constexpr bool IsStringLike =
     std::is_same_v<Decay<T>, std::string> || std::is_same_v<Decay<T>, std::string_view> ||
-    std::is_same_v<Decay<T>, const char*>;
+    std::is_same_v<Decay<T>, const char*> || std::is_same_v<Decay<T>, char*>;
 
 namespace detail {
 /// Helper for CharArrayToCharPtr