2828#include "upb/mini_table.h"
2929
3030#include <inttypes.h>
31- #include <setjmp.h>
3231
3332#include "upb/arena.h"
3433#include "upb/msg_internal.h"
8685enum {
8786 kUpb_EncodedVersion_EnumV1 = '!' ,
8887 kUpb_EncodedVersion_ExtensionV1 = '#' ,
88+ kUpb_EncodedVersion_MapV1 = '%' ,
8989 kUpb_EncodedVersion_MessageV1 = '$' ,
9090};
9191
@@ -213,6 +213,24 @@ char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
213213 return upb_MtDataEncoder_PutField (e , ptr , type , field_num , field_mod );
214214}
215215
216+ char * upb_MtDataEncoder_EncodeMap (upb_MtDataEncoder * e , char * ptr ,
217+ upb_FieldType key_type ,
218+ upb_FieldType value_type ,
219+ uint64_t value_mod ) {
220+ upb_MtDataEncoderInternal * in = upb_MtDataEncoder_GetInternal (e , ptr );
221+ in -> state .msg_state .msg_modifiers = 0 ;
222+ in -> state .msg_state .last_field_num = 0 ;
223+ in -> state .msg_state .oneof_state = kUpb_OneofState_NotStarted ;
224+
225+ ptr = upb_MtDataEncoder_PutRaw (e , ptr , kUpb_EncodedVersion_MapV1 );
226+ if (!ptr ) return NULL ;
227+
228+ ptr = upb_MtDataEncoder_PutField (e , ptr , key_type , 1 , 0 );
229+ if (!ptr ) return NULL ;
230+
231+ return upb_MtDataEncoder_PutField (e , ptr , value_type , 2 , value_mod );
232+ }
233+
216234char * upb_MtDataEncoder_StartMessage (upb_MtDataEncoder * e , char * ptr ,
217235 uint64_t msg_mod ) {
218236 upb_MtDataEncoderInternal * in = upb_MtDataEncoder_GetInternal (e , ptr );
@@ -537,6 +555,28 @@ static void upb_MiniTable_SetTypeAndSub(upb_MiniTable_Field* field,
537555 }
538556}
539557
558+ static const char kUpb_EncodedToType [] = {
559+ [kUpb_EncodedType_Double ] = kUpb_FieldType_Double ,
560+ [kUpb_EncodedType_Float ] = kUpb_FieldType_Float ,
561+ [kUpb_EncodedType_Int64 ] = kUpb_FieldType_Int64 ,
562+ [kUpb_EncodedType_UInt64 ] = kUpb_FieldType_UInt64 ,
563+ [kUpb_EncodedType_Int32 ] = kUpb_FieldType_Int32 ,
564+ [kUpb_EncodedType_Fixed64 ] = kUpb_FieldType_Fixed64 ,
565+ [kUpb_EncodedType_Fixed32 ] = kUpb_FieldType_Fixed32 ,
566+ [kUpb_EncodedType_Bool ] = kUpb_FieldType_Bool ,
567+ [kUpb_EncodedType_String ] = kUpb_FieldType_String ,
568+ [kUpb_EncodedType_Group ] = kUpb_FieldType_Group ,
569+ [kUpb_EncodedType_Message ] = kUpb_FieldType_Message ,
570+ [kUpb_EncodedType_Bytes ] = kUpb_FieldType_Bytes ,
571+ [kUpb_EncodedType_UInt32 ] = kUpb_FieldType_UInt32 ,
572+ [kUpb_EncodedType_OpenEnum ] = kUpb_FieldType_Enum ,
573+ [kUpb_EncodedType_SFixed32 ] = kUpb_FieldType_SFixed32 ,
574+ [kUpb_EncodedType_SFixed64 ] = kUpb_FieldType_SFixed64 ,
575+ [kUpb_EncodedType_SInt32 ] = kUpb_FieldType_SInt32 ,
576+ [kUpb_EncodedType_SInt64 ] = kUpb_FieldType_SInt64 ,
577+ [kUpb_EncodedType_ClosedEnum ] = kUpb_FieldType_Enum ,
578+ };
579+
540580static void upb_MiniTable_SetField (upb_MtDecoder * d , uint8_t ch ,
541581 upb_MiniTable_Field * field ,
542582 uint64_t msg_modifiers ,
@@ -561,28 +601,6 @@ static void upb_MiniTable_SetField(upb_MtDecoder* d, uint8_t ch,
561601 [kUpb_EncodedType_ClosedEnum ] = kUpb_FieldRep_4Byte ,
562602 };
563603
564- static const char kUpb_EncodedToType [] = {
565- [kUpb_EncodedType_Double ] = kUpb_FieldType_Double ,
566- [kUpb_EncodedType_Float ] = kUpb_FieldType_Float ,
567- [kUpb_EncodedType_Int64 ] = kUpb_FieldType_Int64 ,
568- [kUpb_EncodedType_UInt64 ] = kUpb_FieldType_UInt64 ,
569- [kUpb_EncodedType_Int32 ] = kUpb_FieldType_Int32 ,
570- [kUpb_EncodedType_Fixed64 ] = kUpb_FieldType_Fixed64 ,
571- [kUpb_EncodedType_Fixed32 ] = kUpb_FieldType_Fixed32 ,
572- [kUpb_EncodedType_Bool ] = kUpb_FieldType_Bool ,
573- [kUpb_EncodedType_String ] = kUpb_FieldType_String ,
574- [kUpb_EncodedType_Group ] = kUpb_FieldType_Group ,
575- [kUpb_EncodedType_Message ] = kUpb_FieldType_Message ,
576- [kUpb_EncodedType_Bytes ] = kUpb_FieldType_Bytes ,
577- [kUpb_EncodedType_UInt32 ] = kUpb_FieldType_UInt32 ,
578- [kUpb_EncodedType_OpenEnum ] = kUpb_FieldType_Enum ,
579- [kUpb_EncodedType_SFixed32 ] = kUpb_FieldType_SFixed32 ,
580- [kUpb_EncodedType_SFixed64 ] = kUpb_FieldType_SFixed64 ,
581- [kUpb_EncodedType_SInt32 ] = kUpb_FieldType_SInt32 ,
582- [kUpb_EncodedType_SInt64 ] = kUpb_FieldType_SInt64 ,
583- [kUpb_EncodedType_ClosedEnum ] = kUpb_FieldType_Enum ,
584- };
585-
586604 char pointer_rep = d -> platform == kUpb_MiniTablePlatform_32Bit
587605 ? kUpb_FieldRep_4Byte
588606 : kUpb_FieldRep_8Byte ;
@@ -1019,6 +1037,79 @@ static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
10191037 d -> table -> size = UPB_ALIGN_UP (d -> table -> size , 8 );
10201038}
10211039
1040+ static void upb_MiniTable_BuildMapEntry (upb_MtDecoder * d ,
1041+ upb_FieldType key_type ,
1042+ upb_FieldType value_type ,
1043+ bool value_is_proto3_enum ) {
1044+ upb_MiniTable_Field * fields = upb_Arena_Malloc (d -> arena , sizeof (* fields ) * 2 );
1045+ if (!fields ) {
1046+ upb_MtDecoder_ErrorFormat (d , "OOM while building map mini table field" );
1047+ UPB_UNREACHABLE ();
1048+ }
1049+
1050+ upb_MiniTable_Sub * subs = NULL ;
1051+ if (value_is_proto3_enum ) {
1052+ UPB_ASSERT (value_type == kUpb_FieldType_Enum );
1053+ // No sub needed.
1054+ } else if (value_type == kUpb_FieldType_Message ||
1055+ value_type == kUpb_FieldType_Group ||
1056+ value_type == kUpb_FieldType_Enum ) {
1057+ subs = upb_Arena_Malloc (d -> arena , sizeof (* subs ));
1058+ if (!subs ) {
1059+ upb_MtDecoder_ErrorFormat (d , "OOM while building map mini table sub" );
1060+ UPB_UNREACHABLE ();
1061+ }
1062+ }
1063+
1064+ size_t field_size =
1065+ upb_MtDecoder_SizeOfRep (kUpb_FieldRep_StringView , d -> platform );
1066+
1067+ fields [0 ].number = 1 ;
1068+ fields [1 ].number = 2 ;
1069+ fields [0 ].mode = kUpb_FieldMode_Scalar ;
1070+ fields [1 ].mode = kUpb_FieldMode_Scalar ;
1071+ fields [0 ].presence = 0 ;
1072+ fields [1 ].presence = 0 ;
1073+ fields [0 ].offset = 0 ;
1074+ fields [1 ].offset = field_size ;
1075+
1076+ upb_MiniTable_SetTypeAndSub (& fields [0 ], key_type , NULL , 0 , false);
1077+ upb_MiniTable_SetTypeAndSub (& fields [1 ], value_type , NULL , 0 ,
1078+ value_is_proto3_enum );
1079+
1080+ upb_MiniTable * ret = d -> table ;
1081+ ret -> size = UPB_ALIGN_UP (2 * field_size , 8 );
1082+ ret -> field_count = 2 ;
1083+ ret -> ext = kUpb_ExtMode_NonExtendable | kUpb_ExtMode_IsMapEntry ;
1084+ ret -> dense_below = 2 ;
1085+ ret -> table_mask = -1 ;
1086+ ret -> required_count = 0 ;
1087+ ret -> subs = subs ;
1088+ ret -> fields = fields ;
1089+ }
1090+
1091+ static void upb_MtDecoder_ParseMap (upb_MtDecoder * d , const char * data ,
1092+ size_t len ) {
1093+ if (len < 2 ) {
1094+ upb_MtDecoder_ErrorFormat (d , "Invalid map encoding length: %zu" , len );
1095+ UPB_UNREACHABLE ();
1096+ }
1097+ const int e0 = upb_FromBase92 (data [0 ]);
1098+ const int e1 = upb_FromBase92 (data [1 ]);
1099+ if (e0 >= sizeof (kUpb_EncodedToType )) {
1100+ upb_MtDecoder_ErrorFormat (d , "Invalid field type: %d" , e0 );
1101+ UPB_UNREACHABLE ();
1102+ }
1103+ if (e1 >= sizeof (kUpb_EncodedToType )) {
1104+ upb_MtDecoder_ErrorFormat (d , "Invalid field type: %d" , e1 );
1105+ UPB_UNREACHABLE ();
1106+ }
1107+ const upb_FieldType key_type = kUpb_EncodedToType [e0 ];
1108+ const upb_FieldType val_type = kUpb_EncodedToType [e1 ];
1109+ const bool value_is_proto3_enum = (e1 == kUpb_EncodedType_OpenEnum );
1110+ upb_MiniTable_BuildMapEntry (d , key_type , val_type , value_is_proto3_enum );
1111+ }
1112+
10221113upb_MiniTable * upb_MiniTable_BuildWithBuf (const char * data , size_t len ,
10231114 upb_MiniTablePlatform platform ,
10241115 upb_Arena * arena , void * * buf ,
@@ -1042,16 +1133,6 @@ upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
10421133 goto done ;
10431134 }
10441135
1045- // If the string is non-empty then it must begin with a version tag.
1046- if (len ) {
1047- if (* data != kUpb_EncodedVersion_MessageV1 ) {
1048- upb_MtDecoder_ErrorFormat (& decoder , "Invalid message version: %c" , * data );
1049- UPB_UNREACHABLE ();
1050- }
1051- data ++ ;
1052- len -- ;
1053- }
1054-
10551136 upb_MtDecoder_CheckOutOfMemory (& decoder , decoder .table );
10561137
10571138 decoder .table -> size = 0 ;
@@ -1061,10 +1142,26 @@ upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
10611142 decoder .table -> table_mask = -1 ;
10621143 decoder .table -> required_count = 0 ;
10631144
1064- upb_MtDecoder_ParseMessage (& decoder , data , len );
1065- upb_MtDecoder_AssignHasbits (decoder .table );
1066- upb_MtDecoder_SortLayoutItems (& decoder );
1067- upb_MtDecoder_AssignOffsets (& decoder );
1145+ // Strip off and verify the version tag.
1146+ if (!len -- ) goto done ;
1147+ const char vers = * data ++ ;
1148+
1149+ switch (vers ) {
1150+ case kUpb_EncodedVersion_MapV1 :
1151+ upb_MtDecoder_ParseMap (& decoder , data , len );
1152+ break ;
1153+
1154+ case kUpb_EncodedVersion_MessageV1 :
1155+ upb_MtDecoder_ParseMessage (& decoder , data , len );
1156+ upb_MtDecoder_AssignHasbits (decoder .table );
1157+ upb_MtDecoder_SortLayoutItems (& decoder );
1158+ upb_MtDecoder_AssignOffsets (& decoder );
1159+ break ;
1160+
1161+ default :
1162+ upb_MtDecoder_ErrorFormat (& decoder , "Invalid message version: %c" , vers );
1163+ UPB_UNREACHABLE ();
1164+ }
10681165
10691166done :
10701167 * buf = decoder .vec .data ;
@@ -1086,53 +1183,6 @@ upb_MiniTable* upb_MiniTable_BuildMessageSet(upb_MiniTablePlatform platform,
10861183 return ret ;
10871184}
10881185
1089- upb_MiniTable * upb_MiniTable_BuildMapEntry (upb_FieldType key_type ,
1090- upb_FieldType value_type ,
1091- bool value_is_proto3_enum ,
1092- upb_MiniTablePlatform platform ,
1093- upb_Arena * arena ) {
1094- upb_MiniTable * ret = upb_Arena_Malloc (arena , sizeof (* ret ));
1095- upb_MiniTable_Field * fields = upb_Arena_Malloc (arena , sizeof (* fields ) * 2 );
1096- if (!ret || !fields ) return NULL ;
1097-
1098- upb_MiniTable_Sub * subs = NULL ;
1099- if (value_is_proto3_enum ) {
1100- UPB_ASSERT (value_type == kUpb_FieldType_Enum );
1101- // No sub needed.
1102- } else if (value_type == kUpb_FieldType_Message ||
1103- value_type == kUpb_FieldType_Group ||
1104- value_type == kUpb_FieldType_Enum ) {
1105- subs = upb_Arena_Malloc (arena , sizeof (* subs ));
1106- if (!subs ) return NULL ;
1107- }
1108-
1109- size_t field_size =
1110- upb_MtDecoder_SizeOfRep (kUpb_FieldRep_StringView , platform );
1111-
1112- fields [0 ].number = 1 ;
1113- fields [1 ].number = 2 ;
1114- fields [0 ].mode = kUpb_FieldMode_Scalar ;
1115- fields [1 ].mode = kUpb_FieldMode_Scalar ;
1116- fields [0 ].presence = 0 ;
1117- fields [1 ].presence = 0 ;
1118- fields [0 ].offset = 0 ;
1119- fields [1 ].offset = field_size ;
1120-
1121- upb_MiniTable_SetTypeAndSub (& fields [0 ], key_type , NULL , 0 , false);
1122- upb_MiniTable_SetTypeAndSub (& fields [1 ], value_type , NULL , 0 ,
1123- value_is_proto3_enum );
1124-
1125- ret -> size = UPB_ALIGN_UP (2 * field_size , 8 );
1126- ret -> field_count = 2 ;
1127- ret -> ext = kUpb_ExtMode_NonExtendable | kUpb_ExtMode_IsMapEntry ;
1128- ret -> dense_below = 2 ;
1129- ret -> table_mask = -1 ;
1130- ret -> required_count = 0 ;
1131- ret -> subs = subs ;
1132- ret -> fields = fields ;
1133- return ret ;
1134- }
1135-
11361186static size_t upb_MiniTable_EnumSize (size_t count ) {
11371187 return sizeof (upb_MiniTable_Enum ) + count * sizeof (uint32_t );
11381188}
0 commit comments