create base/ subdir and expand :status build target to :base

upb.h is now just a temporary stub

PiperOrigin-RevId: 488255988
diff --git a/BUILD b/BUILD
index de6165b..2315392 100644
--- a/BUILD
+++ b/BUILD
@@ -121,11 +121,15 @@
         "upb/upb.c",
         "upb/wire/decode.c",
         "upb/wire/encode.c",
+        "upb/wire/swap_internal.h",
     ],
     hdrs = [
         "upb/alloc.h",
         "upb/arena.h",
         "upb/array.h",
+        "upb/base/descriptor_constants.h",
+        "upb/base/status.h",
+        "upb/base/string_view.h",
         "upb/collections/array.h",
         "upb/decode.h",
         "upb/encode.h",
@@ -144,12 +148,12 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":collections_internal",
         ":extension_registry",
         ":fastdecode",
         ":mem",
         ":port",
-        ":status",
         ":table_internal",
         ":unicode_internal",
         ":wire_internal",
@@ -157,12 +161,27 @@
 )
 
 cc_library(
+    name = "base",
+    srcs = [
+        "upb/base/status.c",
+    ],
+    hdrs = [
+        "upb/base/descriptor_constants.h",
+        "upb/base/log2.h",
+        "upb/base/status.h",
+        "upb/base/string_view.h",
+    ],
+    copts = UPB_DEFAULT_COPTS,
+    visibility = ["//:__subpackages__"],
+    deps = [":port"],
+)
+
+cc_library(
     name = "extension_registry",
     srcs = [
         "upb/extension_registry.c",
         "upb/msg.h",
         "upb/msg_internal.h",
-        "upb/string_view.h",
         "upb/upb.h",
     ],
     hdrs = [
@@ -171,6 +190,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":collections_internal",
         ":port",
         ":table_internal",
@@ -190,6 +210,7 @@
     ],
     visibility = ["//:__subpackages__"],
     deps = [
+        ":base",
         ":collections_internal",
         ":extension_registry",
         ":port",
@@ -216,6 +237,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":collections_internal",
         ":extension_registry",
         ":mini_table_internal",
@@ -250,7 +272,6 @@
 cc_test(
     name = "mini_table_encode_test",
     srcs = [
-        "upb/internal/table.h",
         "upb/mini_table/encode_test.cc",
     ],
     deps = [
@@ -258,6 +279,7 @@
         ":mini_table",
         ":mini_table_internal",
         ":port",
+        ":table_internal",
         ":upb",
         "@com_google_absl//absl/container:flat_hash_set",
         "@com_google_googletest//:gtest_main",
@@ -296,6 +318,7 @@
     ],
     copts = UPB_DEFAULT_COPTS,
     deps = [
+        ":base",
         ":collections_internal",
         ":extension_registry",
         ":mem_internal",
@@ -332,6 +355,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":collections_internal",
         ":table_internal",
         ":upb",
@@ -354,6 +378,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":collections_internal",
         ":mini_table",
         ":table_internal",
@@ -386,6 +411,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":descriptor_upb_proto",
         ":reflection_internal",
         ":table_internal",
@@ -413,6 +439,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//visibility:public"],
     deps = [
+        ":base",
         ":collections_internal",
         ":port",
     ],
@@ -427,8 +454,6 @@
         "upb/extension_registry.h",
         "upb/msg.h",
         "upb/msg_internal.h",
-        "upb/status.h",
-        "upb/string_view.h",
     ],
     hdrs = [
         "upb/collections/array.h",
@@ -442,6 +467,7 @@
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//:__subpackages__"],
     deps = [
+        ":base",
         ":mem",
         ":port",
         ":table_internal",
@@ -981,19 +1007,6 @@
 )
 
 cc_library(
-    name = "status",
-    srcs = [
-        "upb/status.c",
-    ],
-    hdrs = [
-        "upb/status.h",
-    ],
-    copts = UPB_DEFAULT_COPTS,
-    visibility = ["//:__subpackages__"],
-    deps = [":port"],
-)
-
-cc_library(
     name = "atoi_internal",
     srcs = ["upb/internal/atoi.c"],
     hdrs = ["upb/internal/atoi.h"],
@@ -1014,10 +1027,12 @@
         "upb/wire/common_internal.h",
         "upb/wire/decode_internal.h",
         "upb/wire/encode_internal.h",
+        "upb/wire/swap_internal.h",
     ],
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//:__subpackages__"],
     deps = [
+        ":base",
         ":collections_internal",
         ":mem_internal",
         ":port",
@@ -1035,13 +1050,14 @@
         "upb/internal/table.h",
         "upb/mem/alloc.h",
         "upb/mem/arena.h",
-        "upb/status.h",
-        "upb/string_view.h",
         "upb/upb.h",
     ],
     copts = UPB_DEFAULT_COPTS,
     visibility = ["//:__subpackages__"],
-    deps = [":port"],
+    deps = [
+        ":base",
+        ":port",
+    ],
 )
 
 cc_library(
@@ -1069,6 +1085,7 @@
     ],
     libs = [
         ":atoi_internal",
+        ":base",
         ":collections_internal",
         ":descriptor_upb_proto",
         ":extension_registry",
@@ -1079,7 +1096,6 @@
         ":port",
         ":reflection",
         ":reflection_internal",
-        ":status",
         ":upb",
         ":wire_internal",
     ],
@@ -1102,6 +1118,7 @@
     ],
     libs = [
         ":atoi_internal",
+        ":base",
         ":collections_internal",
         ":descriptor_upb_proto",
         ":descriptor_upb_proto_reflection",
@@ -1114,7 +1131,6 @@
         ":port",
         ":reflection",
         ":reflection_internal",
-        ":status",
         ":table_internal",
         ":unicode_internal",
         ":upb",
@@ -1141,6 +1157,7 @@
     ],
     libs = [
         ":atoi_internal",
+        ":base",
         ":collections_internal",
         ":descriptor_upb_proto",
         ":extension_registry",
@@ -1152,7 +1169,6 @@
         ":port",
         ":reflection",
         ":reflection_internal",
-        ":status",
         ":table_internal",
         ":unicode_internal",
         ":upb",
diff --git a/upb/base/descriptor_constants.h b/upb/base/descriptor_constants.h
new file mode 100644
index 0000000..93f0ead
--- /dev/null
+++ b/upb/base/descriptor_constants.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google LLC 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 Google LLC 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 UPB_BASE_DESCRIPTOR_CONSTANTS_H_
+#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_
+
+// A list of types as they are encoded on-the-wire.
+// TODO(salo): Move this into upb/wire/
+typedef enum {
+  kUpb_WireType_Varint = 0,
+  kUpb_WireType_64Bit = 1,
+  kUpb_WireType_Delimited = 2,
+  kUpb_WireType_StartGroup = 3,
+  kUpb_WireType_EndGroup = 4,
+  kUpb_WireType_32Bit = 5
+} upb_WireType;
+
+// The types a field can have. Note that this list is not identical to the
+// types defined in descriptor.proto, which gives INT32 and SINT32 separate
+// types (we distinguish the two with the "integer encoding" enum below).
+// This enum is an internal convenience only and has no meaning outside of upb.
+typedef enum {
+  kUpb_CType_Bool = 1,
+  kUpb_CType_Float = 2,
+  kUpb_CType_Int32 = 3,
+  kUpb_CType_UInt32 = 4,
+  kUpb_CType_Enum = 5,  // Enum values are int32.
+  kUpb_CType_Message = 6,
+  kUpb_CType_Double = 7,
+  kUpb_CType_Int64 = 8,
+  kUpb_CType_UInt64 = 9,
+  kUpb_CType_String = 10,
+  kUpb_CType_Bytes = 11
+} upb_CType;
+
+// The repeated-ness of each field; this matches descriptor.proto.
+typedef enum {
+  kUpb_Label_Optional = 1,
+  kUpb_Label_Required = 2,
+  kUpb_Label_Repeated = 3
+} upb_Label;
+
+// Descriptor types, as defined in descriptor.proto.
+typedef enum {
+  kUpb_FieldType_Double = 1,
+  kUpb_FieldType_Float = 2,
+  kUpb_FieldType_Int64 = 3,
+  kUpb_FieldType_UInt64 = 4,
+  kUpb_FieldType_Int32 = 5,
+  kUpb_FieldType_Fixed64 = 6,
+  kUpb_FieldType_Fixed32 = 7,
+  kUpb_FieldType_Bool = 8,
+  kUpb_FieldType_String = 9,
+  kUpb_FieldType_Group = 10,
+  kUpb_FieldType_Message = 11,
+  kUpb_FieldType_Bytes = 12,
+  kUpb_FieldType_UInt32 = 13,
+  kUpb_FieldType_Enum = 14,
+  kUpb_FieldType_SFixed32 = 15,
+  kUpb_FieldType_SFixed64 = 16,
+  kUpb_FieldType_SInt32 = 17,
+  kUpb_FieldType_SInt64 = 18,
+} upb_FieldType;
+
+#define kUpb_FieldType_SizeOf 19
+
+#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */
diff --git a/upb/base/log2.h b/upb/base/log2.h
new file mode 100644
index 0000000..d825e8b
--- /dev/null
+++ b/upb/base/log2.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google LLC 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 Google LLC 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 UPB_BASE_LOG2_H_
+#define UPB_BASE_LOG2_H_
+
+// Must be last.
+#include "upb/port/def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE int upb_Log2Ceiling(int x) {
+  if (x <= 1) return 0;
+#ifdef __GNUC__
+  return 32 - __builtin_clz(x - 1);
+#else
+  int lg2 = 0;
+  while (1 << lg2 < x) lg2++;
+  return lg2;
+#endif
+}
+
+UPB_INLINE int upb_Log2CeilingSize(int x) { return 1 << upb_Log2Ceiling(x); }
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port/undef.inc"
+
+#endif /* UPB_BASE_LOG2_H_ */
diff --git a/upb/status.c b/upb/base/status.c
similarity index 98%
rename from upb/status.c
rename to upb/base/status.c
index 9435355..234754c 100644
--- a/upb/status.c
+++ b/upb/base/status.c
@@ -25,7 +25,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "upb/status.h"
+#include "upb/base/status.h"
 
 #include <errno.h>
 #include <float.h>
diff --git a/upb/status.c b/upb/base/status.h
similarity index 62%
copy from upb/status.c
copy to upb/base/status.h
index 9435355..bdd80bf 100644
--- a/upb/status.c
+++ b/upb/base/status.h
@@ -25,57 +25,42 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "upb/status.h"
+#ifndef UPB_BASE_STATUS_H_
+#define UPB_BASE_STATUS_H_
 
-#include <errno.h>
-#include <float.h>
 #include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
 
 // Must be last.
 #include "upb/port/def.inc"
 
-void upb_Status_Clear(upb_Status* status) {
-  if (!status) return;
-  status->ok = true;
-  status->msg[0] = '\0';
-}
+#define _kUpb_Status_MaxMessage 127
 
-bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
+typedef struct {
+  bool ok;
+  char msg[_kUpb_Status_MaxMessage];  // Error message; NULL-terminated.
+} upb_Status;
 
-const char* upb_Status_ErrorMessage(const upb_Status* status) {
-  return status->msg;
-}
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
-  if (!status) return;
-  status->ok = false;
-  strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
-  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
+const char* upb_Status_ErrorMessage(const upb_Status* status);
+bool upb_Status_IsOk(const upb_Status* status);
 
-void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  upb_Status_VSetErrorFormat(status, fmt, args);
-  va_end(args);
-}
-
+// These are no-op if |status| is NULL.
+void upb_Status_Clear(upb_Status* status);
+void upb_Status_SetErrorMessage(upb_Status* status, const char* msg);
+void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...)
+    UPB_PRINTF(2, 3);
 void upb_Status_VSetErrorFormat(upb_Status* status, const char* fmt,
-                                va_list args) {
-  if (!status) return;
-  status->ok = false;
-  vsnprintf(status->msg, sizeof(status->msg), fmt, args);
-  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
+                                va_list args) UPB_PRINTF(2, 0);
 void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
