github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/native/thrift.h (about) 1 /* 2 * Copyright 2023 CloudWeGo Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "native.h" 18 #include "map.h" 19 20 #ifndef THRIFT_H 21 #define THRIFT_H 22 23 #define F_ALLOW_UNKNOWN 1ull 24 #define F_WRITE_DEFAULT (1ull << 1) 25 #define F_ENABLE_VM (1ull << 2) 26 #define F_ENABLE_HM (1ull << 3) 27 #define F_ENABLE_I2S (1ull << 4) 28 #define F_WRITE_REQUIRE (1ull << 5) 29 #define F_NO_BASE64 (1ull << 6) 30 #define F_WRITE_OPTIONAL (1ull << 7) 31 #define F_TRACE_BACK (1ull << 8) 32 33 #define THRIFT_VERSION_MASK 0xffff0000ul 34 #define THRIFT_VERSION_1 0x80010000ul 35 36 typedef int32_t tmsg; 37 38 #define TMESSAGE_TYPE_INVALID 0 39 #define TMESSAGE_TYPE_CALL 1 40 #define TMESSAGE_TYPE_REPLY 2 41 #define TMESSAGE_TYPE_EXCEPTION 3 42 #define TMESSAGE_TYPE_ONEWAY 4 43 44 typedef uint8_t ttype; 45 46 #define TTYPE_STOP (ttype)0 47 #define TTYPE_VOID (ttype)1 48 #define TTYPE_BOOL (ttype)2 49 #define TTYPE_BYTE (ttype)3 50 #define TTYPE_I08 (ttype)3 51 #define TTYPE_DOUBLE (ttype)4 52 #define TTYPE_I16 (ttype)6 53 #define TTYPE_I32 (ttype)8 54 #define TTYPE_I64 (ttype)10 55 #define TTYPE_STRING (ttype)11 56 #define TTYPE_UTF7 (ttype)11 57 #define TTYPE_STRUCT (ttype)12 58 #define TTYPE_MAP (ttype)13 59 #define TTYPE_SET (ttype)14 60 #define TTYPE_LIST (ttype)15 61 #define TTYPE_UTF8 (ttype)16 62 #define TTYPE_UTF16 (ttype)17 63 64 typedef uint16_t vm_em; 65 #define VM_NONE 0 66 #define VM_JSCONV 101 // NOTICE: must be same with internal/native/types.VM_JSCONV 67 #define VM_INLINE_MAX 255 68 69 typedef struct tTypeDesc tTypeDesc; 70 71 typedef struct tFieldDesc tFieldDesc; 72 73 typedef struct 74 { 75 tFieldDesc **buf; 76 size_t len; 77 size_t cap; 78 tFieldDesc **buf_all; 79 size_t len_all; 80 size_t cap_all; 81 } FieldIdMap; 82 83 typedef struct 84 { 85 size_t max_key_len; 86 GoSlice all; 87 TrieTree *trie; 88 HashMap *hash; 89 } tFieldNameMap; 90 91 typedef struct 92 { 93 GoEface go_val; 94 GoString json_val; 95 GoString thrift_binary; 96 } tDefaultValue; 97 98 struct tFieldDesc 99 { 100 bool is_request_base; 101 bool is_response_base; 102 req_em required; 103 vm_em vm; 104 tid ID; 105 tTypeDesc *type; 106 tDefaultValue *default_value; 107 GoString name; 108 GoString alias; 109 GoIface value_mappings; 110 GoSlice http_mappings; 111 GoSlice annotations; 112 }; 113 114 typedef struct 115 { 116 tid base_id; 117 GoString name; 118 FieldIdMap ids; 119 tFieldNameMap names; 120 121 // WARN: Here is a `GoSlice*` pointer actually (allocated 3 QUAD memory from golang) 122 // while we use `ReqBitMap*` pointer (2 QUAD memory) for purpose of conformity to J2TState.ex.es.reqs, 123 // It won't affect the calculating results AS LONG AS IT IS STATICALLY USED. 124 ReqBitMap reqs; 125 GoSlice hms; 126 GoSlice annotations; 127 } tStructDesc; 128 129 struct tTypeDesc 130 { 131 ttype type; 132 GoString name; 133 tTypeDesc *key; 134 tTypeDesc *elem; 135 tStructDesc *st; 136 }; 137 138 typedef struct 139 { 140 size_t bp; 141 size_t size; 142 } J2TExtra_Cont; 143 144 typedef struct 145 { 146 const tStructDesc *sd; 147 ReqBitMap reqs; 148 } J2TExtra_Struct; 149 150 typedef struct 151 { 152 bool skip; 153 tFieldDesc *f; 154 } J2TExtra_Field; 155 156 typedef union 157 { 158 J2TExtra_Cont ec; 159 J2TExtra_Struct es; 160 J2TExtra_Field ef; 161 } J2TExtra; 162 163 typedef struct 164 { 165 size_t st; 166 size_t jp; 167 const tTypeDesc *td; 168 J2TExtra ex; 169 } J2TState; 170 171 typedef struct 172 { 173 int32_t *buf; 174 size_t len; 175 size_t cap; 176 } Int32Slice; 177 178 typedef struct 179 { 180 int32_t id; 181 uint32_t start; 182 uint32_t end; 183 } FieldVal; 184 185 typedef struct 186 { 187 size_t sp; 188 JsonState jt; 189 GoSlice reqs_cache; 190 GoSlice key_cache; 191 J2TState vt[MAX_RECURSE]; 192 StateMachine sm; 193 Int32Slice field_cache; 194 FieldVal fval_cache; 195 } J2TStateMachine; 196 197 #define SIZE_J2TEXTRA sizeof(J2TExtra) 198 199 uint64_t tb_write_i64(GoSlice *buf, int64_t v); 200 201 uint64_t j2t_fsm_exec(J2TStateMachine *self, GoSlice *buf, const GoString *src, uint64_t flag); 202 203 #define J2T_VAL 0 204 #define J2T_ARR 1 205 #define J2T_OBJ 2 206 #define J2T_KEY 3 207 #define J2T_ELEM 4 208 #define J2T_ARR_0 5 209 #define J2T_OBJ_0 6 210 #define J2T_VM 16 211 212 #define J2T_ST(st) ((st)&0xfffful) 213 #define J2T_EX(st) ((st)&0xffff0000ul) 214 215 #define STATE_FIELD (1ull << 16) 216 #define STATE_SKIP (1ull << 17) 217 #define STATE_VM (1ull << 18) 218 #define IS_STATE_FIELD(st) (st & STATE_FIELD) != 0 219 #define IS_STATE_SKIP(st) (st & STATE_SKIP) != 0 220 #define IS_STATE_VM(st) (st & STATE_VM) != 0 221 222 #define ERR_WRAP_SHIFT_CODE 8 223 #define ERR_WRAP_SHIFT_POS 32 224 225 #define WRAP_ERR_POS(e, v, p) \ 226 do \ 227 { \ 228 xprintf("[ERROR_%d]: %d\n", e, v); \ 229 return (((uint64_t)(v) << (ERR_WRAP_SHIFT_CODE + ERR_WRAP_SHIFT_POS)) | (((uint64_t)(p) << ERR_WRAP_SHIFT_CODE) | (uint8_t)(e))); \ 230 } while (0) 231 232 #define WRAP_ERR(e, v) WRAP_ERR_POS(e, v, *p) 233 234 #define WRAP_ERR2(e, vh, vl) WRAP_ERR(e, ((uint32_t)(vh) << ERR_WRAP_SHIFT_CODE | (uint8_t)(vl))) 235 236 #define WRAP_ERR0(e, v) \ 237 do \ 238 { \ 239 xprintf("[ERROR_%d]: %d\n", e, v); \ 240 return (((uint64_t)(v) << (ERR_WRAP_SHIFT_CODE)) | (uint8_t)(e)); \ 241 } while (0) 242 243 #define J2T_EXP(e, v) \ 244 if unlikely (e != v) \ 245 { \ 246 WRAP_ERR2(ERR_DISMATCH_TYPE, v, e); \ 247 } 248 249 #define J2T_EXP2(e1, e2, v) \ 250 if unlikely (e1 != v && e2 != v) \ 251 { \ 252 WRAP_ERR(ERR_DISMATCH_TYPE2, ((uint32_t)(v) << (ERR_WRAP_SHIFT_CODE + ERR_WRAP_SHIFT_CODE) | ((uint16_t)(e2) << ERR_WRAP_SHIFT_CODE) | (uint8_t)(e1))); \ 253 } 254 255 #define J2T_ZERO(e) \ 256 do \ 257 { \ 258 uint64_t re = e; \ 259 if unlikely (re != 0) \ 260 { \ 261 return re; \ 262 } \ 263 } while (0) 264 265 #define J2T_DROP(v) (v)->sp-- 266 267 #define J2T_CHAR(c, s) \ 268 do \ 269 { \ 270 if unlikely (ch != (c)) \ 271 WRAP_ERR2(ERR_INVAL, c, s); \ 272 } while (0) 273 274 #define J2T_XERR(v, s) \ 275 do \ 276 { \ 277 int64_t r = (int64_t)(v); \ 278 if unlikely (r < 0) \ 279 WRAP_ERR(-r, s); \ 280 } while (0) 281 282 #define J2T_INIT(self, v) \ 283 self->sp = 1; \ 284 self->vt[0] = v; 285 286 #define J2T_REPL(self, a, b, c) \ 287 do \ 288 { \ 289 J2TState *xp = &self->vt[self->sp - 1]; \ 290 xp->st = a; \ 291 xp->jp = b; \ 292 xp->td = c; \ 293 DEBUG_PRINT_STATE(1, self->sp - 1, *p); \ 294 } while (0) 295 296 #define J2T_REPL_EX(self, a, b, c, d) \ 297 do \ 298 { \ 299 J2TState *xp = &self->vt[self->sp - 1]; \ 300 xp->st = a; \ 301 xp->jp = b; \ 302 xp->td = c; \ 303 xp->ex = d; \ 304 DEBUG_PRINT_STATE_EX(2, self->sp - 1, *p); \ 305 } while (0) 306 307 #define J2T_PUSH(self, a, b, c) \ 308 if unlikely (self->sp >= MAX_RECURSE) \ 309 { \ 310 WRAP_ERR(ERR_RECURSE_MAX, self->sp); \ 311 } \ 312 else \ 313 { \ 314 J2TState *xp = &self->vt[self->sp++]; \ 315 xp->st = a; \ 316 xp->jp = b; \ 317 xp->td = c; \ 318 } \ 319 DEBUG_PRINT_STATE(3, self->sp - 1, *p); 320 321 #define J2T_PUSH_EX(self, a, b, c, d) \ 322 if unlikely (self->sp >= MAX_RECURSE) \ 323 { \ 324 WRAP_ERR(ERR_RECURSE_MAX, self->sp); \ 325 } \ 326 else \ 327 { \ 328 J2TState *xp = &self->vt[self->sp++]; \ 329 xp->st = a; \ 330 xp->jp = b; \ 331 xp->td = c; \ 332 xp->ex = d; \ 333 } \ 334 DEBUG_PRINT_STATE_EX(4, self->sp - 1, *p); 335 336 #define J2T_STORE(f) \ 337 do \ 338 { \ 339 uint64_t ret = f; \ 340 if unlikely (ret != 0) \ 341 { \ 342 self->vt[self->sp - 1] = bt; \ 343 buf->len = wp; \ 344 DEBUG_PRINT_STATE(5, self->sp - 1, *p) \ 345 return ret; \ 346 } \ 347 } while (0) 348 349 #define J2T_STORE_NEXT(f) \ 350 do \ 351 { \ 352 uint64_t ret = f; \ 353 if unlikely (ret != 0) \ 354 { \ 355 self->vt[self->sp++] = bt; \ 356 buf->len = wp; \ 357 DEBUG_PRINT_STATE(6, self->sp - 1, *p) \ 358 return ret; \ 359 } \ 360 } while (0) 361 362 #define DEBUG_PRINT_STATE(i, sp, p) \ 363 xprintf("[DEBUG_PRINT_STATE_%d] STATE{sp:%d, st:%d, jp:%d, td:%s} POS:%d CHAR:%c BUF{\n\tbuf:%l,\n\tlen:%d, cap:%d}\n", i, sp, vt->st, vt->jp, vt->td == NULL ? &(GoString){} : &vt->td->name, p, ch, buf, buf->len, buf->cap); 364 365 #define DEBUG_PRINT_STATE_EX(i, sp, p) \ 366 xprintf("[DEBUG_PRINT_STATE_EX_%d] STATE{sp:%d, st:%d, jp:%d, td:%s, ex:[%d,%d,%d]} POS:%d CHAR:%c BUF{\n\tbuf:%l,\n\tlen:%d, cap:%d}\n", i, sp, vt->st, vt->jp, vt->td == NULL ? &(GoString){} : &vt->td->name, *(uint64_t *)(&vt->ex), *((uint64_t *)(&vt->ex) + 1), *((uint64_t *)(&vt->ex) + 2), p, ch, buf, buf->len, buf->cap); 367 368 #endif // THRIFT_H