(NFC) Refactored upbc header generation into smaller methods.

This is in anticipation of a larger upcoming refactor.
diff --git a/upbc/protoc-gen-upb.cc b/upbc/protoc-gen-upb.cc
index 7e52153..6e82f39 100644
--- a/upbc/protoc-gen-upb.cc
+++ b/upbc/protoc-gen-upb.cc
@@ -418,6 +418,338 @@
   }
 }
 
+void GenerateMessageFunctionsInHeader(const protobuf::Descriptor* message,
+                                      Output& output) {
+  output(
+      R"cc(
+        UPB_INLINE $0* $0_new(upb_Arena* arena) {
+          return ($0*)_upb_Message_New(&$1, arena);
+        }
+        UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) {
+          $0* ret = $0_new(arena);
+          if (!ret) return NULL;
+          if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+            return NULL;
+          }
+          return ret;
+        }
+        UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size,
+                                   const upb_ExtensionRegistry* extreg,
+                                   int options, upb_Arena* arena) {
+          $0* ret = $0_new(arena);
+          if (!ret) return NULL;
+          if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) !=
+              kUpb_DecodeStatus_Ok) {
+            return NULL;
+          }
+          return ret;
+        }
+        UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) {
+          return upb_Encode(msg, &$1, 0, arena, len);
+        }
+        UPB_INLINE char* $0_serialize_ex(const $0* msg, int options,
+                                         upb_Arena* arena, size_t* len) {
+          return upb_Encode(msg, &$1, options, arena, len);
+        }
+      )cc",
+      MessageName(message), MessageInit(message));
+}
+
+void GenerateOneofInHeader(const protobuf::OneofDescriptor* oneof,
+                           const MessageLayout& layout,
+                           absl::string_view msg_name, Output& output) {
+  std::string fullname = ToCIdent(oneof->full_name());
+  output("typedef enum {\n");
+  for (int j = 0; j < oneof->field_count(); j++) {
+    const protobuf::FieldDescriptor* field = oneof->field(j);
+    output("  $0_$1 = $2,\n", fullname, field->name(), field->number());
+  }
+  output(
+      "  $0_NOT_SET = 0\n"
+      "} $0_oneofcases;\n",
+      fullname);
+  output(
+      "UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) { "
+      "return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t); }\n"
+      "\n",
+      fullname, msg_name, oneof->name(),
+      GetSizeInit(layout.GetOneofCaseOffset(oneof)));
+}
+
+void GenerateHazzer(const protobuf::FieldDescriptor* field,
+                    const MessageLayout& layout, absl::string_view msg_name,
+                    Output& output) {
+  if (layout.HasHasbit(field)) {
+    output(
+        "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
+        "return _upb_hasbit(msg, $2); }\n",
+        msg_name, field->name(), layout.GetHasbitIndex(field));
+  } else if (field->real_containing_oneof()) {
+    output(
+        "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
+        "return _upb_getoneofcase(msg, $2) == $3; }\n",
+        msg_name, field->name(),
+        GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())),
+        field->number());
+  } else if (field->message_type()) {
+    output(
+        "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
+        "return _upb_has_submsg_nohasbit(msg, $2); }\n",
+        msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)));
+  }
+}
+
+void GenerateMapGetters(const protobuf::FieldDescriptor* field,
+                        const MessageLayout& layout, absl::string_view msg_name,
+                        Output& output) {
+  const protobuf::Descriptor* entry = field->message_type();
+  const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
+  const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
+  output(
+      "UPB_INLINE size_t $0_$1_size(const $0 *msg) {"
+      "return _upb_msg_map_size(msg, $2); }\n",
+      msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)));
+  output(
+      "UPB_INLINE bool $0_$1_get(const $0 *msg, $2 key, $3 *val) { "
+      "return _upb_msg_map_get(msg, $4, &key, $5, val, $6); }\n",
+      msg_name, field->name(), CType(key), CType(val),
+      GetSizeInit(layout.GetFieldOffset(field)),
+      key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+          ? "0"
+          : "sizeof(key)",
+      val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+          ? "0"
+          : "sizeof(*val)");
+  output(
+      "UPB_INLINE $0 $1_$2_next(const $1 *msg, size_t* iter) { "
+      "return ($0)_upb_msg_map_next(msg, $3, iter); }\n",
+      CTypeConst(field), msg_name, field->name(),
+      GetSizeInit(layout.GetFieldOffset(field)));
+}
+
+void GenerateMapEntryGetters(const protobuf::FieldDescriptor* field,
+                             absl::string_view msg_name, Output& output) {
+  output(
+      "UPB_INLINE $0 $1_$2(const $1 *msg) {\n"
+      "  $3 ret;\n"
+      "  _upb_msg_map_$2(msg, &ret, $4);\n"
+      "  return ret;\n"
+      "}\n",
+      CTypeConst(field), msg_name, field->name(), CType(field),
+      field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+          ? "0"
+          : "sizeof(ret)");
+}
+
+void GenerateRepeatedGetters(const protobuf::FieldDescriptor* field,
+                             const MessageLayout& layout,
+                             absl::string_view msg_name, Output& output) {
+  output(
+      "UPB_INLINE $0 const* $1_$2(const $1 *msg, size_t *len) { "
+      "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n",
+      CTypeConst(field), msg_name, field->name(),
+      GetSizeInit(layout.GetFieldOffset(field)));
+}
+
+void GenerateOneofGetters(const protobuf::FieldDescriptor* field,
+                          const MessageLayout& layout,
+                          absl::string_view msg_name, Output& output) {
+  output(
+      "UPB_INLINE $0 $1_$2(const $1 *msg) { "
+      "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n",
+      CTypeConst(field), msg_name, field->name(),
+      GetSizeInit(layout.GetFieldOffset(field)),
+      GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())),
+      field->number(), FieldDefault(field));
+}
+
+void GenerateScalarGetters(const protobuf::FieldDescriptor* field,
+                           const MessageLayout& layout,
+                           absl::string_view msg_name, Output& output) {
+  if (HasNonZeroDefault(field)) {
+    output(
+        R"cc(
+          UPB_INLINE $0 $1_$2(const $1* msg) {
+            return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
+          }
+        )cc",
+        CTypeConst(field), msg_name, field->name(),
+        GetSizeInit(layout.GetFieldOffset(field)), FieldDefault(field));
+  } else {
+    output(
+        R"cc(
+          UPB_INLINE $0 $1_$2(const $1* msg) {
+            return *UPB_PTR_AT(msg, $3, $0);
+          }
+        )cc",
+        CTypeConst(field), msg_name, field->name(),
+        GetSizeInit(layout.GetFieldOffset(field)));
+  }
+}
+
+void GenerateGetters(const protobuf::FieldDescriptor* field,
+                     const MessageLayout& layout, absl::string_view msg_name,
+                     Output& output) {
+  if (field->is_map()) {
+    GenerateMapGetters(field, layout, msg_name, output);
+  } else if (field->containing_type()->options().map_entry()) {
+    GenerateMapEntryGetters(field, msg_name, output);
+  } else if (field->is_repeated()) {
+    GenerateRepeatedGetters(field, layout, msg_name, output);
+  } else if (field->real_containing_oneof()) {
+    GenerateOneofGetters(field, layout, msg_name, output);
+  } else {
+    GenerateScalarGetters(field, layout, msg_name, output);
+  }
+}
+
+void GenerateMapSetters(const protobuf::FieldDescriptor* field,
+                        const MessageLayout& layout, absl::string_view msg_name,
+                        Output& output) {
+  const protobuf::Descriptor* entry = field->message_type();
+  const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
+  const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
+  output(
+      "UPB_INLINE void $0_$1_clear($0 *msg) { _upb_msg_map_clear(msg, "
+      "$2); "
+      "}\n",
+      msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)));
+  output(
+      "UPB_INLINE bool $0_$1_set($0 *msg, $2 key, $3 val, upb_Arena *a) "
+      "{ "
+      "return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a); }\n",
+      msg_name, field->name(), CType(key), CType(val),
+      GetSizeInit(layout.GetFieldOffset(field)),
+      key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+          ? "0"
+          : "sizeof(key)",
+      val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+          ? "0"
+          : "sizeof(val)");
+  output(
+      "UPB_INLINE bool $0_$1_delete($0 *msg, $2 key) { "
+      "return _upb_msg_map_delete(msg, $3, &key, $4); }\n",
+      msg_name, field->name(), CType(key),
+      GetSizeInit(layout.GetFieldOffset(field)),
+      key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+          ? "0"
+          : "sizeof(key)");
+  output(
+      "UPB_INLINE $0 $1_$2_nextmutable($1 *msg, size_t* iter) { "
+      "return ($0)_upb_msg_map_next(msg, $3, iter); }\n",
+      CType(field), msg_name, field->name(),
+      GetSizeInit(layout.GetFieldOffset(field)));
+}
+
+void GenerateRepeatedSetters(const protobuf::FieldDescriptor* field,
+                             const MessageLayout& layout,
+                             absl::string_view msg_name, Output& output) {
+  output(
+      "UPB_INLINE $0* $1_mutable_$2($1 *msg, size_t *len) {\n"
+      "  return ($0*)_upb_array_mutable_accessor(msg, $3, len);\n"
+      "}\n",
+      CType(field), msg_name, field->name(),
+      GetSizeInit(layout.GetFieldOffset(field)));
+  output(
+      "UPB_INLINE $0* $1_resize_$2($1 *msg, size_t len, "
+      "upb_Arena *arena) {\n"
+      "  return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, "
+      "arena);\n"
+      "}\n",
+      CType(field), msg_name, field->name(),
+      GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field));
+  if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+    output(
+        "UPB_INLINE struct $0* $1_add_$2($1 *msg, upb_Arena *arena) {\n"
+        "  struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);\n"
+        "  bool ok = _upb_Array_Append_accessor2(\n"
+        "      msg, $4, $5, &sub, arena);\n"
+        "  if (!ok) return NULL;\n"
+        "  return sub;\n"
+        "}\n",
+        MessageName(field->message_type()), msg_name, field->name(),
+        MessageInit(field->message_type()),
+        GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field));
+  } else {
+    output(
+        "UPB_INLINE bool $1_add_$2($1 *msg, $0 val, upb_Arena *arena) {\n"
+        "  return _upb_Array_Append_accessor2(msg, $3, $4, &val,\n"
+        "      arena);\n"
+        "}\n",
+        CType(field), msg_name, field->name(),
+        GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field));
+  }
+}
+
+void GenerateNonRepeatedSetters(const protobuf::FieldDescriptor* field,
+                                const MessageLayout& layout,
+                                absl::string_view msg_name, Output& output) {
+  if (field == field->containing_type()->map_key()) {
+    // Key cannot be mutated.
+    return;
+  }
+
+  // The common function signature for all setters.  Varying
+  // implementations follow.
+  output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name,
+         field->name(), CType(field));
+
+  if (field == field->containing_type()->map_value()) {
+    output(
+        "  _upb_msg_map_set_value(msg, &value, $0);\n"
+        "}\n",
+        field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
+            ? "0"
+            : "sizeof(" + CType(field) + ")");
+  } else if (field->real_containing_oneof()) {
+    output(
+        "  UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n"
+        "}\n",
+        CType(field), GetSizeInit(layout.GetFieldOffset(field)),
+        GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())),
+        field->number());
+  } else {
+    if (MessageLayout::HasHasbit(field)) {
+      output("  _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field));
+    }
+    output(
+        "  *UPB_PTR_AT(msg, $1, $0) = value;\n"
+        "}\n",
+        CType(field), GetSizeInit(layout.GetFieldOffset(field)));
+  }
+
+  // Message fields also have a Msg_mutable_foo() accessor that will create
+  // the sub-message if it doesn't already exist.
+  if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
+      !field->containing_type()->options().map_entry()) {
+    output(
+        "UPB_INLINE struct $0* $1_mutable_$2($1 *msg, upb_Arena *arena) "
+        "{\n"
+        "  struct $0* sub = (struct $0*)$1_$2(msg);\n"
+        "  if (sub == NULL) {\n"
+        "    sub = (struct $0*)_upb_Message_New(&$3, arena);\n"
+        "    if (!sub) return NULL;\n"
+        "    $1_set_$2(msg, sub);\n"
+        "  }\n"
+        "  return sub;\n"
+        "}\n",
+        MessageName(field->message_type()), msg_name, field->name(),
+        MessageInit(field->message_type()));
+  }
+}
+
+void GenerateSetters(const protobuf::FieldDescriptor* field,
+                     const MessageLayout& layout, absl::string_view msg_name,
+                     Output& output) {
+  if (field->is_map()) {
+    GenerateMapSetters(field, layout, msg_name, output);
+  } else if (field->is_repeated()) {
+    GenerateRepeatedSetters(field, layout, msg_name, output);
+  } else {
+    GenerateNonRepeatedSetters(field, layout, msg_name, output);
+  }
+}
+
 void GenerateMessageInHeader(const protobuf::Descriptor* message,
                              Output& output) {
   MessageLayout layout(message);
@@ -426,286 +758,22 @@
   std::string msg_name = ToCIdent(message->full_name());
 
   if (!message->options().map_entry()) {
-    output(
-        R"cc(
-          UPB_INLINE $0* $0_new(upb_Arena* arena) {
-            return ($0*)_upb_Message_New(&$1, arena);
-          }
-          UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) {
-            $0* ret = $0_new(arena);
-            if (!ret) return NULL;
-            if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
-              return NULL;
-            }
-            return ret;
-          }
-          UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size,
-                                     const upb_ExtensionRegistry* extreg,
-                                     int options, upb_Arena* arena) {
-            $0* ret = $0_new(arena);
-            if (!ret) return NULL;
-            if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) !=
-                kUpb_DecodeStatus_Ok) {
-              return NULL;
-            }
-            return ret;
-          }
-          UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) {
-            return upb_Encode(msg, &$1, 0, arena, len);
-          }
-          UPB_INLINE char* $0_serialize_ex(const $0* msg, int options,
-                                           upb_Arena* arena, size_t* len) {
-            return upb_Encode(msg, &$1, options, arena, len);
-          }
-        )cc",
-        MessageName(message), MessageInit(message));
+    GenerateMessageFunctionsInHeader(message, output);
   }
 
   for (int i = 0; i < message->real_oneof_decl_count(); i++) {
-    const protobuf::OneofDescriptor* oneof = message->oneof_decl(i);
-    std::string fullname = ToCIdent(oneof->full_name());
-    output("typedef enum {\n");
-    for (int j = 0; j < oneof->field_count(); j++) {
-      const protobuf::FieldDescriptor* field = oneof->field(j);
-      output("  $0_$1 = $2,\n", fullname, field->name(), field->number());
-    }
-    output(
-        "  $0_NOT_SET = 0\n"
-        "} $0_oneofcases;\n",
-        fullname);
-    output(
-        "UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) { "
-        "return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t); }\n"
-        "\n",
-        fullname, msg_name, oneof->name(),
-        GetSizeInit(layout.GetOneofCaseOffset(oneof)));
+    GenerateOneofInHeader(message->oneof_decl(i), layout, msg_name, output);
   }
 