-                                   va_list args) {
-  size_t len;
-  if (!status) return;
-  status->ok = false;
-  len = strlen(status->msg);
-  vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
-  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
+                                   va_list args) UPB_PRINTF(2, 0);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port/undef.inc"
+
+#endif /* UPB_BASE_STATUS_H_ */
diff --git a/upb/base/string_view.h b/upb/base/string_view.h
new file mode 100644
index 0000000..ddf1004
--- /dev/null
+++ b/upb/base/string_view.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google LLC 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 Google LLC 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 UPB_BASE_STRING_VIEW_H_
+#define UPB_BASE_STRING_VIEW_H_
+
+#include <string.h>
+
+// Must be last.
+#include "upb/port/def.inc"
+
+#define UPB_STRINGVIEW_INIT(ptr, len) \
+  { ptr, len }
+
+#define UPB_STRINGVIEW_FORMAT "%.*s"
+#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data
+
+// LINT.IfChange(struct_definition)
+typedef struct {
+  const char* data;
+  size_t size;
+} upb_StringView;
+// LINT.ThenChange(GoogleInternalName0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data,
+                                                         size_t size) {
+  upb_StringView ret;
+  ret.data = data;
+  ret.size = size;
+  return ret;
+}
+
+UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) {
+  return upb_StringView_FromDataAndSize(data, strlen(data));
+}
+
+UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) {
+  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port/undef.inc"
+
+#endif /* UPB_BASE_STRING_VIEW_H_ */
diff --git a/upb/collections/array.h b/upb/collections/array.h
index d475517..c304ff6 100644
--- a/upb/collections/array.h
+++ b/upb/collections/array.h
@@ -28,6 +28,7 @@
 #ifndef UPB_COLLECTIONS_ARRAY_H_
 #define UPB_COLLECTIONS_ARRAY_H_
 
+#include "upb/base/descriptor_constants.h"
 #include "upb/collections/message_value.h"
 
 // Must be last.
diff --git a/upb/collections/map.h b/upb/collections/map.h
index d1cb79e..d94cbd1 100644
--- a/upb/collections/map.h
+++ b/upb/collections/map.h
@@ -28,6 +28,7 @@
 #ifndef UPB_COLLECTIONS_MAP_H_
 #define UPB_COLLECTIONS_MAP_H_
 
+#include "upb/base/descriptor_constants.h"
 #include "upb/collections/message_value.h"
 
 // Must be last.
@@ -73,7 +74,7 @@
          kUpb_MapInsertStatus_OutOfMemory;
 }
 
