1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Google LLC nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
29 #define UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
30 
31 #include "upb/base/string_view.h"
32 #include "upb/hash/common.h"
33 #include "upb/mini_table/types.h"
34 
35 // Must be last.
36 #include "upb/port/def.inc"
37 
38 struct upb_Decoder;
39 typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
40                                      upb_Message* msg, intptr_t table,
41                                      uint64_t hasbits, uint64_t data);
42 typedef struct {
43   uint64_t field_data;
44   _upb_FieldParser* field_parser;
45 } _upb_FastTable_Entry;
46 
47 typedef enum {
48   kUpb_ExtMode_NonExtendable = 0,  // Non-extendable message.
49   kUpb_ExtMode_Extendable = 1,     // Normal extendable message.
50   kUpb_ExtMode_IsMessageSet = 2,   // MessageSet message.
51   kUpb_ExtMode_IsMessageSet_ITEM =
52       3,  // MessageSet item (temporary only, see decode.c)
53 
54   // During table building we steal a bit to indicate that the message is a map
55   // entry.  *Only* used during table building!
56   kUpb_ExtMode_IsMapEntry = 4,
57 } upb_ExtMode;
58 
59 // LINT.IfChange(mini_table_layout)
60 
61 // upb_MiniTable represents the memory layout of a given upb_MessageDef.
62 // The members are public so generated code can initialize them,
63 // but users MUST NOT directly read or write any of its members.
64 struct upb_MiniTable {
65   const upb_MiniTableSub* subs;
66   const upb_MiniTableField* fields;
67 
68   // Must be aligned to sizeof(void*). Doesn't include internal members like
69   // unknown fields, extension dict, pointer to msglayout, etc.
70   uint16_t size;
71 
72   uint16_t field_count;
73   uint8_t ext;  // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1
74   uint8_t dense_below;
75   uint8_t table_mask;
76   uint8_t required_count;  // Required fields have the lowest hasbits.
77 
78   // To statically initialize the tables of variable length, we need a flexible
79   // array member, and we need to compile in gnu99 mode (constant initialization
80   // of flexible array members is a GNU extension, not in C99 unfortunately.
81   _upb_FastTable_Entry fasttable[];
82 };
83 
84 // LINT.ThenChange(//depot/google3/third_party/upb/js/impl/upb_bits/mini_table.ts:presence_logic)
85 
86 // Map entries aren't actually stored for map fields, they are only used during
87 // parsing. For parsing, it helps a lot if all map entry messages have the same
88 // layout. The layout code in mini_table/decode.c will ensure that all map
89 // entries have this layout.
90 //
91 // Note that users can and do create map entries directly, which will also use
92 // this layout.
93 //
94 // NOTE: sync with mini_table/decode.c.
95 typedef struct {
96   // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here,
97   // and the uint64_t helps make this clear.
98   uint64_t hasbits;
99   union {
100     upb_StringView str;  // For str/bytes.
101     upb_value val;       // For all other types.
102   } k;
103   union {
104     upb_StringView str;  // For str/bytes.
105     upb_value val;       // For all other types.
106   } v;
107 } upb_MapEntryData;
108 
109 typedef struct {
110   void* internal_data;
111   upb_MapEntryData data;
112 } upb_MapEntry;
113 
114 #ifdef __cplusplus
115 extern "C" {
116 #endif
117 
118 // Computes a bitmask in which the |l->required_count| lowest bits are set,
119 // except that we skip the lowest bit (because upb never uses hasbit 0).
120 //
121 // Sample output:
122 //    requiredmask(1) => 0b10 (0x2)
123 //    requiredmask(5) => 0b111110 (0x3e)
upb_MiniTable_requiredmask(const upb_MiniTable * l)124 UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
125   int n = l->required_count;
126   assert(0 < n && n <= 63);
127   return ((1ULL << n) - 1) << 1;
128 }
129 
130 #ifdef __cplusplus
131 } /* extern "C" */
132 #endif
133 
134 #include "upb/port/undef.inc"
135 
136 #endif /* UPB_MINI_TABLE_MESSAGE_INTERNAL_H_ */
137