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