-/* Deletes this key from the table.  Returns true if the key was present. */
+// Deletes this key from the table. Returns true if the key was present.
 bool upb_Map_Delete(upb_Map* map, upb_MessageValue key);
 
 /* Map iteration:
@@ -88,7 +89,9 @@
  * }
  */
 
-/* Advances to the next entry.  Returns false if no more entries are present. */
+#define kUpb_Map_Begin ((size_t)-1)
+
+// Advances to the next entry. Returns false if no more entries are present.
 bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
 
 /* Returns true if the iterator still points to a valid entry, or false if the
diff --git a/upb/collections/map_internal.h b/upb/collections/map_internal.h
index b611abb..be85f3a 100644
--- a/upb/collections/map_internal.h
+++ b/upb/collections/map_internal.h
@@ -30,10 +30,10 @@
 #ifndef UPB_COLLECTIONS_MAP_INTERNAL_H_
 #define UPB_COLLECTIONS_MAP_INTERNAL_H_
 
+#include "upb/base/string_view.h"
 #include "upb/collections/map.h"
 #include "upb/internal/table.h"
 #include "upb/mem/arena.h"
-#include "upb/string_view.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/collections/map_sorter.c b/upb/collections/map_sorter.c
index 237ee2f..aa8a241 100644
--- a/upb/collections/map_sorter.c
+++ b/upb/collections/map_sorter.c
@@ -25,6 +25,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "upb/base/log2.h"
 #include "upb/collections/map_sorter_internal.h"
 
 // Must be last.
@@ -110,7 +111,7 @@
 
   // Grow s->entries if necessary.
   if (sorted->end > s->cap) {
-    s->cap = _upb_Log2CeilingSize(sorted->end);
+    s->cap = upb_Log2CeilingSize(sorted->end);
     s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
     if (!s->entries) return false;
   }
diff --git a/upb/collections/message_value.h b/upb/collections/message_value.h
index a0e7b19..f3b0128 100644
--- a/upb/collections/message_value.h
+++ b/upb/collections/message_value.h
@@ -28,9 +28,8 @@
 #ifndef UPB_MESSAGE_VALUE_H_
 #define UPB_MESSAGE_VALUE_H_
 
+#include "upb/base/string_view.h"
 #include "upb/msg.h"
-#include "upb/string_view.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/extension_registry.h b/upb/extension_registry.h
index 3c26420..4f31273 100644
--- a/upb/extension_registry.h
+++ b/upb/extension_registry.h
@@ -29,7 +29,6 @@
 #define UPB_EXTENSION_REGISTRY_H_
 
 #include "upb/msg.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/internal/table.c b/upb/internal/table.c
index b7a6eac..f50c7ae 100644
--- a/upb/internal/table.c
+++ b/upb/internal/table.c
@@ -35,6 +35,8 @@
 
 #include <string.h>
 
+#include "upb/base/log2.h"
+
 // Must be last.
 #include "upb/port/def.inc"
 
@@ -458,7 +460,7 @@
   // denominator.
   size_t need_entries = (expected_size + 1) * 1204 / 1024;
   UPB_ASSERT(need_entries >= expected_size * 0.85);
-  int size_lg2 = _upb_Log2Ceiling(need_entries);
+  int size_lg2 = upb_Log2Ceiling(need_entries);
   return init(&t->t, size_lg2, a);
 }
 
diff --git a/upb/internal/table.h b/upb/internal/table.h
index 6bb1e1a..7a31311 100644
--- a/upb/internal/table.h
+++ b/upb/internal/table.h
@@ -49,7 +49,9 @@
 
 #include <string.h>
 
-#include "upb/upb.h"
+#include "upb/base/descriptor_constants.h"
+#include "upb/base/string_view.h"
+#include "upb/mem/arena.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/io/BUILD b/upb/io/BUILD
index 3600a18..0f0632e 100644
--- a/upb/io/BUILD
+++ b/upb/io/BUILD
@@ -24,7 +24,8 @@
         ":string",
         ":strtod",
         ":zero_copy_stream",
-        "//:upb",
+        "//:base",
+        "//:mem",
         "//:port",
         "//:unicode_internal",
     ],
@@ -37,9 +38,9 @@
         "zero_copy_output_stream.h",
     ],
     deps = [
+        "//:base",
         "//:mem",
         "//:port",
-        "//:status",
     ],
 )
 
diff --git a/upb/io/tokenizer.h b/upb/io/tokenizer.h
index 1b6c3e6..d8a6c5c 100644
--- a/upb/io/tokenizer.h
+++ b/upb/io/tokenizer.h
@@ -30,9 +30,10 @@
 #ifndef UPB_IO_TOKENIZER_H_
 #define UPB_IO_TOKENIZER_H_
 
+#include "upb/base/status.h"
+#include "upb/base/string_view.h"
 #include "upb/io/zero_copy_input_stream.h"
-#include "upb/string_view.h"
-#include "upb/upb.h"
+#include "upb/mem/arena.h"
 
 // Must be included last.
 #include "upb/port/def.inc"
diff --git a/upb/io/zero_copy_input_stream.h b/upb/io/zero_copy_input_stream.h
index af83ee6..62520fc 100644
--- a/upb/io/zero_copy_input_stream.h
+++ b/upb/io/zero_copy_input_stream.h
@@ -28,7 +28,7 @@
 #ifndef UPB_IO_ZERO_COPY_INPUT_STREAM_H_
 #define UPB_IO_ZERO_COPY_INPUT_STREAM_H_
 
-#include "upb/status.h"
+#include "upb/base/status.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/io/zero_copy_output_stream.h b/upb/io/zero_copy_output_stream.h
index bab3aa6..9fd75ba 100644
--- a/upb/io/zero_copy_output_stream.h
+++ b/upb/io/zero_copy_output_stream.h
@@ -28,7 +28,7 @@
 #ifndef UPB_IO_ZERO_COPY_OUTPUT_STREAM_H_
 #define UPB_IO_ZERO_COPY_OUTPUT_STREAM_H_
 
-#include "upb/status.h"
+#include "upb/base/status.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/mini_table/accessors_test.cc b/upb/mini_table/accessors_test.cc
index 603ceee..100a859 100644
--- a/upb/mini_table/accessors_test.cc
+++ b/upb/mini_table/accessors_test.cc
@@ -40,7 +40,6 @@
 #include "upb/mini_table/decode.h"
 #include "upb/mini_table/encode_internal.hpp"
 #include "upb/test.upb.h"
-#include "upb/upb.h"
 #include "upb/wire/decode.h"
 
 namespace {
diff --git a/upb/mini_table/common.c b/upb/mini_table/common.c
index 6839599..818bfa2 100644
--- a/upb/mini_table/common.c
+++ b/upb/mini_table/common.c
@@ -31,7 +31,6 @@
 
 #include "upb/mem/arena.h"
 #include "upb/mini_table/common_internal.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/mini_table/common_internal.h b/upb/mini_table/common_internal.h
index c373d26..8a966b0 100644
--- a/upb/mini_table/common_internal.h
+++ b/upb/mini_table/common_internal.h
@@ -28,7 +28,7 @@
 #ifndef UPB_MINI_TABLE_COMMON_INTERNAL_H_
 #define UPB_MINI_TABLE_COMMON_INTERNAL_H_
 
-#include "upb/upb.h"
+#include "upb/base/descriptor_constants.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/mini_table/decode.c b/upb/mini_table/decode.c
index 6fa3642..1e7d4cf 100644
--- a/upb/mini_table/decode.c
+++ b/upb/mini_table/decode.c
@@ -29,10 +29,10 @@
 
 #include <inttypes.h>
 
+#include "upb/base/log2.h"
 #include "upb/mem/arena.h"
 #include "upb/mini_table/common.h"
 #include "upb/mini_table/common_internal.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
@@ -115,7 +115,7 @@
   uint32_t val = 0;
   uint32_t shift = 0;
   const int bits_per_char =
-      _upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min));
+      upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min));
   char ch = first_ch;
   while (1) {
     uint32_t bits = _upb_FromBase92(ch) - _upb_FromBase92(min);
@@ -534,8 +534,8 @@
   //  2. field_index (smallest numbers first)
   // The main goal of this is to reduce space lost to padding.
   // Later we may have more subtle reasons to prefer a different ordering.
-  const int rep_bits = _upb_Log2Ceiling(kUpb_FieldRep_Max);
-  const int type_bits = _upb_Log2Ceiling(kUpb_LayoutItemType_Max);
+  const int rep_bits = upb_Log2Ceiling(kUpb_FieldRep_Max);
+  const int type_bits = upb_Log2Ceiling(kUpb_LayoutItemType_Max);
   const int idx_bits = (sizeof(a->field_index) * 8);
   UPB_ASSERT(idx_bits + rep_bits + type_bits < 32);
 #define UPB_COMBINE(rep, ty, idx) (((rep << type_bits) | ty) << idx_bits) | idx
diff --git a/upb/mini_table/encode.c b/upb/mini_table/encode.c
index 80ddf57..176a7f4 100644
--- a/upb/mini_table/encode.c
+++ b/upb/mini_table/encode.c
@@ -27,11 +27,11 @@
 
 #include <inttypes.h>
 
+#include "upb/base/log2.h"
 #include "upb/mem/arena.h"
 #include "upb/mini_table/common.h"
 #include "upb/mini_table/common_internal.h"
 #include "upb/mini_table/encode_internal.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
@@ -82,7 +82,7 @@
 
 static char* upb_MtDataEncoder_PutBase92Varint(upb_MtDataEncoder* e, char* ptr,
                                                uint32_t val, int min, int max) {
-  int shift = _upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min) + 1);
+  int shift = upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min) + 1);
   UPB_ASSERT(shift <= 6);
   uint32_t mask = (1 << shift) - 1;
   do {
diff --git a/upb/mini_table/encode_internal.hpp b/upb/mini_table/encode_internal.hpp
index c8bea3e..ebfefbc 100644
--- a/upb/mini_table/encode_internal.hpp
+++ b/upb/mini_table/encode_internal.hpp
@@ -30,6 +30,7 @@
 
 #include <string>
 
+#include "upb/base/log2.h"
 #include "upb/mini_table/encode_internal.h"
 
 namespace upb {
@@ -114,7 +115,7 @@
       if (!end) return false;
       // C++ does not guarantee that string has doubling growth behavior, but
       // we need it to avoid O(n^2).
-      str_.reserve(_upb_Log2CeilingSize(str_.size() + (end - buf_)));
+      str_.reserve(upb_Log2CeilingSize(str_.size() + (end - buf_)));
       str_.append(buf_, end - buf_);
       return true;
     }
diff --git a/upb/mini_table/encode_test.cc b/upb/mini_table/encode_test.cc
index b376c6d..2dcb254 100644
--- a/upb/mini_table/encode_test.cc
+++ b/upb/mini_table/encode_test.cc
@@ -32,7 +32,6 @@
 #include "upb/mini_table/common_internal.h"
 #include "upb/mini_table/decode.h"
 #include "upb/mini_table/encode_internal.hpp"
-#include "upb/upb.h"
 #include "upb/upb.hpp"
 #include "upb/wire/decode.h"
 
diff --git a/upb/msg.c b/upb/msg.c
index 0de64a2..b8e1631e 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -29,6 +29,7 @@
 
 #include <math.h>
 
+#include "upb/base/log2.h"
 #include "upb/msg_internal.h"
 
 // Must be last.
@@ -59,7 +60,7 @@
   upb_Message_Internal* in = upb_Message_Getinternal(msg);
   if (!in->internal) {
     /* No internal data, allocate from scratch. */