-  // Generate const methods.
-
   for (auto field : FieldNumberOrder(message)) {
-    // Generate hazzer (if any).
-    if (layout.HasHasbit(field)) {
-      output(
-          "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
-          "return _upb_hasbit(msg, $2); }\n",
-          msg_name, field->name(), layout.GetHasbitIndex(field));
-    } else if (field->real_containing_oneof()) {
-      output(
-          "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
-          "return _upb_getoneofcase(msg, $2) == $3; }\n",
-          msg_name, field->name(),
-          GetSizeInit(
-              layout.GetOneofCaseOffset(field->real_containing_oneof())),
-          field->number());
-    } else if (field->message_type()) {
-      output(
-          "UPB_INLINE bool $0_has_$1(const $0 *msg) { "
-          "return _upb_has_submsg_nohasbit(msg, $2); }\n",
-          msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)));
-    }
-
-    // Generate getter.
-    if (field->is_map()) {
-      const protobuf::Descriptor* entry = field->message_type();
-      const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
-      const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
-      output(
-          "UPB_INLINE size_t $0_$1_size(const $0 *msg) {"
-          "return _upb_msg_map_size(msg, $2); }\n",
-          msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)));
-      output(
-          "UPB_INLINE bool $0_$1_get(const $0 *msg, $2 key, $3 *val) { "
-          "return _upb_msg_map_get(msg, $4, &key, $5, val, $6); }\n",
-          msg_name, field->name(), CType(key), CType(val),
-          GetSizeInit(layout.GetFieldOffset(field)),
-          key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-              ? "0"
-              : "sizeof(key)",
-          val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-              ? "0"
-              : "sizeof(*val)");
-      output(
-          "UPB_INLINE $0 $1_$2_next(const $1 *msg, size_t* iter) { "
-          "return ($0)_upb_msg_map_next(msg, $3, iter); }\n",
-          CTypeConst(field), msg_name, field->name(),
-          GetSizeInit(layout.GetFieldOffset(field)));
-    } else if (message->options().map_entry()) {
-      output(
-          "UPB_INLINE $0 $1_$2(const $1 *msg) {\n"
-          "  $3 ret;\n"
-          "  _upb_msg_map_$2(msg, &ret, $4);\n"
-          "  return ret;\n"
-          "}\n",
-          CTypeConst(field), msg_name, field->name(), CType(field),
-          field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-              ? "0"
-              : "sizeof(ret)");
-    } else if (field->is_repeated()) {
-      output(
-          "UPB_INLINE $0 const* $1_$2(const $1 *msg, size_t *len) { "
-          "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n",
-          CTypeConst(field), msg_name, field->name(),
-          GetSizeInit(layout.GetFieldOffset(field)));
-    } else if (field->real_containing_oneof()) {
-      output(
-          "UPB_INLINE $0 $1_$2(const $1 *msg) { "
-          "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n",
-          CTypeConst(field), msg_name, field->name(),
-          GetSizeInit(layout.GetFieldOffset(field)),
-          GetSizeInit(
-              layout.GetOneofCaseOffset(field->real_containing_oneof())),
-          field->number(), FieldDefault(field));
-    } else {
-      if (HasNonZeroDefault(field)) {
-        output(
-            R"cc(
-              UPB_INLINE $0 $1_$2(const $1* msg) {
-                return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
-              }
-            )cc",
-            CTypeConst(field), msg_name, field->name(),
-            GetSizeInit(layout.GetFieldOffset(field)), FieldDefault(field));
-      } else {
-        output(
-            R"cc(
-              UPB_INLINE $0 $1_$2(const $1* msg) {
-                return *UPB_PTR_AT(msg, $3, $0);
-              }
-            )cc",
-            CTypeConst(field), msg_name, field->name(),
-            GetSizeInit(layout.GetFieldOffset(field)));
-      }
-    }
+    GenerateHazzer(field, layout, msg_name, output);
+    GenerateGetters(field, layout, msg_name, output);
   }
 
   output("\n");
 
