Merge pull request #460 from haberman/encode-required

Added required field checking into the encoder
diff --git a/cmake/google/protobuf/descriptor.upb.h b/cmake/google/protobuf/descriptor.upb.h
index 95feda0..e31f6e0 100644
--- a/cmake/google/protobuf/descriptor.upb.h
+++ b/cmake/google/protobuf/descriptor.upb.h
@@ -188,6 +188,12 @@
 UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize_ex(const google_protobuf_FileDescriptorSet *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_FileDescriptorSet_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
 UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
 
@@ -232,6 +238,12 @@
 UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize_ex(const google_protobuf_FileDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_FileDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -412,6 +424,12 @@
 UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_DescriptorProto_serialize_ex(const google_protobuf_DescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_DescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -582,6 +600,12 @@
 UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize_ex(const google_protobuf_DescriptorProto_ExtensionRange *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
@@ -644,6 +668,12 @@
 UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize_ex(const google_protobuf_DescriptorProto_ReservedRange *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
@@ -689,6 +719,12 @@
 UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize_ex(const google_protobuf_ExtensionRangeOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_ExtensionRangeOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
 UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
 
@@ -733,6 +769,12 @@
 UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize_ex(const google_protobuf_FieldDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_FieldDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview);
@@ -859,6 +901,12 @@
 UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize_ex(const google_protobuf_OneofDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_OneofDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -913,6 +961,12 @@
 UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize_ex(const google_protobuf_EnumDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_EnumDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -1008,6 +1062,12 @@
 UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize_ex(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
@@ -1053,6 +1113,12 @@
 UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize_ex(const google_protobuf_EnumValueDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_EnumValueDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview);
@@ -1115,6 +1181,12 @@
 UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize_ex(const google_protobuf_ServiceDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_ServiceDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -1184,6 +1256,12 @@
 UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize_ex(const google_protobuf_MethodDescriptorProto *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_MethodDescriptorProto_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -1270,6 +1348,12 @@
 UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_FileOptions_serialize_ex(const google_protobuf_FileOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_FileOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview);
@@ -1474,6 +1558,12 @@
 UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_MessageOptions_serialize_ex(const google_protobuf_MessageOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_MessageOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
@@ -1550,6 +1640,12 @@
 UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_FieldOptions_serialize_ex(const google_protobuf_FieldOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_FieldOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
@@ -1642,6 +1738,12 @@
 UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_OneofOptions_serialize_ex(const google_protobuf_OneofOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_OneofOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
 UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
 
@@ -1686,6 +1788,12 @@
 UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_EnumOptions_serialize_ex(const google_protobuf_EnumOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_EnumOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
@@ -1746,6 +1854,12 @@
 UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_EnumValueOptions_serialize_ex(const google_protobuf_EnumValueOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_EnumValueOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
@@ -1798,6 +1912,12 @@
 UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_ServiceOptions_serialize_ex(const google_protobuf_ServiceOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_ServiceOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
@@ -1850,6 +1970,12 @@
 UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_MethodOptions_serialize_ex(const google_protobuf_MethodOptions *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_MethodOptions_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool);
@@ -1910,6 +2036,12 @@
 UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_UninterpretedOption_serialize_ex(const google_protobuf_UninterpretedOption *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_UninterpretedOption_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
 UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
 UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); }
@@ -2002,6 +2134,12 @@
 UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize_ex(const google_protobuf_UninterpretedOption_NamePart *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) {
   return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview);
@@ -2047,6 +2185,12 @@
 UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize_ex(const google_protobuf_SourceCodeInfo *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_SourceCodeInfo_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
 UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
 
@@ -2091,6 +2235,12 @@
 UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize_ex(const google_protobuf_SourceCodeInfo_Location *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_SourceCodeInfo_Location_msginit, options, arena, len);
+}
 UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
 UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
 UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 1); }
@@ -2169,6 +2319,12 @@
 UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize_ex(const google_protobuf_GeneratedCodeInfo *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_GeneratedCodeInfo_msginit, options, arena, len);
+}
 UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
 UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
 
@@ -2213,6 +2369,12 @@
 UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
   return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
 }
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize_ex(const google_protobuf_GeneratedCodeInfo_Annotation *msg,
+                                 int options,
+                                 upb_arena *arena,
+                                 size_t *len) {
+  return upb_encode_ex(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, options, arena, len);
+}
 UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
 UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); }
 UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) {
diff --git a/upb/decode.c b/upb/decode.c
index 4a54ac0..39a07bf 100644
--- a/upb/decode.c
+++ b/upb/decode.c
@@ -690,17 +690,6 @@
   return ptr;
 }
 
-// Computes a bitmask in which the |n| lowest bits are set, except that we
-// skip the lowest bit (because upb never uses hasbit 0).
-//
-// Sample output:
-//    decode_requiredmask(1) => 0b10 (0x2)
-//    decode_requiredmask(5) => 0b111110 (0x3e)
-uint64_t decode_requiredmask(int n) {
-  assert(0 < n && n < 63);
-  return ((1 << n) - 1) << 1;
-}
-
 UPB_NOINLINE
 const char *decode_checkrequired(upb_decstate *d, const char *ptr,
                                  const upb_msg *msg, const upb_msglayout *l) {
@@ -711,7 +700,7 @@
   uint64_t msg_head;
   memcpy(&msg_head, msg, 8);
   msg_head = _upb_be_swap64(msg_head);
-  if (decode_requiredmask(l->required_count) & ~msg_head) {
+  if (upb_msglayout_requiredmask(l) & ~msg_head) {
     d->missing_required = true;
   }
   return ptr;
diff --git a/upb/encode.c b/upb/encode.c
index 694327a..6a35ff0 100644
--- a/upb/encode.c
+++ b/upb/encode.c
@@ -511,6 +511,15 @@
                            const upb_msglayout *m, size_t *size) {
   size_t pre_len = e->limit - e->ptr;
 
+  if ((e->options & UPB_ENCODE_CHECKREQUIRED) && m->required_count) {
+    uint64_t msg_head;
+    memcpy(&msg_head, msg, 8);
+    msg_head = _upb_be_swap64(msg_head);
+    if (upb_msglayout_requiredmask(m) & ~msg_head) {
+      encode_err(e);
+    }
+  }
+
   if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) {
     size_t unknown_size;
     const char *unknown = upb_msg_getunknown(msg, &unknown_size);
diff --git a/upb/encode.h b/upb/encode.h
index 3ea2003..922e6d4 100644
--- a/upb/encode.h
+++ b/upb/encode.h
@@ -52,6 +52,9 @@
 
   /* When set, unknown fields are not printed. */
   UPB_ENCODE_SKIPUNKNOWN = 2,
+
+  /* When set, the encode will fail if any required fields are missing. */
+  UPB_ENCODE_CHECKREQUIRED = 4,
 };
 
 #define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
diff --git a/upb/msg_internal.h b/upb/msg_internal.h
index 89a4874..247f7e6 100644
--- a/upb/msg_internal.h
+++ b/upb/msg_internal.h
@@ -198,6 +198,18 @@
   int ext_count;
 } upb_msglayout_file;
 
+// Computes a bitmask in which the |l->required_count| lowest bits are set,
+// except that we skip the lowest bit (because upb never uses hasbit 0).
+//
+// Sample output:
+//    requiredmask(1) => 0b10 (0x2)
+//    requiredmask(5) => 0b111110 (0x3e)
+UPB_INLINE uint64_t upb_msglayout_requiredmask(const upb_msglayout *l) {
+  int n = l->required_count;
+  assert(0 < n && n <= 63);
+  return ((1ULL << n) - 1) << 1;
+}
+
 /** upb_extreg ****************************************************************/
 
 /* Adds the given extension info for message type |l| and field number |num|
diff --git a/upb/msg_test.cc b/upb/msg_test.cc
index 35cfb1a..d390f01 100644
--- a/upb/msg_test.cc
+++ b/upb/msg_test.cc
@@ -25,8 +25,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "gtest/gtest.h"
 #include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "src/google/protobuf/test_messages_proto3.upb.h"
 #include "upb/def.hpp"
 #include "upb/json_decode.h"
@@ -233,7 +233,7 @@
                          serialized.data(), serialized.size(), arena.ptr()));
 }
 
-TEST(MessageTest, RequiredFieldsTopLevelMessage) {
+TEST(MessageTest, DecodeRequiredFieldsTopLevelMessage) {
   upb::Arena arena;
   upb_test_TestRequiredFields *test_msg;
   upb_test_EmptyMessage *empty_msg;
@@ -291,7 +291,7 @@
                         kUpb_DecodeOption_CheckRequired, arena.ptr()));
 }
 
-TEST(MessageTest, RequiredFieldsSubMessage) {
+TEST(MessageTest, DecodeRequiredFieldsSubMessage) {
   upb::Arena arena;
   upb_test_TestRequiredFields *test_msg =
       upb_test_TestRequiredFields_new(arena.ptr());
@@ -326,3 +326,72 @@
                          serialized, size, NULL,
                          kUpb_DecodeOption_CheckRequired, arena.ptr()));
 }
+
+TEST(MessageTest, EncodeRequiredFields) {
+  upb::Arena arena;
+  upb_test_TestRequiredFields *test_msg =
+      upb_test_TestRequiredFields_new(arena.ptr());
+
+  // Succeeds, we didn't ask for required field checking.
+  size_t size;
+  char* serialized =
+      upb_test_TestRequiredFields_serialize_ex(test_msg, 0, arena.ptr(), &size);
+  ASSERT_TRUE(serialized != nullptr);
+  EXPECT_EQ(size, 0);
+
+  // Fails, we asked for required field checking but the required field is
+  // missing.
+  serialized = upb_test_TestRequiredFields_serialize_ex(
+      test_msg, UPB_ENCODE_CHECKREQUIRED, arena.ptr(), &size);
+  ASSERT_TRUE(serialized == nullptr);
+
+  // Fails, some required fields are present but not others.
+  upb_test_TestRequiredFields_set_required_int32(test_msg, 1);
+  serialized = upb_test_TestRequiredFields_serialize_ex(
+      test_msg, UPB_ENCODE_CHECKREQUIRED, arena.ptr(), &size);
+  ASSERT_TRUE(serialized == nullptr);
+
+  // Succeeds, all required fields are set.
+  upb_test_EmptyMessage *empty_msg = upb_test_EmptyMessage_new(arena.ptr());
+  upb_test_TestRequiredFields_set_required_int64(test_msg, 2);
+  upb_test_TestRequiredFields_set_required_message(test_msg, empty_msg);
+  serialized = upb_test_TestRequiredFields_serialize_ex(
+      test_msg, UPB_ENCODE_CHECKREQUIRED, arena.ptr(), &size);
+  ASSERT_TRUE(serialized != nullptr);
+}
+
+TEST(MessageTest, MaxRequiredFields) {
+  upb::Arena arena;
+  upb_test_TestMaxRequiredFields *test_msg =
+      upb_test_TestMaxRequiredFields_new(arena.ptr());
+
+  // Fails, we asked for required field checking but the required field is
+  // missing.
+  size_t size;
+  char* serialized = upb_test_TestMaxRequiredFields_serialize_ex(
+      test_msg, UPB_ENCODE_CHECKREQUIRED, arena.ptr(), &size);
+  ASSERT_TRUE(serialized == nullptr);
+
+  upb::SymbolTable symtab;
+  upb::MessageDefPtr m(upb_test_TestMaxRequiredFields_getmsgdef(symtab.ptr()));
+  upb_msgval val;
+  val.int32_val = 1;
+  for (int i = 1; i <= 61; i++) {
+    upb::FieldDefPtr f = m.FindFieldByNumber(i);
+    ASSERT_TRUE(f);
+    upb_msg_set(test_msg, f.ptr(), val, arena.ptr());
+  }
+
+  // Fails, field 63 still isn't set.
+  serialized = upb_test_TestMaxRequiredFields_serialize_ex(
+      test_msg, UPB_ENCODE_CHECKREQUIRED, arena.ptr(), &size);
+  ASSERT_TRUE(serialized == nullptr);
+
+  // Succeeds, all required fields are set.
+  upb::FieldDefPtr f = m.FindFieldByNumber(62);
+  ASSERT_TRUE(f);
+  upb_msg_set(test_msg, f.ptr(), val, arena.ptr());
+  serialized = upb_test_TestMaxRequiredFields_serialize_ex(
+      test_msg, UPB_ENCODE_CHECKREQUIRED, arena.ptr(), &size);
+  ASSERT_TRUE(serialized != nullptr);
+}
diff --git a/upb/msg_test.proto b/upb/msg_test.proto
index 9c49beb..81c7dee 100644
--- a/upb/msg_test.proto
+++ b/upb/msg_test.proto
@@ -93,3 +93,68 @@
 message SubMessageHasRequired {
   optional TestRequiredFields optional_message = 1;
 }
+
+message TestMaxRequiredFields {
+  required int32 required_int32_1 = 1;
+  required int32 required_int32_2 = 2;
+  required int32 required_int32_3 = 3;
+  required int32 required_int32_4 = 4;
+  required int32 required_int32_5 = 5;
+  required int32 required_int32_6 = 6;
+  required int32 required_int32_7 = 7;
+  required int32 required_int32_8 = 8;
+  required int32 required_int32_9 = 9;
+  required int32 required_int32_10 = 10;
+  required int32 required_int32_11 = 11;
+  required int32 required_int32_12 = 12;
+  required int32 required_int32_13 = 13;
+  required int32 required_int32_14 = 14;
+  required int32 required_int32_15 = 15;
+  required int32 required_int32_16 = 16;
+  required int32 required_int32_17 = 17;
+  required int32 required_int32_18 = 18;
+  required int32 required_int32_19 = 19;
+  required int32 required_int32_20 = 20;
+  required int32 required_int32_21 = 21;
+  required int32 required_int32_22 = 22;
+  required int32 required_int32_23 = 23;
+  required int32 required_int32_24 = 24;
+  required int32 required_int32_25 = 25;
+  required int32 required_int32_26 = 26;
+  required int32 required_int32_27 = 27;
+  required int32 required_int32_28 = 28;
+  required int32 required_int32_29 = 29;
+  required int32 required_int32_30 = 30;
+  required int32 required_int32_31 = 31;
+  required int32 required_int32_32 = 32;
+  required int32 required_int32_33 = 33;
+  required int32 required_int32_34 = 34;
+  required int32 required_int32_35 = 35;
+  required int32 required_int32_36 = 36;
+  required int32 required_int32_37 = 37;
+  required int32 required_int32_38 = 38;
+  required int32 required_int32_39 = 39;
+  required int32 required_int32_40 = 40;
+  required int32 required_int32_41 = 41;
+  required int32 required_int32_42 = 42;
+  required int32 required_int32_43 = 43;
+  required int32 required_int32_44 = 44;
+  required int32 required_int32_45 = 45;
+  required int32 required_int32_46 = 46;
+  required int32 required_int32_47 = 47;
+  required int32 required_int32_48 = 48;
+  required int32 required_int32_49 = 49;
+  required int32 required_int32_50 = 50;
+  required int32 required_int32_51 = 51;
+  required int32 required_int32_52 = 52;
+  required int32 required_int32_53 = 53;
+  required int32 required_int32_54 = 54;
+  required int32 required_int32_55 = 55;
+  required int32 required_int32_56 = 56;
+  required int32 required_int32_57 = 57;
+  required int32 required_int32_58 = 58;
+  required int32 required_int32_59 = 59;
+  required int32 required_int32_60 = 60;
+  required int32 required_int32_61 = 61;
+  required int32 required_int32_62 = 62;
+}
diff --git a/upbc/message_layout.cc b/upbc/message_layout.cc
index 92465a8..62eefde 100644
--- a/upbc/message_layout.cc
+++ b/upbc/message_layout.cc
@@ -175,7 +175,7 @@
       int index = ++hasbit_count_;
       hasbit_indexes_[field] = index;
       if (field->is_required()) {
-        if (index >= 63) {
+        if (index > 63) {
           // This could be fixed in the decoder without too much trouble.  But
           // we expect this to be so rare that we don't worry about it for now.
           std::cerr << "upb does not support messages with more than 63 "
diff --git a/upbc/protoc-gen-upb.cc b/upbc/protoc-gen-upb.cc
index ef88363..4bf9239 100644
--- a/upbc/protoc-gen-upb.cc
+++ b/upbc/protoc-gen-upb.cc
@@ -437,6 +437,12 @@
           UPB_INLINE char *$0_serialize(const $0 *msg, upb_arena *arena, size_t *len) {
             return upb_encode(msg, &$1, arena, len);
           }
+          UPB_INLINE char *$0_serialize_ex(const $0 *msg,
+                                           int options,
+                                           upb_arena *arena,
+                                           size_t *len) {
+            return upb_encode_ex(msg, &$1, options, arena, len);
+          }
         )cc",
         MessageName(message), MessageInit(message));
   }