-    size_t size = UPB_MAX(128, _upb_Log2CeilingSize(need + overhead));
+    size_t size = UPB_MAX(128, upb_Log2CeilingSize(need + overhead));
     upb_Message_InternalData* internal = upb_Arena_Malloc(arena, size);
     if (!internal) return false;
     internal->size = size;
@@ -68,7 +69,7 @@
     in->internal = internal;
   } else if (in->internal->ext_begin - in->internal->unknown_end < need) {
     /* Internal data is too small, reallocate. */
-    size_t new_size = _upb_Log2CeilingSize(in->internal->size + need);
+    size_t new_size = upb_Log2CeilingSize(in->internal->size + need);
     size_t ext_bytes = in->internal->size - in->internal->ext_begin;
     size_t new_ext_begin = new_size - ext_bytes;
     upb_Message_InternalData* internal =
diff --git a/upb/msg_internal.h b/upb/msg_internal.h
index 315390f..be8433a 100644
--- a/upb/msg_internal.h
+++ b/upb/msg_internal.h
@@ -38,11 +38,11 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "upb/base/status.h"
 #include "upb/collections/map_internal.h"
 #include "upb/extension_registry.h"
 #include "upb/internal/table.h"
 #include "upb/msg.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/reflection/def_pool.h b/upb/reflection/def_pool.h
index cdcdb38..dd02f73 100644
--- a/upb/reflection/def_pool.h
+++ b/upb/reflection/def_pool.h
@@ -30,9 +30,9 @@
 #ifndef UPB_REFLECTION_DEF_POOL_H_
 #define UPB_REFLECTION_DEF_POOL_H_
 
+#include "upb/base/string_view.h"
 #include "upb/reflection/common.h"
 #include "upb/reflection/def_type.h"
-#include "upb/string_view.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/reflection/enum_def.h b/upb/reflection/enum_def.h
index 07fb8aa..d8ee28b 100644
--- a/upb/reflection/enum_def.h
+++ b/upb/reflection/enum_def.h
@@ -30,8 +30,8 @@
 #ifndef UPB_REFLECTION_ENUM_DEF_H_
 #define UPB_REFLECTION_ENUM_DEF_H_
 
+#include "upb/base/string_view.h"
 #include "upb/reflection/common.h"
-#include "upb/string_view.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/reflection/field_def.h b/upb/reflection/field_def.h
index 8883b53..cd9af2a 100644
--- a/upb/reflection/field_def.h
+++ b/upb/reflection/field_def.h
@@ -30,8 +30,8 @@
 #ifndef UPB_REFLECTION_FIELD_DEF_H_
 #define UPB_REFLECTION_FIELD_DEF_H_
 
+#include "upb/base/string_view.h"
 #include "upb/reflection/common.h"
-#include "upb/string_view.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/reflection/message_def.h b/upb/reflection/message_def.h
index fb26bfe..3be3491 100644
--- a/upb/reflection/message_def.h
+++ b/upb/reflection/message_def.h
@@ -30,8 +30,8 @@
 #ifndef UPB_REFLECTION_MESSAGE_DEF_H_
 #define UPB_REFLECTION_MESSAGE_DEF_H_
 
+#include "upb/base/string_view.h"
 #include "upb/reflection/common.h"
-#include "upb/string_view.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/status.h b/upb/status.h
index aab12b3..c16be90 100644
--- a/upb/status.h
+++ b/upb/status.h
@@ -25,42 +25,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// This header is deprecated, use upb/base/status.h instead
+
 #ifndef UPB_STATUS_H_
 #define UPB_STATUS_H_
 
-#include <stdarg.h>
-
-// Must be last.
-#include "upb/port/def.inc"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define _kUpb_Status_MaxMessage 127
-
-typedef struct {
-  bool ok;
-  char msg[_kUpb_Status_MaxMessage]; /* Error message; NULL-terminated. */
-} upb_Status;
-
-const char* upb_Status_ErrorMessage(const upb_Status* status);
-bool upb_Status_IsOk(const upb_Status* status);
-
-/* These are no-op if |status| is NULL. */
-void upb_Status_Clear(upb_Status* status);
-void upb_Status_SetErrorMessage(upb_Status* status, const char* msg);
-void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...)
-    UPB_PRINTF(2, 3);
-void upb_Status_VSetErrorFormat(upb_Status* status, const char* fmt,
-                                va_list args) UPB_PRINTF(2, 0);
-void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
-                                   va_list args) UPB_PRINTF(2, 0);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#include "upb/port/undef.inc"
+#include "upb/base/status.h"
 
 #endif /* UPB_STATUS_H_ */