-  // Generate mutable methods.
-
   for (auto field : FieldNumberOrder(message)) {
-    if (field->is_map()) {
-      // TODO(haberman): add map-based mutators.
-      const protobuf::Descriptor* entry = field->message_type();
-      const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1);
-      const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2);
-      output(
-          "UPB_INLINE void $0_$1_clear($0 *msg) { _upb_msg_map_clear(msg, $2); "
-          "}\n",
-          msg_name, field->name(), GetSizeInit(layout.GetFieldOffset(field)));
-      output(
-          "UPB_INLINE bool $0_$1_set($0 *msg, $2 key, $3 val, upb_Arena *a) { "
-          "return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a); }\n",
-          msg_name, field->name(), CType(key), CType(val),
-          GetSizeInit(layout.GetFieldOffset(field)),
-          key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-              ? "0"
-              : "sizeof(key)",
-          val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-              ? "0"
-              : "sizeof(val)");
-      output(
-          "UPB_INLINE bool $0_$1_delete($0 *msg, $2 key) { "
-          "return _upb_msg_map_delete(msg, $3, &key, $4); }\n",
-          msg_name, field->name(), CType(key),
-          GetSizeInit(layout.GetFieldOffset(field)),
-          key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-              ? "0"
-              : "sizeof(key)");
-      output(
-          "UPB_INLINE $0 $1_$2_nextmutable($1 *msg, size_t* iter) { "
-          "return ($0)_upb_msg_map_next(msg, $3, iter); }\n",
-          CType(field), msg_name, field->name(),
-          GetSizeInit(layout.GetFieldOffset(field)));
-    } else if (field->is_repeated()) {
-      output(
-          "UPB_INLINE $0* $1_mutable_$2($1 *msg, size_t *len) {\n"
-          "  return ($0*)_upb_array_mutable_accessor(msg, $3, len);\n"
-          "}\n",
-          CType(field), msg_name, field->name(),
-          GetSizeInit(layout.GetFieldOffset(field)));
-      output(
-          "UPB_INLINE $0* $1_resize_$2($1 *msg, size_t len, "
-          "upb_Arena *arena) {\n"
-          "  return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, "
-          "arena);\n"
-          "}\n",
-          CType(field), msg_name, field->name(),
-          GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field));
-      if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
-        output(
-            "UPB_INLINE struct $0* $1_add_$2($1 *msg, upb_Arena *arena) {\n"
-            "  struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);\n"
-            "  bool ok = _upb_Array_Append_accessor2(\n"
-            "      msg, $4, $5, &sub, arena);\n"
-            "  if (!ok) return NULL;\n"
-            "  return sub;\n"
-            "}\n",
-            MessageName(field->message_type()), msg_name, field->name(),
-            MessageInit(field->message_type()),
-            GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field));
-      } else {
-        output(
-            "UPB_INLINE bool $1_add_$2($1 *msg, $0 val, upb_Arena *arena) {\n"
-            "  return _upb_Array_Append_accessor2(msg, $3, $4, &val,\n"
-            "      arena);\n"
-            "}\n",
-            CType(field), msg_name, field->name(),
-            GetSizeInit(layout.GetFieldOffset(field)), SizeLg2(field));
-      }
-    } else {
-      // Non-repeated field.
-      if (message->options().map_entry() && field->name() == "key") {
-        // Key cannot be mutated.
-        continue;
-      }
-
-      // The common function signature for all setters.  Varying implementations
-      // follow.
-      output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name,
-             field->name(), CType(field));
-
-      if (message->options().map_entry()) {
-        output(
-            "  _upb_msg_map_set_value(msg, &value, $0);\n"
-            "}\n",
-            field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING
-                ? "0"
-                : "sizeof(" + CType(field) + ")");
-      } else if (field->real_containing_oneof()) {
-        output(
-            "  UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n"
-            "}\n",
-            CType(field), GetSizeInit(layout.GetFieldOffset(field)),
-            GetSizeInit(
-                layout.GetOneofCaseOffset(field->real_containing_oneof())),
-            field->number());
-      } else {
-        if (MessageLayout::HasHasbit(field)) {
-          output("  _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field));
-        }
-        output(
-            "  *UPB_PTR_AT(msg, $1, $0) = value;\n"
-            "}\n",
-            CType(field), GetSizeInit(layout.GetFieldOffset(field)));
-      }
-
-      if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
-          !message->options().map_entry()) {
-        output(
-            "UPB_INLINE struct $0* $1_mutable_$2($1 *msg, upb_Arena *arena) {\n"
-            "  struct $0* sub = (struct $0*)$1_$2(msg);\n"
-            "  if (sub == NULL) {\n"
-            "    sub = (struct $0*)_upb_Message_New(&$3, arena);\n"
-            "    if (!sub) return NULL;\n"
-            "    $1_set_$2(msg, sub);\n"
-            "  }\n"
-            "  return sub;\n"
-            "}\n",
-            MessageName(field->message_type()), msg_name, field->name(),
-            MessageInit(field->message_type()));
-      }
-    }
+    GenerateSetters(field, layout, msg_name, output);
   }
 
   output("\n");