pw_bytes: Added code for Size Report

Change-Id: I224e96c88288c890686cb91eac354cf30dbcad4f
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/13182
Commit-Queue: Shane Gomindes <shaneajg@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
diff --git a/pw_bytes/BUILD.gn b/pw_bytes/BUILD.gn
index f1d71c2..74c966b 100644
--- a/pw_bytes/BUILD.gn
+++ b/pw_bytes/BUILD.gn
@@ -63,4 +63,17 @@
 
 pw_doc_group("docs") {
   sources = [ "docs.rst" ]
+  report_deps = [ ":byte_builder_size_report" ]
+}
+
+pw_size_report("byte_builder_size_report") {
+  title = "Using pw::ByteBuilder"
+
+  binaries = [
+    {
+      target = "size_report:with_byte_builder"
+      base = "size_report:without_byte_builder"
+      label = "Using ByteBuilder vs not using it"
+    },
+  ]
 }
diff --git a/pw_bytes/docs.rst b/pw_bytes/docs.rst
index d67a8df..d8a26ca 100644
--- a/pw_bytes/docs.rst
+++ b/pw_bytes/docs.rst
@@ -34,6 +34,10 @@
 -``PutInt32``, ``PutUInt32``: Inserts 32-bit integers in little/big endian.
 -``PutInt64``, ``PutInt64``: Inserts 64-bit integers in little/big endian.
 
+Size report: using ByteBuffer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. include:: byte_builder_size_report
+
 Future work
 ^^^^^^^^^^^
 - Utilities for building byte arrays at compile time.
diff --git a/pw_bytes/size_report/BUILD b/pw_bytes/size_report/BUILD
new file mode 100644
index 0000000..d58feea
--- /dev/null
+++ b/pw_bytes/size_report/BUILD
@@ -0,0 +1,31 @@
+# Copyright 2019 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.
+
+load(
+    "//pw_build:pigweed.bzl",
+    "pw_cc_binary",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])  # Apache License 2.0
+
+pw_cc_binary(
+    name = "build_byte_buffer",
+    srcs = ["byte_builder_size_report.cc"],
+    deps = [
+        "//pw_bloat:bloat_this_binary",
+        "//pw_bytes",
+    ],
+)
\ No newline at end of file
diff --git a/pw_bytes/size_report/BUILD.gn b/pw_bytes/size_report/BUILD.gn
new file mode 100644
index 0000000..c70b201
--- /dev/null
+++ b/pw_bytes/size_report/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2019 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.
+
+# gn-format disable
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/target_types.gni")
+pw_executable("with_byte_builder") {
+  sources = [ "byte_builder_size_report.cc" ]
+  deps = [ ".." ]
+  defines = [ "USE_BYTE_BUILDER=1" ]
+}
+
+pw_executable("without_byte_builder") {
+  sources = [ "byte_builder_size_report.cc" ]
+  deps = [ ".." ]
+  defines = [ "USE_BYTE_BUILDER=0" ]
+}
diff --git a/pw_bytes/size_report/byte_builder_size_report.cc b/pw_bytes/size_report/byte_builder_size_report.cc
new file mode 100644
index 0000000..72a440d
--- /dev/null
+++ b/pw_bytes/size_report/byte_builder_size_report.cc
@@ -0,0 +1,103 @@
+// Copyright 2019 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.
+
+// This size report uses either pw::ByteBuilder or manual bytes manipulation
+// depending on whether "USE_BYTE_BUILDER" is set to true/false.
+// Building the file: ninja -C out build_me
+
+#include <array>
+#include <cstdint>
+#include <cstdio>
+
+#include "pw_bytes/byte_builder.h"
+
+#if !defined(USE_BYTE_BUILDER)
+#error "USE_BYTE_BUILDER must be defined"
+#endif  // !defined(USE_BYTE_BUILDER)
+
+#if USE_BYTE_BUILDER
+
+pw::ByteBuffer<8> bb;
+
+void PutBytes() {
+  bb.PutUint32(0x482B3D9E);
+  bb.PutInt32(0x482B3D9E, pw::ByteOrder::kBigEndian);
+}
+
+void ReadBytes() {
+  auto it = bb.begin();
+
+  printf("%lu\n", it.ReadUint32());
+  printf("%ld\n", it.ReadInt32(pw::ByteOrder::kBigEndian));
+}
+
+#else  // !USE_BYTE_BUILDER
+
+std::byte b_array[8];
+
+void PutBytes() {
+  uint32_t kVal1 = 0x482B3D9E;
+  int32_t kVal2 = 0x482B3D9E;
+
+  if (pw::kSystemEndianness == pw::ByteOrder::kLittleEndian) {
+    std::memcpy(b_array, &kVal1, sizeof(kVal1));
+
+    kVal2 = int32_t(((kVal2 & 0x000000FF) << 3 * 8) |  //
+                    ((kVal2 & 0x0000FF00) << 1 * 8) |  //
+                    ((kVal2 & 0x00FF0000) >> 1 * 8) |  //
+                    ((kVal2 & 0xFF000000) >> 3 * 8));
+    std::memcpy(b_array + 4, &kVal2, sizeof(kVal2));
+  } else {
+    kVal1 = uint32_t(((kVal1 & 0x000000FF) << 3 * 8) |  //
+                     ((kVal1 & 0x0000FF00) << 1 * 8) |  //
+                     ((kVal1 & 0x00FF0000) >> 1 * 8) |  //
+                     ((kVal1 & 0xFF000000) >> 3 * 8));
+    std::memcpy(b_array, &kVal1, sizeof(kVal1));
+
+    std::memcpy(b_array + 4, &kVal2, sizeof(kVal2));
+  }
+}
+
+void ReadBytes() {
+  uint32_t kVal1;
+  int32_t kVal2;
+
+  if (pw::kSystemEndianness == pw::ByteOrder::kLittleEndian) {
+    std::memcpy(&kVal1, b_array, sizeof(kVal1));
+    std::memcpy(&kVal2, b_array + 4, sizeof(kVal2));
+    kVal2 = int32_t(((kVal2 & 0x000000FF) << 3 * 8) |  //
+                    ((kVal2 & 0x0000FF00) << 1 * 8) |  //
+                    ((kVal2 & 0x00FF0000) >> 1 * 8) |  //
+                    ((kVal2 & 0xFF000000) >> 3 * 8));
+  } else {
+    std::memcpy(&kVal1, b_array, sizeof(kVal1));
+    std::memcpy(&kVal2, b_array + 4, sizeof(kVal2));
+
+    kVal1 = uint32_t(((kVal1 & 0x000000FF) << 3 * 8) |  //
+                     ((kVal1 & 0x0000FF00) << 1 * 8) |  //
+                     ((kVal1 & 0x00FF0000) >> 1 * 8) |  //
+                     ((kVal1 & 0xFF000000) >> 3 * 8));
+  }
+
+  printf("%lu\n", kVal1);
+  printf("%ld\n", kVal2);
+}
+
+#endif  // USE_BYTE_BUILDER
+
+int main() {
+  PutBytes();
+  ReadBytes();
+  return 0;
+}