diff --git a/upb/string_view.h b/upb/string_view.h
index bc735d9..0e0fadd 100644
--- a/upb/string_view.h
+++ b/upb/string_view.h
@@ -25,51 +25,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// This header is deprecated, use upb/base/string_view.h instead
+
 #ifndef UPB_STRING_VIEW_H_
 #define UPB_STRING_VIEW_H_
 
-#include <string.h>
-
-// Must be last.
-#include "upb/port/def.inc"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// LINT.IfChange(struct_definition)
-typedef struct {
-  const char* data;
-  size_t size;
-} upb_StringView;
-// LINT.ThenChange(GoogleInternalName0)
-
-UPB_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data,
-                                                         size_t size) {
-  upb_StringView ret;
-  ret.data = data;
-  ret.size = size;
-  return ret;
-}
-
-UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) {
-  return upb_StringView_FromDataAndSize(data, strlen(data));
-}
-
-UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) {
-  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRINGVIEW_INIT(ptr, len) \
-  { ptr, len }
-
-#define UPB_STRINGVIEW_FORMAT "%.*s"
-#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#include "upb/port/undef.inc"
+#include "upb/base/string_view.h"
 
 #endif /* UPB_STRING_VIEW_H_ */
diff --git a/upb/test_cpp.cc b/upb/test_cpp.cc
index 51fca5b..cd18370 100644
--- a/upb/test_cpp.cc
+++ b/upb/test_cpp.cc
@@ -41,7 +41,6 @@
 #include "upb/reflection/def.hpp"
 #include "upb/test_cpp.upb.h"
 #include "upb/test_cpp.upbdefs.h"
-#include "upb/upb.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/upb.h b/upb/upb.h
index 4cb2bbb..526d3dd 100644
--- a/upb/upb.h
+++ b/upb/upb.h
@@ -25,128 +25,14 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * This file contains shared definitions that are widely used across upb.
- */
+// This header is deprecated, use the individual #includes below as needed.
 
 #ifndef UPB_H_
 #define UPB_H_
 
-#include <stdarg.h>
-#include <string.h>
-
-// TODO(b/232091617): Remove these and fix everything that breaks as a result.
+#include "upb/base/descriptor_constants.h"
+#include "upb/base/status.h"
+#include "upb/base/string_view.h"
 #include "upb/mem/arena.h"
-#include "upb/status.h"
-#include "upb/string_view.h"
-
-// Must be last.
-#include "upb/port/def.inc"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
-  kUpb_WireType_Varint = 0,
-  kUpb_WireType_64Bit = 1,
-  kUpb_WireType_Delimited = 2,
-  kUpb_WireType_StartGroup = 3,
-  kUpb_WireType_EndGroup = 4,
-  kUpb_WireType_32Bit = 5
-} upb_WireType;
-
-/* The types a field can have.  Note that this list is not identical to the
- * types defined in descriptor.proto, which gives INT32 and SINT32 separate
- * types (we distinguish the two with the "integer encoding" enum below). */
-typedef enum {
-  kUpb_CType_Bool = 1,
-  kUpb_CType_Float = 2,
-  kUpb_CType_Int32 = 3,
-  kUpb_CType_UInt32 = 4,
-  kUpb_CType_Enum = 5, /* Enum values are int32. */
-  kUpb_CType_Message = 6,
-  kUpb_CType_Double = 7,
-  kUpb_CType_Int64 = 8,
-  kUpb_CType_UInt64 = 9,
-  kUpb_CType_String = 10,
-  kUpb_CType_Bytes = 11
-} upb_CType;
-
-/* The repeated-ness of each field; this matches descriptor.proto. */
-typedef enum {
-  kUpb_Label_Optional = 1,
-  kUpb_Label_Required = 2,
-  kUpb_Label_Repeated = 3
-} upb_Label;
-
-/* Descriptor types, as defined in descriptor.proto. */
-typedef enum {
-  kUpb_FieldType_Double = 1,
-  kUpb_FieldType_Float = 2,
-  kUpb_FieldType_Int64 = 3,
-  kUpb_FieldType_UInt64 = 4,
-  kUpb_FieldType_Int32 = 5,
-  kUpb_FieldType_Fixed64 = 6,
-  kUpb_FieldType_Fixed32 = 7,
-  kUpb_FieldType_Bool = 8,
-  kUpb_FieldType_String = 9,
-  kUpb_FieldType_Group = 10,
-  kUpb_FieldType_Message = 11,
-  kUpb_FieldType_Bytes = 12,
-  kUpb_FieldType_UInt32 = 13,
-  kUpb_FieldType_Enum = 14,
-  kUpb_FieldType_SFixed32 = 15,
-  kUpb_FieldType_SFixed64 = 16,
-  kUpb_FieldType_SInt32 = 17,
-  kUpb_FieldType_SInt64 = 18,
-} upb_FieldType;
-
-#define kUpb_FieldType_SizeOf 19
-
-#define kUpb_Map_Begin ((size_t)-1)
-
-UPB_INLINE bool _upb_IsLittleEndian(void) {
-  int x = 1;
-  return *(char*)&x == 1;
-}
-
-UPB_INLINE uint32_t _upb_BigEndian_Swap32(uint32_t val) {
-  if (_upb_IsLittleEndian()) {
-    return val;
-  } else {
-    return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
-           ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
-  }
-}
-
-UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
-  if (_upb_IsLittleEndian()) {
-    return val;
-  } else {
-    return ((uint64_t)_upb_BigEndian_Swap32((uint32_t)val) << 32) |
-           _upb_BigEndian_Swap32((uint32_t)(val >> 32));
-  }
-}
-
-UPB_INLINE int _upb_Log2Ceiling(int x) {
-  if (x <= 1) return 0;
-#ifdef __GNUC__
-  return 32 - __builtin_clz(x - 1);
-#else
-  int lg2 = 0;
-  while (1 << lg2 < x) lg2++;
-  return lg2;
-#endif
-}
-
-UPB_INLINE int _upb_Log2CeilingSize(int x) { return 1 << _upb_Log2Ceiling(x); }
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#include "upb/port/undef.inc"
 
 #endif /* UPB_H_ */
