[tint][utils] Add byte reader utility
Change-Id: I0c6e1f14212071984147ab50edc26095431e16d9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162201
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/cmd/test/BUILD.bazel b/src/tint/cmd/test/BUILD.bazel
index c883c12..6c3f01e 100644
--- a/src/tint/cmd/test/BUILD.bazel
+++ b/src/tint/cmd/test/BUILD.bazel
@@ -60,6 +60,7 @@
"//src/tint/lang/wgsl/writer/ir_to_program:test",
"//src/tint/lang/wgsl/writer/raise:test",
"//src/tint/lang/wgsl:test",
+ "//src/tint/utils/bytes:test",
"//src/tint/utils/cli:test",
"//src/tint/utils/command:test",
"//src/tint/utils/containers:test",
diff --git a/src/tint/cmd/test/BUILD.cmake b/src/tint/cmd/test/BUILD.cmake
index f994d98..8dac742 100644
--- a/src/tint/cmd/test/BUILD.cmake
+++ b/src/tint/cmd/test/BUILD.cmake
@@ -61,6 +61,7 @@
tint_lang_wgsl_writer_ir_to_program_test
tint_lang_wgsl_writer_raise_test
tint_lang_wgsl_test
+ tint_utils_bytes_test
tint_utils_cli_test
tint_utils_command_test
tint_utils_containers_test
diff --git a/src/tint/cmd/test/BUILD.gn b/src/tint/cmd/test/BUILD.gn
index 774b68a..9a45716 100644
--- a/src/tint/cmd/test/BUILD.gn
+++ b/src/tint/cmd/test/BUILD.gn
@@ -66,6 +66,7 @@
"${tint_src_dir}/lang/wgsl/sem:unittests",
"${tint_src_dir}/lang/wgsl/writer/ir_to_program:unittests",
"${tint_src_dir}/lang/wgsl/writer/raise:unittests",
+ "${tint_src_dir}/utils/bytes:unittests",
"${tint_src_dir}/utils/cli:unittests",
"${tint_src_dir}/utils/command:unittests",
"${tint_src_dir}/utils/containers:unittests",
diff --git a/src/tint/utils/BUILD.cmake b/src/tint/utils/BUILD.cmake
index 659c2a2..badeb73 100644
--- a/src/tint/utils/BUILD.cmake
+++ b/src/tint/utils/BUILD.cmake
@@ -34,6 +34,7 @@
# Do not modify this file directly
################################################################################
+include(utils/bytes/BUILD.cmake)
include(utils/cli/BUILD.cmake)
include(utils/command/BUILD.cmake)
include(utils/containers/BUILD.cmake)
diff --git a/src/tint/utils/bytes/BUILD.bazel b/src/tint/utils/bytes/BUILD.bazel
new file mode 100644
index 0000000..5fcc9cf
--- /dev/null
+++ b/src/tint/utils/bytes/BUILD.bazel
@@ -0,0 +1,84 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+# tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+cc_library(
+ name = "bytes",
+ srcs = [
+ "bytes.cc",
+ ],
+ hdrs = [
+ "endianness.h",
+ "reader.h",
+ "swap.h",
+ ],
+ deps = [
+ "//src/tint/utils/containers",
+ "//src/tint/utils/ice",
+ "//src/tint/utils/macros",
+ "//src/tint/utils/math",
+ "//src/tint/utils/memory",
+ "//src/tint/utils/reflection",
+ "//src/tint/utils/rtti",
+ "//src/tint/utils/traits",
+ ],
+ copts = COPTS,
+ visibility = ["//visibility:public"],
+)
+cc_library(
+ name = "test",
+ alwayslink = True,
+ srcs = [
+ "reader_test.cc",
+ "swap_test.cc",
+ ],
+ deps = [
+ "//src/tint/utils/bytes",
+ "//src/tint/utils/containers",
+ "//src/tint/utils/ice",
+ "//src/tint/utils/macros",
+ "//src/tint/utils/math",
+ "//src/tint/utils/memory",
+ "//src/tint/utils/reflection",
+ "//src/tint/utils/rtti",
+ "//src/tint/utils/traits",
+ "@gtest",
+ ],
+ copts = COPTS,
+ visibility = ["//visibility:public"],
+)
+
diff --git a/src/tint/utils/bytes/BUILD.cmake b/src/tint/utils/bytes/BUILD.cmake
new file mode 100644
index 0000000..9322ea7
--- /dev/null
+++ b/src/tint/utils/bytes/BUILD.cmake
@@ -0,0 +1,82 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+# tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+################################################################################
+# Target: tint_utils_bytes
+# Kind: lib
+################################################################################
+tint_add_target(tint_utils_bytes lib
+ utils/bytes/bytes.cc
+ utils/bytes/endianness.h
+ utils/bytes/reader.h
+ utils/bytes/swap.h
+)
+
+tint_target_add_dependencies(tint_utils_bytes lib
+ tint_utils_containers
+ tint_utils_ice
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_reflection
+ tint_utils_rtti
+ tint_utils_traits
+)
+
+################################################################################
+# Target: tint_utils_bytes_test
+# Kind: test
+################################################################################
+tint_add_target(tint_utils_bytes_test test
+ utils/bytes/reader_test.cc
+ utils/bytes/swap_test.cc
+)
+
+tint_target_add_dependencies(tint_utils_bytes_test test
+ tint_utils_bytes
+ tint_utils_containers
+ tint_utils_ice
+ tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_reflection
+ tint_utils_rtti
+ tint_utils_traits
+)
+
+tint_target_add_external_dependencies(tint_utils_bytes_test test
+ "gtest"
+)
diff --git a/src/tint/utils/bytes/BUILD.gn b/src/tint/utils/bytes/BUILD.gn
new file mode 100644
index 0000000..c6fb515
--- /dev/null
+++ b/src/tint/utils/bytes/BUILD.gn
@@ -0,0 +1,82 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+# tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+# Do not modify this file directly
+################################################################################
+
+import("../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+
+if (tint_build_unittests || tint_build_benchmarks) {
+ import("//testing/test.gni")
+}
+
+libtint_source_set("bytes") {
+ sources = [
+ "bytes.cc",
+ "endianness.h",
+ "reader.h",
+ "swap.h",
+ ]
+ deps = [
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/traits",
+ ]
+}
+if (tint_build_unittests) {
+ tint_unittests_source_set("unittests") {
+ sources = [
+ "reader_test.cc",
+ "swap_test.cc",
+ ]
+ deps = [
+ "${tint_src_dir}:gmock_and_gtest",
+ "${tint_src_dir}/utils/bytes",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/ice",
+ "${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/reflection",
+ "${tint_src_dir}/utils/rtti",
+ "${tint_src_dir}/utils/traits",
+ ]
+ }
+}
diff --git a/src/tint/utils/bytes/bytes.cc b/src/tint/utils/bytes/bytes.cc
new file mode 100644
index 0000000..392f0ea
--- /dev/null
+++ b/src/tint/utils/bytes/bytes.cc
@@ -0,0 +1,33 @@
+// Copyright 2023 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.
+
+#if defined(__clang__)
+#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
+#endif
+
+// A placeholder symbol used to emit a symbol for this lib target.
+int tint_utils_bytes_symbol = 1;
diff --git a/src/tint/utils/bytes/endianness.h b/src/tint/utils/bytes/endianness.h
new file mode 100644
index 0000000..81db319
--- /dev/null
+++ b/src/tint/utils/bytes/endianness.h
@@ -0,0 +1,47 @@
+// Copyright 2023 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_ENDIANNESS_H_
+#define SRC_TINT_UTILS_BYTES_ENDIANNESS_H_
+
+#include <cstdint>
+#include <cstring>
+
+namespace tint::bytes {
+
+enum class Endianness : uint8_t { kBig, kLittle };
+
+inline Endianness NativeEndianness() {
+ uint8_t u8[4];
+ uint32_t u32 = 0x01020304;
+ memcpy(u8, &u32, 4);
+ return u8[0] == 1 ? Endianness::kBig : Endianness::kLittle;
+}
+
+} // namespace tint::bytes
+
+#endif // SRC_TINT_UTILS_BYTES_ENDIANNESS_H_
diff --git a/src/tint/utils/bytes/reader.h b/src/tint/utils/bytes/reader.h
new file mode 100644
index 0000000..38bbf4e
--- /dev/null
+++ b/src/tint/utils/bytes/reader.h
@@ -0,0 +1,140 @@
+// Copyright 2023 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_READER_H_
+#define SRC_TINT_UTILS_BYTES_READER_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/reflection/reflection.h"
+
+namespace tint::bytes {
+
+/// A binary stream reader.
+struct Reader {
+ /// @returns true if there are no more bytes remaining
+ bool IsEOF() const { return offset >= bytes.len; }
+
+ /// @returns the number of bytes remaining in the stream
+ size_t BytesRemaining() const { return IsEOF() ? 0 : bytes.len - offset; }
+
+ /// 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
+ /// the missing data will be substituted with zeros.
+ /// @return the deserialized integer
+ template <typename T>
+ T Int() {
+ static_assert(std::is_integral_v<T>);
+ T out = 0;
+ if (!IsEOF()) {
+ size_t n = std::min(sizeof(T), BytesRemaining());
+ memcpy(&out, &bytes[offset], n);
+ offset += n;
+ if (NativeEndianness() != endianness) {
+ out = Swap(out);
+ }
+ }
+ return out;
+ }
+
+ /// Reads a float from the stream. If there are too few bytes remaining in the stream, then
+ /// the missing data will be substituted with zeros.
+ /// @return the deserialized floating point number
+ template <typename T>
+ T Float() {
+ static_assert(std::is_floating_point_v<T>);
+ T out = 0;
+ if (!IsEOF()) {
+ size_t n = std::min(sizeof(T), BytesRemaining());
+ memcpy(&out, &bytes[offset], n);
+ offset += n;
+ }
+ return out;
+ }
+
+ /// Reads a boolean from the stream
+ /// @returns true if the next byte is non-zero
+ bool Bool() {
+ if (IsEOF()) {
+ return false;
+ }
+ return bytes[offset++] != std::byte{0};
+ }
+
+ /// Reads a string of @p len bytes from the stream. If there are too few bytes remaining in the
+ /// stream, then the returned string will be truncated.
+ /// @param len the length of the returned string in bytes
+ /// @return the deserialized string
+ std::string String(size_t len) {
+ if (IsEOF()) {
+ return "";
+ }
+ size_t n = std::min(len, BytesRemaining());
+ std::string out(reinterpret_cast<const char*>(&bytes[offset]), n);
+ offset += n;
+ return out;
+ }
+
+ /// The data to read from
+ Slice<const std::byte> bytes;
+
+ /// The current byte offset
+ size_t offset = 0;
+
+ /// The endianness of integers serialized in the stream
+ Endianness endianness = Endianness::kLittle;
+};
+
+/// Reads the templated type from the reader and assigns it to @p out
+/// @note This function does not
+template <typename T>
+Reader& operator>>(Reader& reader, T& out) {
+ constexpr bool is_numeric = std::is_integral_v<T> || std::is_floating_point_v<T>;
+ static_assert(is_numeric);
+
+ if constexpr (std::is_integral_v<T>) {
+ out = reader.Int<T>();
+ return reader;
+ }
+
+ if constexpr (std::is_floating_point_v<T>) {
+ out = reader.Float<T>();
+ return reader;
+ }
+
+ // Unreachable
+ return reader;
+}
+
+} // namespace tint::bytes
+
+#endif // SRC_TINT_UTILS_BYTES_READER_H_
diff --git a/src/tint/utils/bytes/reader_test.cc b/src/tint/utils/bytes/reader_test.cc
new file mode 100644
index 0000000..e8af39d
--- /dev/null
+++ b/src/tint/utils/bytes/reader_test.cc
@@ -0,0 +1,107 @@
+// Copyright 2023 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/reader.h"
+
+#include "gtest/gtest.h"
+
+namespace tint::bytes {
+namespace {
+
+template <typename... ARGS>
+auto Data(ARGS&&... args) {
+ return std::array{std::byte{static_cast<uint8_t>(args)}...};
+}
+
+TEST(BytesReaderTest, IntegerBigEndian) {
+ auto data = Data(0x10, 0x20, 0x30, 0x40);
+ auto u32 = Reader{Slice{data}, 0, Endianness::kBig}.Int<uint32_t>();
+ EXPECT_EQ(u32, 0x10203040u);
+ auto i32 = Reader{Slice{data}, 0, Endianness::kBig}.Int<int32_t>();
+ EXPECT_EQ(i32, 0x10203040);
+}
+
+TEST(BytesReaderTest, IntegerBigEndian_Offset) {
+ auto data = Data(0x10, 0x20, 0x30, 0x40, 0x50, 0x60);
+ auto u32 = Reader{Slice{data}, 2, Endianness::kBig}.Int<uint32_t>();
+ EXPECT_EQ(u32, 0x30405060u);
+ auto i32 = Reader{Slice{data}, 2, Endianness::kBig}.Int<int32_t>();
+ EXPECT_EQ(i32, 0x30405060);
+}
+
+TEST(BytesReaderTest, IntegerBigEndian_Clipped) {
+ auto data = Data(0x10, 0x20, 0x30, 0x40);
+ auto u32 = Reader{Slice{data}, 2, Endianness::kBig}.Int<uint32_t>();
+ EXPECT_EQ(u32, 0x30400000u);
+ auto i32 = Reader{Slice{data}, 2, Endianness::kBig}.Int<int32_t>();
+ EXPECT_EQ(i32, 0x30400000);
+}
+
+TEST(BytesReaderTest, IntegerLittleEndian) {
+ auto data = Data(0x10, 0x20, 0x30, 0x40);
+ auto u32 = Reader{Slice{data}, 0, Endianness::kLittle}.Int<uint32_t>();
+ EXPECT_EQ(u32, 0x40302010u);
+ auto i32 = Reader{Slice{data}, 0, Endianness::kLittle}.Int<int32_t>();
+ EXPECT_EQ(i32, 0x40302010);
+}
+
+TEST(BytesReaderTest, IntegerLittleEndian_Offset) {
+ auto data = Data(0x10, 0x20, 0x30, 0x40, 0x50, 0x60);
+ auto u32 = Reader{Slice{data}, 2, Endianness::kLittle}.Int<uint32_t>();
+ EXPECT_EQ(u32, 0x60504030u);
+ auto i32 = Reader{Slice{data}, 2, Endianness::kLittle}.Int<int32_t>();
+ EXPECT_EQ(i32, 0x60504030);
+}
+
+TEST(BytesReaderTest, IntegerLittleEndian_Clipped) {
+ auto data = Data(0x10, 0x20, 0x30, 0x40);
+ auto u32 = Reader{Slice{data}, 2, Endianness::kLittle}.Int<uint32_t>();
+ EXPECT_EQ(u32, 0x00004030u);
+ auto i32 = Reader{Slice{data}, 2, Endianness::kLittle}.Int<int32_t>();
+ EXPECT_EQ(i32, 0x00004030);
+}
+
+TEST(BytesReaderTest, Float) {
+ auto data = Data(0x00, 0x00, 0x08, 0x41);
+ float f32 = Reader{Slice{data}}.Float<float>();
+ EXPECT_EQ(f32, 8.5f);
+}
+
+TEST(BytesReaderTest, Float_Offset) {
+ auto data = Data(0x00, 0x00, 0x08, 0x41, 0x80, 0x3e);
+ float f32 = Reader{Slice{data}, 2}.Float<float>();
+ EXPECT_EQ(f32, 0.25049614f);
+}
+
+TEST(BytesReaderTest, Float_Clipped) {
+ auto data = Data(0x00, 0x00, 0x08, 0x41);
+ float f32 = Reader{Slice{data}, 2}.Float<float>();
+ EXPECT_EQ(f32, 2.3329e-41f);
+}
+
+} // namespace
+} // namespace tint::bytes
diff --git a/src/tint/utils/bytes/swap.h b/src/tint/utils/bytes/swap.h
new file mode 100644
index 0000000..da4c6e6
--- /dev/null
+++ b/src/tint/utils/bytes/swap.h
@@ -0,0 +1,55 @@
+// Copyright 2023 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_SWAP_H_
+#define SRC_TINT_UTILS_BYTES_SWAP_H_
+
+#include <cstdint>
+#include <cstring>
+#include <type_traits>
+#include <utility>
+
+namespace tint::bytes {
+
+/// @return the input integer value with all bytes reversed
+/// @param value the input value
+template <typename T>
+[[nodiscard]] inline T Swap(T value) {
+ static_assert(std::is_integral_v<T>);
+ uint8_t bytes[sizeof(T)];
+ memcpy(bytes, &value, sizeof(T));
+ for (size_t i = 0; i < sizeof(T) / 2; i++) {
+ std::swap(bytes[i], bytes[sizeof(T) - i - 1]);
+ }
+ T out;
+ memcpy(&out, bytes, sizeof(T));
+ return out;
+}
+
+} // namespace tint::bytes
+
+#endif // SRC_TINT_UTILS_BYTES_SWAP_H_
diff --git a/src/tint/utils/bytes/swap_test.cc b/src/tint/utils/bytes/swap_test.cc
new file mode 100644
index 0000000..5d950c0
--- /dev/null
+++ b/src/tint/utils/bytes/swap_test.cc
@@ -0,0 +1,54 @@
+// Copyright 2023 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/swap.h"
+
+#include "gtest/gtest.h"
+
+namespace tint::bytes {
+namespace {
+
+TEST(BytesSwapTest, Uint) {
+ EXPECT_EQ(Swap<uint8_t>(0x41), static_cast<uint8_t>(0x41));
+ EXPECT_EQ(Swap<uint16_t>(0x4152), static_cast<uint16_t>(0x5241));
+ EXPECT_EQ(Swap<uint32_t>(0x41526374), static_cast<uint32_t>(0x74635241));
+ EXPECT_EQ(Swap<uint64_t>(0x415263748596A7B8), static_cast<uint64_t>(0xB8A7968574635241));
+}
+
+TEST(BytesSwapTest, Sint) {
+ EXPECT_EQ(Swap<int8_t>(0x41), static_cast<int8_t>(0x41));
+ EXPECT_EQ(Swap<int8_t>(-0x41), static_cast<int8_t>(-0x41));
+ EXPECT_EQ(Swap<int16_t>(0x4152), static_cast<int16_t>(0x5241));
+ EXPECT_EQ(Swap<int16_t>(-0x4152), static_cast<int16_t>(0xAEBE));
+ EXPECT_EQ(Swap<int32_t>(0x41526374), static_cast<int32_t>(0x74635241));
+ EXPECT_EQ(Swap<int32_t>(-0x41526374), static_cast<int32_t>(0x8C9CADBE));
+ EXPECT_EQ(Swap<int64_t>(0x415263748596A7B8), static_cast<int64_t>(0xB8A7968574635241));
+ EXPECT_EQ(Swap<int64_t>(-0x415263748596A7B8), static_cast<int64_t>(0x4858697A8B9CADBE));
+}
+
+} // namespace
+} // namespace tint::bytes
diff --git a/src/tint/utils/containers/slice.h b/src/tint/utils/containers/slice.h
index f2cf7c3..3c60913 100644
--- a/src/tint/utils/containers/slice.h
+++ b/src/tint/utils/containers/slice.h
@@ -28,6 +28,7 @@
#ifndef SRC_TINT_UTILS_CONTAINERS_SLICE_H_
#define SRC_TINT_UTILS_CONTAINERS_SLICE_H_
+#include <array>
#include <cstdint>
#include <iterator>
@@ -158,6 +159,12 @@
constexpr Slice(T (&elements)[N]) // NOLINT
: data(elements), len(N), cap(N) {}
+ /// Constructor
+ /// @param array std::array of elements
+ template <size_t N>
+ constexpr Slice(std::array<T, N>& array) // NOLINT
+ : data(array.data()), len(N), cap(N) {}
+
/// Reinterprets this slice as `const Slice<TO>&`
/// @returns the reinterpreted slice
/// @see CanReinterpretSlice
diff --git a/src/tint/utils/containers/slice_test.cc b/src/tint/utils/containers/slice_test.cc
index 2432aeb..01932fd 100644
--- a/src/tint/utils/containers/slice_test.cc
+++ b/src/tint/utils/containers/slice_test.cc
@@ -118,6 +118,16 @@
EXPECT_FALSE(slice.IsEmpty());
}
+TEST(TintSliceTest, CtorStdArray) {
+ std::array elements{1, 2, 3};
+
+ auto slice = Slice{elements};
+ EXPECT_EQ(slice.data, &elements[0]);
+ EXPECT_EQ(slice.len, 3u);
+ EXPECT_EQ(slice.cap, 3u);
+ EXPECT_FALSE(slice.IsEmpty());
+}
+
TEST(TintSliceTest, Index) {
int elements[] = {1, 2, 3};