pw_bytes: Add _b suffix for byte literals

This is a frequently requested literal that allows users to easily
create bytes for tests and constants.

Change-Id: I3fa4670f4abea23ffd8eb48fa79ca728ed78284a
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/178134
Commit-Queue: Taylor Cramer <cramertj@google.com>
Reviewed-by: Erik Gilling <konkers@google.com>
diff --git a/pw_bytes/BUILD.bazel b/pw_bytes/BUILD.bazel
index 5725281..9a8ded1 100644
--- a/pw_bytes/BUILD.bazel
+++ b/pw_bytes/BUILD.bazel
@@ -33,6 +33,7 @@
         "public/pw_bytes/byte_builder.h",
         "public/pw_bytes/endian.h",
         "public/pw_bytes/span.h",
+        "public/pw_bytes/suffix.h",
         "public/pw_bytes/units.h",
     ],
     includes = ["public"],
@@ -99,6 +100,14 @@
 )
 
 pw_cc_test(
+    name = "suffix_test",
+    srcs = ["suffix_test.cc"],
+    deps = [
+        ":pw_bytes",
+    ],
+)
+
+pw_cc_test(
     name = "units_test",
     srcs = ["units_test.cc"],
     deps = [
diff --git a/pw_bytes/BUILD.gn b/pw_bytes/BUILD.gn
index 8d6702d..5aba518 100644
--- a/pw_bytes/BUILD.gn
+++ b/pw_bytes/BUILD.gn
@@ -32,6 +32,7 @@
     "public/pw_bytes/byte_builder.h",
     "public/pw_bytes/endian.h",
     "public/pw_bytes/span.h",
+    "public/pw_bytes/suffix.h",
     "public/pw_bytes/units.h",
   ]
   sources = [ "byte_builder.cc" ]
@@ -57,6 +58,7 @@
     ":bit_test",
     ":byte_builder_test",
     ":endian_test",
+    ":suffix_test",
     ":units_test",
   ]
   group_deps = [
@@ -90,6 +92,11 @@
   sources = [ "endian_test.cc" ]
 }
 
+pw_test("suffix_test") {
+  deps = [ ":pw_bytes" ]
+  sources = [ "suffix_test.cc" ]
+}
+
 pw_test("units_test") {
   deps = [ ":pw_bytes" ]
   sources = [ "units_test.cc" ]
diff --git a/pw_bytes/CMakeLists.txt b/pw_bytes/CMakeLists.txt
index c0e0b7b..8abe481 100644
--- a/pw_bytes/CMakeLists.txt
+++ b/pw_bytes/CMakeLists.txt
@@ -21,6 +21,7 @@
     public/pw_bytes/byte_builder.h
     public/pw_bytes/endian.h
     public/pw_bytes/span.h
+    public/pw_bytes/suffix.h
     public/pw_bytes/units.h
   PUBLIC_INCLUDES
     public
@@ -94,6 +95,16 @@
     pw_bytes
 )
 
+pw_add_test(pw_bytes.suffix_test
+  SOURCES
+    suffix_test.cc
+  PRIVATE_DEPS
+    pw_bytes
+  GROUPS
+    modules
+    pw_bytes
+)
+
 pw_add_test(pw_bytes.units_test
   SOURCES
     units_test.cc
diff --git a/pw_bytes/docs.rst b/pw_bytes/docs.rst
index b2eef24..82c870b 100644
--- a/pw_bytes/docs.rst
+++ b/pw_bytes/docs.rst
@@ -58,6 +58,13 @@
 =================
 Functions for converting the endianness of integral values.
 
+pw_bytes/suffix.h
+=================
+This module exports a single ``_b`` literal, making it easier to create
+``std::byte`` values for tests.
+
+.. cpp:function:: constexpr std::byte operator"" _b(unsigned long long value)
+
 pw_bytes/units.h
 ================
 Constants, functions and user-defined literals for specifying a number of bytes
diff --git a/pw_bytes/public/pw_bytes/suffix.h b/pw_bytes/public/pw_bytes/suffix.h
new file mode 100644
index 0000000..38c6d10
--- /dev/null
+++ b/pw_bytes/public/pw_bytes/suffix.h
@@ -0,0 +1,33 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include <cstddef>
+
+namespace pw {
+
+/// Returns a ``std::byte`` when used as a ``_b`` suffix.
+///
+/// This is useful for writing byte literals, particularly in tests.
+/// To use, add ``using ::pw::operator""_b;`` and then use like ``5_b``
+/// in order to create a ``std::byte`` with the contents ``5``.
+///
+/// This should not be used in header files, as it requires a ``using``
+/// declaration that will be publicly exported at whatever level it is
+/// used.
+constexpr std::byte operator"" _b(unsigned long long value) {
+  return std::byte(value);
+}
+
+}  // namespace pw
diff --git a/pw_bytes/suffix_test.cc b/pw_bytes/suffix_test.cc
new file mode 100644
index 0000000..5825c03
--- /dev/null
+++ b/pw_bytes/suffix_test.cc
@@ -0,0 +1,28 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "pw_bytes/suffix.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::pw::operator""_b;
+
+TEST(Suffix, ReturnsByte) {
+  std::byte x = 5_b;
+  EXPECT_EQ(x, std::byte(5));
+}
+
+}  // namespace