diff --git a/upb/upb.hpp b/upb/upb.hpp
index e462f43..db217bb 100644
--- a/upb/upb.hpp
+++ b/upb/upb.hpp
@@ -28,7 +28,9 @@
 
 #include <memory>
 
-#include "upb/upb.h"
+#include "upb/base/descriptor_constants.h"
+#include "upb/base/status.h"
+#include "upb/mem/arena.h"
 
 namespace upb {
 
diff --git a/upb/util/BUILD b/upb/util/BUILD
index 486b424..0270ec8 100644
--- a/upb/util/BUILD
+++ b/upb/util/BUILD
@@ -117,6 +117,7 @@
     srcs = ["compare_test.cc"],
     deps = [
         ":compare",
+        "//:wire_internal",
         "@com_google_absl//absl/strings",
         "@com_google_googletest//:gtest_main",
     ],
diff --git a/upb/util/compare_test.cc b/upb/util/compare_test.cc
index a35c6b3..0a9a179 100644
--- a/upb/util/compare_test.cc
+++ b/upb/util/compare_test.cc
@@ -32,9 +32,10 @@
 #include <string_view>
 #include <vector>
 
-#include "absl/strings/string_view.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/strings/string_view.h"
+#include "upb/wire/swap_internal.h"
 
 struct UnknownField;
 
diff --git a/upb/wire/decode.c b/upb/wire/decode.c
index be267ab..a3167ff 100644
--- a/upb/wire/decode.c
+++ b/upb/wire/decode.c
@@ -31,9 +31,9 @@
 
 #include "upb/collections/array_internal.h"
 #include "upb/collections/map_internal.h"
-#include "upb/upb.h"
 #include "upb/wire/common_internal.h"
 #include "upb/wire/decode_internal.h"
+#include "upb/wire/swap_internal.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/wire/encode.c b/upb/wire/encode.c
index 556e9c1..51be995 100644
--- a/upb/wire/encode.c
+++ b/upb/wire/encode.c
@@ -34,6 +34,7 @@
 #include "upb/collections/array_internal.h"
 #include "upb/collections/map_sorter_internal.h"
 #include "upb/wire/common_internal.h"
+#include "upb/wire/swap_internal.h"
 
 // Must be last.
 #include "upb/port/def.inc"
diff --git a/upb/wire/swap_internal.h b/upb/wire/swap_internal.h
new file mode 100644
index 0000000..d79d4c3
--- /dev/null
+++ b/upb/wire/swap_internal.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google LLC 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 Google LLC 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 UPB_WIRE_SWAP_INTERNAL_H_
+#define UPB_WIRE_SWAP_INTERNAL_H_
+
+// Must be last.
+#include "upb/port/def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE bool _upb_IsLittleEndian(void) {
+  int x = 1;
+  return *(char*)&x == 1;
+}
+
+UPB_INLINE uint32_t _upb_BigEndian_Swap32(uint32_t val) {
+  if (_upb_IsLittleEndian()) return val;
+
+  return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+         ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+}
+
+UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
+  if (_upb_IsLittleEndian()) return val;
+
+  return ((uint64_t)_upb_BigEndian_Swap32((uint32_t)val) << 32) |
+         _upb_BigEndian_Swap32((uint32_t)(val >> 32));
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port/undef.inc"
+
+#endif /* UPB_WIRE_SWAP_INTERNAL_H_ */