github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/native/thrift.c (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  #include "scanning.h"
    20  #include "memops.h"
    21  #include "thrift.h"
    22  #include <stdint.h>
    23  #include "test/xprintf.h"
    24  
    25  uint64_t buf_malloc(GoSlice *buf, size_t size)
    26  {
    27      if (size == 0)
    28      {
    29          return 0;
    30      }
    31      size_t d = buf->len + size;
    32      if (d > buf->cap)
    33      {
    34          WRAP_ERR0(ERR_OOM_BUF, d - buf->cap);
    35      }
    36      buf->len = d;
    37      return 0;
    38  }
    39  
    40  uint64_t tb_write_byte(GoSlice *buf, char v)
    41  {
    42      size_t s = buf->len;
    43      J2T_ZERO(buf_malloc(buf, 1));
    44      buf->buf[s] = v;
    45      return 0;
    46  }
    47  
    48  uint64_t tb_write_bool(GoSlice *buf, bool v)
    49  {
    50      if (v)
    51      {
    52          return tb_write_byte(buf, 1);
    53      }
    54      return tb_write_byte(buf, 0);
    55  }
    56  
    57  uint64_t tb_write_i16(GoSlice *buf, int16_t v)
    58  {
    59      size_t s = buf->len;
    60      J2T_ZERO(buf_malloc(buf, 2));
    61      *(int16_t *)(&buf->buf[s]) = __builtin_bswap16(v);
    62      return 0;
    63  }
    64  
    65  uint64_t tb_write_i32(GoSlice *buf, int32_t v)
    66  {
    67      size_t s = buf->len;
    68      J2T_ZERO(buf_malloc(buf, 4));
    69      *(int32_t *)(&buf->buf[s]) = __builtin_bswap32(v);
    70      return 0;
    71  }
    72  
    73  uint64_t tb_write_i64(GoSlice *buf, int64_t v)
    74  {
    75      size_t s = buf->len;
    76      J2T_ZERO(buf_malloc(buf, 8));
    77      *(int64_t *)(&buf->buf[s]) = __builtin_bswap64(v);
    78      return 0;
    79  }
    80  
    81  uint64_t tb_write_double(GoSlice *buf, double v)
    82  {
    83      uint64_t f = *(uint64_t *)(&v);
    84      return tb_write_i64(buf, f);
    85  }
    86  
    87  uint64_t tb_write_string(GoSlice *buf, const char *v, size_t n)
    88  {
    89      size_t s = buf->len;
    90      J2T_ZERO(buf_malloc(buf, n + 4));
    91      *(int32_t *)(&buf->buf[s]) = __builtin_bswap32(n);
    92      xprintf("[tb_write_string] %c%c%c%c\n", buf->buf[s], buf->buf[s + 1], buf->buf[s + 2], buf->buf[s + 3]);
    93      memcpy2(&buf->buf[s + 4], v, n);
    94      return 0;
    95  }
    96  
    97  uint64_t tb_write_binary(GoSlice *buf, const GoSlice v)
    98  {
    99      size_t s = buf->len;
   100      J2T_ZERO(buf_malloc(buf, v.len + 4));
   101      *(int32_t *)(&buf->buf[s]) = __builtin_bswap32(v.len);
   102      memcpy2(&buf->buf[s + 4], v.buf, v.len);
   103      return 0;
   104  }
   105  
   106  void tb_write_struct_begin(GoSlice *buf)
   107  {
   108      return;
   109  }
   110  
   111  uint64_t tb_write_struct_end(GoSlice *buf)
   112  {
   113      J2T_ZERO(tb_write_byte(buf, TTYPE_STOP));
   114      xprintf("[tb_write_struct_end]:%c\n", buf->buf[buf->len - 1]);
   115      return 0;
   116  }
   117  
   118  uint64_t tb_write_field_begin(GoSlice *buf, ttype type, int16_t id)
   119  {
   120      J2T_ZERO(tb_write_byte(buf, type));
   121      return tb_write_i16(buf, id);
   122  }
   123  
   124  uint64_t tb_write_map_n(GoSlice *buf, ttype key, ttype val, int32_t n)
   125  {
   126      J2T_ZERO(tb_write_byte(buf, key));
   127      J2T_ZERO(tb_write_byte(buf, val));
   128      J2T_ZERO(tb_write_i32(buf, n));
   129      return 0;
   130  }
   131  
   132  uint64_t tb_write_map_begin(GoSlice *buf, ttype key, ttype val, size_t *back)
   133  {
   134      J2T_ZERO(tb_write_byte(buf, key));
   135      J2T_ZERO(tb_write_byte(buf, val));
   136      *back = buf->len;
   137      J2T_ZERO(buf_malloc(buf, 4));
   138  
   139      return 0;
   140  }
   141  
   142  void tb_write_map_end(GoSlice *buf, size_t back, size_t size)
   143  {
   144      xprintf("[tb_write_map_end]: %d, bp pos: %d\n", size, back);
   145      *(int32_t *)(&buf->buf[back]) = __builtin_bswap32(size);
   146      return;
   147  }
   148  
   149  uint64_t tb_write_list_begin(GoSlice *buf, ttype elem, size_t *back)
   150  {
   151      J2T_ZERO(tb_write_byte(buf, elem));
   152      *back = buf->len;
   153      J2T_ZERO(buf_malloc(buf, 4));
   154      return 0;
   155  }
   156  
   157  void tb_write_list_end(GoSlice *buf, size_t back, size_t size)
   158  {
   159      xprintf("[tb_write_list_end]: %d, bp pos: %d\n", size, back);
   160      *(int32_t *)(&buf->buf[back]) = __builtin_bswap32(size);
   161      return;
   162  }
   163  
   164  uint64_t tb_write_list_n(GoSlice *buf, ttype elem, int32_t size)
   165  {
   166      J2T_ZERO(tb_write_byte(buf, elem));
   167      J2T_ZERO(tb_write_i32(buf, size));
   168      return 0;
   169  }
   170  
   171  uint64_t tb_write_default_or_empty(GoSlice *buf, const tFieldDesc *field, long p)
   172  {
   173      if (field->default_value != NULL)
   174      {
   175          xprintf("[tb_write_default_or_empty] json_val: %s\n", &field->default_value->json_val);
   176          size_t n = field->default_value->thrift_binary.len;
   177          size_t l = buf->len;
   178          J2T_ZERO(buf_malloc(buf, n));
   179          memcpy2(&buf->buf[l], field->default_value->thrift_binary.buf, n);
   180          return 0;
   181      }
   182      tTypeDesc *desc = field->type;
   183      switch (desc->type)
   184      {
   185      case TTYPE_BOOL:
   186          return tb_write_bool(buf, false);
   187      case TTYPE_BYTE:
   188          return tb_write_byte(buf, 0);
   189      case TTYPE_I16:
   190          return tb_write_i16(buf, 0);
   191      case TTYPE_I32:
   192          return tb_write_i32(buf, 0);
   193      case TTYPE_I64:
   194          return tb_write_i64(buf, 0);
   195      case TTYPE_DOUBLE:
   196          return tb_write_double(buf, 0);
   197      case TTYPE_STRING:
   198          return tb_write_string(buf, NULL, 0);
   199      case TTYPE_LIST:
   200      case TTYPE_SET:
   201          J2T_ZERO(tb_write_list_n(buf, desc->elem->type, 0));
   202          return 0;
   203      case TTYPE_MAP:
   204          J2T_ZERO(tb_write_map_n(buf, desc->key->type, desc->elem->type, 0));
   205          return 0;
   206      case TTYPE_STRUCT:
   207          tb_write_struct_begin(buf);
   208          tFieldDesc **f = desc->st->ids.buf_all;
   209          size_t l = desc->st->ids.len_all;
   210          for (int i = 0; i < l; i++)
   211          {
   212              if (f[i]->required == REQ_OPTIONAL)
   213              {
   214                  continue;
   215              }
   216              J2T_ZERO(tb_write_field_begin(buf, f[i]->type->type, f[i]->ID));
   217              J2T_ZERO(tb_write_default_or_empty(buf, f[i], p));
   218          }
   219          J2T_ZERO(tb_write_struct_end(buf));
   220          return 0;
   221      default:
   222          WRAP_ERR_POS(ERR_UNSUPPORT_THRIFT_TYPE, desc->type, p);
   223      }
   224  }
   225  
   226  uint64_t tb_write_message_begin(GoSlice *buf, const GoString name, int32_t type, int32_t seq)
   227  {
   228      uint32_t version = THRIFT_VERSION_1 | (uint32_t)type;
   229      J2T_ZERO(tb_write_i32(buf, version));
   230      J2T_ZERO(tb_write_string(buf, name.buf, name.len));
   231      return tb_write_i32(buf, seq);
   232  }
   233  
   234  void tb_write_message_end(GoSlice *buf)
   235  {
   236      return;
   237  }
   238  
   239  uint64_t bm_malloc_reqs(GoSlice *cache, ReqBitMap src, ReqBitMap *copy, long p)
   240  {
   241      xprintf("[bm_malloc_reqs oom] malloc, cache.len:%d, cache.cap:%d, src.len:%d\n", cache->len, cache->cap, src.len);
   242      size_t n = src.len * SIZE_INT64;
   243      size_t d = cache->len + n;
   244      if unlikely (d > cache->cap)
   245      {
   246          xprintf("[bm_malloc_reqs] oom d:%d, cap:%d\n", d, cache->cap);
   247          WRAP_ERR0(ERR_OOM_BM, (d - cache->cap));
   248      }
   249  
   250      copy->buf = (uint64_t *)&cache->buf[cache->len];
   251      copy->len = src.len;
   252      memcpy2((char *)copy->buf, (char *)src.buf, n);
   253      cache->len = d;
   254      // xprintf("[bm_malloc_reqs] copy:%n, src:%n \n", copy, &src);
   255  
   256      return 0;
   257  }
   258  
   259  void bm_free_reqs(GoSlice *cache, size_t len)
   260  {
   261      xprintf("[bm_free_reqs] free, cache.len: %d, src.len:%d", cache->len, len);
   262      cache->len -= (len * SIZE_INT64);
   263  }
   264  
   265  uint64_t j2t_write_unset_fields(J2TStateMachine *self, GoSlice *buf, const tStructDesc *st, ReqBitMap reqs, uint64_t flags, long p)
   266  {
   267      bool wr_enabled = flags & F_WRITE_REQUIRE;
   268      bool wd_enabled = flags & F_WRITE_DEFAULT;
   269      bool wo_enabled = flags & F_WRITE_OPTIONAL;
   270      bool tb_enabled = flags & F_TRACE_BACK;
   271      uint64_t *s = reqs.buf;
   272      // xprintf("[j2t_write_unset_fields] reqs: %n \n", &reqs);
   273      for (int i = 0; i < reqs.len; i++)
   274      {
   275          uint64_t v = *s;
   276          for (int j = 0; v != 0 && j < BSIZE_INT64; j++)
   277          {
   278              if ((v % 2) != 0)
   279              {
   280                  tid id = i * BSIZE_INT64 + j;
   281                  if (id >= st->ids.len)
   282                  {
   283                      continue;
   284                  }
   285                  tFieldDesc *f = (st->ids.buf)[id];
   286                  // xprintf("[j2t_write_unset_fields] field:%d, f.name:%s\n", (int64_t)id, &f->name);
   287  
   288                  // NOTICE: if traceback is enabled AND (field is required OR current state is root layer),
   289                  // return field id to traceback field value from http-mapping in Go.
   290                  if (tb_enabled && (f->required == REQ_REQUIRED || self->sp == 1))
   291                  {
   292                      if (self->field_cache.cap <= self->field_cache.len)
   293                      {
   294                          WRAP_ERR0(ERR_OOM_FIELD, p);
   295                      }
   296                      self->field_cache.buf[self->field_cache.len++] = f->ID;
   297                  }
   298                  else if (!wr_enabled && f->required == REQ_REQUIRED)
   299                  {
   300                      WRAP_ERR_POS(ERR_NULL_REQUIRED, id, p);
   301                  }
   302                  else if ((wr_enabled && f->required == REQ_REQUIRED) || (wd_enabled && f->required == REQ_DEFAULT) || (wo_enabled && f->required == REQ_OPTIONAL))
   303                  {
   304                      J2T_ZERO(tb_write_field_begin(buf, f->type->type, f->ID));
   305                      J2T_ZERO(tb_write_default_or_empty(buf, f, p));
   306                  }
   307              }
   308              v >>= 1;
   309          }
   310          s++;
   311      }
   312      return 0;
   313  }
   314  
   315  uint64_t j2t_number(GoSlice *buf, const tTypeDesc *desc, const GoString *src, long *p, JsonState *ret)
   316  {
   317      long s = *p;
   318      vnumber(src, p, ret);
   319      xprintf("[j2t_number] p:%d, ret.vt:%d, ret.iv:%d, ret.dv:%f\n", s, ret->vt, ret->iv, ret->dv);
   320      if (ret->vt < 0)
   321      {
   322          WRAP_ERR(-ret->vt, s);
   323      }
   324      // FIXME: check double-integer overflow
   325      switch (desc->type)
   326      {
   327      case TTYPE_I08:
   328          if (ret->vt == V_INTEGER)
   329          {
   330              return tb_write_byte(buf, (uint8_t)ret->iv);
   331          }
   332          else
   333          {
   334              return tb_write_byte(buf, (uint8_t)ret->dv);
   335          }
   336      case TTYPE_I16:
   337          if (ret->vt == V_INTEGER)
   338          {
   339              return tb_write_i16(buf, (int16_t)ret->iv);
   340          }
   341          else
   342          {
   343              return tb_write_i16(buf, (int16_t)ret->dv);
   344          }
   345      case TTYPE_I32:
   346          if (ret->vt == V_INTEGER)
   347          {
   348              return tb_write_i32(buf, (int32_t)ret->iv);
   349          }
   350          else
   351          {
   352              return tb_write_i32(buf, (int32_t)ret->dv);
   353          }
   354      case TTYPE_I64:
   355          if (ret->vt == V_INTEGER)
   356          {
   357              return tb_write_i64(buf, (int64_t)ret->iv);
   358          }
   359          else
   360          {
   361              return tb_write_i64(buf, (int64_t)ret->dv);
   362          }
   363      case TTYPE_DOUBLE:
   364          // NOTICE: vnumber() has set dv when V_INTEGER
   365          return tb_write_double(buf, (double)(ret->dv));
   366      }
   367      WRAP_ERR2(ERR_DISMATCH_TYPE, desc->type, V_INTEGER);
   368  }
   369  
   370  uint64_t j2t_string(GoSlice *buf, const GoString *src, long *p, uint64_t flags)
   371  {
   372      long s = *p;
   373      int64_t ep;
   374      ssize_t e = advance_string(src, s, &ep);
   375      J2T_XERR(e, s);
   376      *p = e;
   377      size_t n = e - s - 1;
   378      xprintf("[j2t_string]s:%d, p:%d, ep:%d, n:%d\n", s, e, ep, n);
   379      if unlikely (ep >= s && ep < e)
   380      {
   381          char *sp = &buf->buf[buf->len];
   382          J2T_ZERO(buf_malloc(buf, 4));
   383          // unescape string
   384          size_t o = buf->len;
   385          ep = -1;
   386          J2T_ZERO(buf_malloc(buf, n));
   387          xprintf("[j2t_string] unquote o:%d, n:%d, ep:%d, flags:%d\n", o, n, ep, flags);
   388          ssize_t l = unquote(&src->buf[s], n, &buf->buf[o], &ep, flags);
   389          xprintf("[j2t_string] unquote end, l:%d\n", l);
   390          if (l < 0)
   391          {
   392              WRAP_ERR(-l, s);
   393          }
   394          buf->len = o + l;
   395          *(int32_t *)sp = __builtin_bswap32(l);
   396      }
   397      else
   398      {
   399          J2T_ZERO(tb_write_string(buf, &src->buf[s], n));
   400      }
   401      return 0;
   402  }
   403  
   404  uint64_t j2t_binary(GoSlice *buf, const GoString *src, long *p, uint64_t flags)
   405  {
   406      long s = *p;
   407      int64_t ep;
   408      ssize_t e = advance_string(src, s, &ep);
   409      J2T_XERR(e, s);
   410      *p = e;
   411      size_t n = e - s - 1;
   412      xprintf("[j2t_binary]s:%d, p:%d, ep:%d, n:%d\n", s, *p, ep, n);
   413      char *back = &buf->buf[buf->len];
   414      J2T_ZERO(buf_malloc(buf, 4));
   415      ssize_t l = b64decode(buf, &src->buf[s], n, 0);
   416      xprintf("[j2t_binary] base64 endm l:%d\n", l);
   417      if (l < 0)
   418      {
   419          WRAP_ERR(ERR_DECODE_BASE64, -l - 1);
   420      }
   421      *(int32_t *)(back) = __builtin_bswap32(l);
   422      return 0;
   423  }
   424  
   425  uint64_t j2t_map_key(GoSlice *buf, const char *sp, size_t n, const tTypeDesc *dc, JsonState *js, long p)
   426  {
   427      xprintf("[j2t_map_key]\n");
   428      switch (dc->type)
   429      {
   430      case TTYPE_STRING:
   431      {
   432          J2T_ZERO(tb_write_string(buf, sp, n));
   433          break;
   434      }
   435      case TTYPE_I08:
   436      case TTYPE_I16:
   437      case TTYPE_I32:
   438      case TTYPE_I64:
   439      case TTYPE_DOUBLE:
   440      {
   441          GoString tmp = (GoString){.buf = sp, .len = n};
   442          long p = 0;
   443          J2T_ZERO(j2t_number(buf, dc, &tmp, &p, js));
   444          break;
   445      }
   446      default:
   447          WRAP_ERR_POS(ERR_UNSUPPORT_THRIFT_TYPE, dc->type, p);
   448      }
   449      return 0;
   450  }
   451  
   452  tFieldDesc *j2t_find_field_key(const GoString *key, const tStructDesc *st)
   453  {
   454      xprintf("[j2t_find_field_key] key:%s\t", key);
   455      if unlikely (st->names.hash != NULL)
   456      {
   457          tFieldDesc *ret = (tFieldDesc *)hm_get(st->names.hash, key);
   458          xprintf("hash field:%x\n", ret);
   459          return ret;
   460      }
   461      else
   462      {
   463          tFieldDesc *ret = (tFieldDesc *)trie_get(st->names.trie, key);
   464          xprintf("trie field:%x\n", ret);
   465          return ret;
   466      }
   467  }
   468  
   469  uint64_t j2t_read_key(J2TStateMachine *self, const GoString *src, long *p, const char **spp, size_t *knp)
   470  {
   471      long s = *p;
   472      int64_t ep = -1;
   473      ssize_t e = advance_string(src, s, &ep);
   474      J2T_XERR(e, s);
   475      *p = e;
   476      size_t kn = e - s - 1;
   477      const char *sp = &src->buf[s];
   478      xprintf("[j2t_read_key] s:%d, e:%d, kn:%d, ep:%d\n", s, e, kn, ep);
   479      if unlikely (ep >= s && ep < e)
   480      {
   481          if unlikely (kn > self->key_cache.cap)
   482          {
   483              WRAP_ERR0(ERR_OOM_KEY, kn - self->key_cache.cap);
   484          }
   485          else
   486          {
   487              ep = -1;
   488              char *dp = self->key_cache.buf;
   489              ssize_t l = unquote(sp, kn, dp, &ep, 0);
   490              xprintf("[j2t_read_key] unquote end l:%d\n", l);
   491              if unlikely (l < 0)
   492              {
   493                  WRAP_ERR(-l, s);
   494              }
   495              sp = dp;
   496              kn = l;
   497          }
   498      }
   499      *spp = sp;
   500      *knp = kn;
   501      xprintf("[j2t_read_key]sp:%c, kn:%d\n", *sp, kn);
   502      return 0;
   503  }
   504  
   505  uint64_t j2t_field_vm(J2TStateMachine *self, GoSlice *buf, const GoString *src, long *p, J2TState *vt)
   506  {
   507      tFieldDesc *f = vt->ex.ef.f;
   508      xprintf("[j2t_field_vm] f->ID:%d, f->type->type:%d, p:%d \n", f->ID, f->type->type, *p);
   509      // if it is inlined value-mapping, write field tag first
   510      if (f->vm <= VM_INLINE_MAX)
   511      {
   512          J2T_ZERO(tb_write_field_begin(buf, f->type->type, f->ID));
   513          switch (f->vm)
   514          {
   515          case VM_JSCONV:
   516          {
   517              char ch = src->buf[*p - 1];
   518              if (ch == '"')
   519              {
   520                  // If the field is a string and value is also a string, we just handle it normally.
   521                  if (f->type->type == TTYPE_STRING)
   522                  {
   523                      J2T_ZERO(j2t_string(buf, src, p, 0));
   524                      return 0;
   525                  }
   526                  if (src->buf[*p] == '"')
   527                  {
   528                      // empty string
   529                      J2T_ZERO(tb_write_default_or_empty(buf, f, *p));
   530                      *p += 1;
   531                      return 0;
   532                  }
   533              }
   534              else
   535              {
   536                  // invalid number
   537                  if (ch != '-' && (ch < '0' || ch > '9'))
   538                  {
   539                      WRAP_ERR(ERR_INVAL, ch);
   540                  }
   541                  // back to begin of number
   542                  *p -= 1;
   543              }
   544  
   545              // handle it as number
   546              long s = *p;
   547              vnumber(src, p, &self->jt);
   548              if (self->jt.vt != V_INTEGER && self->jt.vt != V_DOUBLE)
   549              {
   550                  WRAP_ERR(ERR_NUMBER_FMT, self->jt.vt);
   551              }
   552              xprintf("[j2t_field_vm] jt.vt:%d, jt.iv:%d, jt.dv:%d\n", self->jt.vt, self->jt.iv, self->jt.dv);
   553              switch (f->type->type)
   554              {
   555              case TTYPE_STRING:
   556              {
   557                  J2T_ZERO(tb_write_string(buf, &src->buf[s], *p - s));
   558                  return 0;
   559              }
   560              case TTYPE_I64:
   561              {
   562                  int64_t v = 0;
   563                  if (self->jt.vt == V_INTEGER)
   564                  {
   565                      v = (int64_t)self->jt.iv;
   566                  }
   567                  else
   568                  {
   569                      v = (int64_t)self->jt.dv;
   570                  }
   571                  J2T_ZERO(tb_write_i64(buf, v));
   572                  break;
   573              }
   574              case TTYPE_I32:
   575              {
   576                  xprintf("[j2t_field_vm] TTYPE_I32\n");
   577                  int32_t v = 0;
   578                  if (self->jt.vt == V_INTEGER)
   579                  {
   580                      v = (int32_t)self->jt.iv;
   581                  }
   582                  else
   583                  {
   584                      v = (int32_t)self->jt.dv;
   585                  }
   586                  J2T_ZERO(tb_write_i32(buf, v));
   587                  break;
   588              }
   589              case TTYPE_I16:
   590              {
   591                  int16_t v = 0;
   592                  if (self->jt.vt == V_INTEGER)
   593                  {
   594                      v = (int16_t)self->jt.iv;
   595                  }
   596                  else
   597                  {
   598                      v = (int16_t)self->jt.dv;
   599                  }
   600                  J2T_ZERO(tb_write_i16(buf, v));
   601              }
   602              case TTYPE_I08:
   603              {
   604                  char v = 0;
   605                  if (self->jt.vt == V_INTEGER)
   606                  {
   607                      v = (char)self->jt.iv;
   608                  }
   609                  else
   610                  {
   611                      v = (char)self->jt.dv;
   612                  }
   613                  J2T_ZERO(tb_write_byte(buf, v));
   614                  break;
   615              }
   616              case TTYPE_DOUBLE:
   617              {
   618                  J2T_ZERO(tb_write_double(buf, (double)self->jt.dv));
   619                  break;
   620              }
   621              default:
   622                  WRAP_ERR(ERR_UNSUPPORT_THRIFT_TYPE, f->type->type);
   623              }
   624  
   625              // for int/float field and string value, we need to skip the quote.
   626              if (ch == '"')
   627              {
   628                  if (src->buf[*p] != '"')
   629                  {
   630                      WRAP_ERR(ERR_INVAL, src->buf[*p]);
   631                  }
   632                  *p += 1;
   633              }
   634              return 0;
   635          }
   636          default:
   637              WRAP_ERR(ERR_UNSUPPORT_VM_TYPE, f->vm);
   638          }
   639      }
   640      else
   641      {
   642          // non-inline implementation, need return to caller
   643          *p -= 1;
   644          long s = *p;
   645          self->sm.sp = 0;
   646          long r = skip_one(src, p, &self->sm);
   647          if (r < 0)
   648          {
   649              WRAP_ERR(-r, s);
   650          }
   651          // check if the fval_cache if full
   652          // if (self->fval_cache.len >= self->fval_cache.cap)
   653          // {
   654          //     WRAP_ERR0(ERR_OOM_FVAL, s);
   655          // }
   656          // self->fval_cache.len += 1;
   657          // FieldVal *fv = (FieldVal *)&self->fval_cache.buf[self->fval_cache.len - 1];
   658          // record field id and value (begin and end) into FSM.FieldValueCache
   659          FieldVal *fv = &self->fval_cache;
   660          fv->id = f->ID;
   661          fv->start = r;
   662          fv->end = *p;
   663          WRAP_ERR0(ERR_VM_END, *p);
   664      }
   665  }
   666  
   667  #define j2t_key(obj0)                                                                                                \
   668      do                                                                                                               \
   669      {                                                                                                                \
   670          const char *sp;                                                                                              \
   671          size_t kn;                                                                                                   \
   672          J2T_STORE(j2t_read_key(self, src, p, &sp, &kn));                                                             \
   673          if (dc->type == TTYPE_MAP)                                                                                   \
   674          {                                                                                                            \
   675              unwindPos = buf->len;                                                                                    \
   676              J2T_STORE(j2t_map_key(buf, sp, kn, dc->key, &self->jt, *p));                                             \
   677              if (obj0)                                                                                                \
   678              {                                                                                                        \
   679                  vt->ex.ec.size = 0;                                                                                  \
   680                  J2T_PUSH(self, J2T_ELEM, *p, dc->elem);                                                              \
   681              }                                                                                                        \
   682              else                                                                                                     \
   683              {                                                                                                        \
   684                  J2T_REPL(self, J2T_ELEM, *p, dc->elem);                                                              \
   685              }                                                                                                        \
   686          }                                                                                                            \
   687          else                                                                                                         \
   688          {                                                                                                            \
   689              J2TExtra *pex;                                                                                           \
   690              if (obj0)                                                                                                \
   691              {                                                                                                        \
   692                  pex = &vt->ex;                                                                                       \
   693              }                                                                                                        \
   694              else                                                                                                     \
   695              {                                                                                                        \
   696                  pex = &self->vt[self->sp - 2].ex;                                                                    \
   697              }                                                                                                        \
   698              GoString tmp_str = (GoString){.buf = sp, .len = kn};                                                     \
   699              tFieldDesc *f = j2t_find_field_key(&tmp_str, dc->st);                                                    \
   700              if (f == NULL)                                                                                           \
   701              {                                                                                                        \
   702                  xprintf("[J2T_KEY] unknown field %s\n", &tmp_str);                                                   \
   703                  if ((flag & F_ALLOW_UNKNOWN) == 0)                                                                   \
   704                  {                                                                                                    \
   705                      WRAP_ERR(ERR_UNKNOWN_FIELD, kn);                                                                 \
   706                  }                                                                                                    \
   707                  if (obj0)                                                                                            \
   708                  {                                                                                                    \
   709                      J2T_PUSH(self, J2T_ELEM | STATE_SKIP, *p, NULL);                                                 \
   710                  }                                                                                                    \
   711                  else                                                                                                 \
   712                  {                                                                                                    \
   713                      J2T_REPL(self, J2T_ELEM | STATE_SKIP, *p, NULL);                                                 \
   714                  }                                                                                                    \
   715              }                                                                                                        \
   716              else                                                                                                     \
   717              {                                                                                                        \
   718                  if unlikely ((flag & F_ENABLE_HM) && (f->http_mappings.len != 0) && !bm_is_set(pex->es.reqs, f->ID)) \
   719                  {                                                                                                    \
   720                      xprintf("[J2T_KEY] skip field %s\n", &tmp_str);                                                  \
   721                      if (obj0)                                                                                        \
   722                      {                                                                                                \
   723                          J2T_PUSH(self, J2T_ELEM | STATE_SKIP, *p, f->type);                                          \
   724                      }                                                                                                \
   725                      else                                                                                             \
   726                      {                                                                                                \
   727                          J2T_REPL(self, J2T_ELEM | STATE_SKIP, *p, f->type);                                          \
   728                      }                                                                                                \
   729                  }                                                                                                    \
   730                  else                                                                                                 \
   731                  {                                                                                                    \
   732                      J2TExtra ex = {};                                                                                \
   733                      ex.ef.f = f;                                                                                     \
   734                      uint64_t vm = STATE_VM;                                                                          \
   735                      if ((flag & F_ENABLE_VM) == 0 || f->vm == VM_NONE)                                               \
   736                      {                                                                                                \
   737                          vm = STATE_FIELD;                                                                            \
   738                          unwindPos = buf->len;                                                                        \
   739                          lastField = f;                                                                               \
   740                          J2T_STORE(tb_write_field_begin(buf, f->type->type, f->ID));                                  \
   741                      }                                                                                                \
   742                      xprintf("[J2T_KEY] vm: %d\n", vm);                                                               \
   743                      if (obj0)                                                                                        \
   744                      {                                                                                                \
   745                          J2T_PUSH_EX(self, J2T_ELEM | vm, *p, f->type, ex);                                           \
   746                      }                                                                                                \
   747                      else                                                                                             \
   748                      {                                                                                                \
   749                          J2T_REPL_EX(self, J2T_ELEM | vm, *p, f->type, ex);                                           \
   750                      }                                                                                                \
   751                  }                                                                                                    \
   752                  bm_set_req(pex->es.reqs, f->ID, REQ_OPTIONAL);                                                       \
   753              }                                                                                                        \
   754          }                                                                                                            \
   755      } while (0)
   756  
   757  uint64_t j2t_fsm_exec(J2TStateMachine *self, GoSlice *buf, const GoString *src, uint64_t flag)
   758  {
   759      if (self->sp <= 0)
   760      {
   761          return 0;
   762      }
   763      // load json position from last state
   764      long pv = self->vt[self->sp - 1].jp;
   765      long *p = &pv;
   766  
   767      // for 'null' value backtrace
   768      bool null_val = false;
   769      size_t unwindPos = 0;
   770      tFieldDesc *lastField = NULL;
   771  
   772      /* run until no more nested values */
   773      while (self->sp)
   774      {
   775          if unlikely (self->sp >= MAX_RECURSE)
   776          {
   777              WRAP_ERR(ERR_RECURSE_MAX, self->sp);
   778          }
   779          // load varialbes for current state
   780          J2TState *vt = &self->vt[self->sp - 1];
   781          J2TState bt = *vt;
   782          const tTypeDesc *dc = bt.td;
   783          uint64_t st = bt.st;
   784          size_t wp = buf->len;
   785  
   786          // advance to next char
   787          const char ch = advance_ns(src, p);
   788          DEBUG_PRINT_STATE(0, self->sp - 1, *p);
   789  
   790          /* check for special types */
   791          switch (J2T_ST(st))
   792          {
   793  
   794          default:
   795          {
   796              xprintf("[J2T_VAL] drop: %d\n", self->sp);
   797              J2T_DROP(self);
   798              break;
   799          }
   800  
   801          /* arrays, first element */
   802          case J2T_ARR_0:
   803          {
   804              xprintf("[J2T_ARR_0] 0\n");
   805              switch (ch)
   806              {
   807              case ']':
   808              {
   809                  xprintf("[J2T_ARR_0] end\n");
   810                  tb_write_list_end(buf, vt->ex.ec.bp, 0);
   811                  J2T_DROP(self);
   812                  continue;
   813              }
   814              default:
   815              {
   816                  xprintf("[J2T_ARR_0] start\n");
   817                  vt->ex.ec.size = 0;
   818                  // set parent state as J2T_ARR
   819                  vt->st = J2T_ARR;
   820                  *p -= 1;
   821                  J2T_PUSH(self, J2T_VAL, *p, dc->elem);
   822                  continue;
   823              }
   824              }
   825          }
   826  
   827          /* arrays */
   828          case J2T_ARR:
   829          {
   830              xprintf("[J2T_ARR] 0\n");
   831              switch (ch)
   832              {
   833              case ']':
   834              {
   835                  xprintf("[J2T_ARR] end\n");
   836                  if (!null_val)
   837                  {
   838                      // count last element
   839                      vt->ex.ec.size += 1;
   840                  }
   841                  else
   842                  {
   843                      // last element is null, so don't count it
   844                      null_val = false;
   845                  }
   846                  // since the encoding of list and set, we call only one type's func here.
   847                  // TODO: add thrift type choose for corresponding func
   848                  tb_write_list_end(buf, vt->ex.ec.bp, vt->ex.ec.size);
   849                  J2T_DROP(self);
   850                  continue;
   851              }
   852              case ',':
   853                  xprintf("[J2T_ARR] add\n");
   854                  if (!null_val)
   855                  {
   856                      vt->ex.ec.size += 1;
   857                  }
   858                  else
   859                  {
   860                      null_val = false;
   861                  }
   862                  J2T_PUSH_EX(self, J2T_VAL, *p, dc->elem, vt->ex);
   863                  continue;
   864              default:
   865                  WRAP_ERR2(ERR_INVAL, ch, J2T_ARR);
   866              }
   867          }
   868  
   869          /* objects, first pair */
   870          case J2T_OBJ_0:
   871          {
   872              xprintf("[J2T_OBJ_0] 0\n");
   873              switch (ch)
   874              {
   875              default:
   876              {
   877                  WRAP_ERR2(ERR_INVAL, ch, J2T_OBJ_0);
   878              }
   879  
   880              /* empty object */
   881              case '}':
   882              {
   883                  xprintf("[J2T_OBJ_0] end\n");
   884                  if (dc->type == TTYPE_STRUCT)
   885                  {
   886                      // check if all required/default fields got written
   887                      J2T_STORE(j2t_write_unset_fields(self, buf, vt->ex.es.sd, vt->ex.es.reqs, flag, *p - 1));
   888                      bm_free_reqs(&self->reqs_cache, vt->ex.es.reqs.len);
   889                      // http-mapping enalbed and some fields remain not written
   890                      if (flag & F_ENABLE_HM && self->field_cache.len > 0)
   891                      { // return back to go handler
   892                          xprintf("[J2T_OBJ_0] fallback http-mapping pos: %d\n", *p);
   893                          WRAP_ERR0(ERR_HM_END, *p);
   894                          // NOTICE: should tb_write_struct_end(), then J2T_DROP(self) in Go handler
   895                      }
   896                      else
   897                      {
   898                          J2T_STORE(tb_write_struct_end(buf));
   899                      }
   900                  }
   901                  else
   902                  {
   903                      tb_write_map_end(buf, vt->ex.ec.bp, 0);
   904                  }
   905                  J2T_DROP(self);
   906                  continue;
   907              }
   908  
   909              /* the quote of the first key */
   910              case '"':
   911              {
   912                  xprintf("[J2T_OBJ_0] start\n");
   913                  // set parent state
   914                  vt->st = J2T_OBJ;
   915                  j2t_key(true);
   916                  continue;
   917              }
   918              }
   919          }
   920  
   921          /* objects */
   922          case J2T_OBJ:
   923          {
   924              xprintf("[J2T_OBJ] 0\n");
   925              switch (ch)
   926              {
   927              case '}':
   928                  xprintf("[J2T_OBJ] end\n");
   929                  // update backtrace position, in case of OOM return
   930                  bt.jp = *p - 1;
   931                  if (dc->type == TTYPE_STRUCT)
   932                  {
   933                      // last field value is null, so must unwind written field header
   934                      if (null_val)
   935                      {
   936                          null_val = false;
   937                          bm_set_req(vt->ex.es.reqs, lastField->ID, lastField->required);
   938                          buf->len = unwindPos;
   939                      }
   940                      // check if all required/default fields got written
   941                      J2T_STORE(j2t_write_unset_fields(self, buf, vt->ex.es.sd, vt->ex.es.reqs, flag, *p - 1));
   942                      bm_free_reqs(&self->reqs_cache, vt->ex.es.reqs.len);
   943                      // http-mapping enalbed and some fields remain not written
   944                      if (flag & F_ENABLE_HM && self->field_cache.len != 0)
   945                      {
   946                          // return back to go handler
   947                          xprintf("[J2T_OBJ] fallback http-mapping pos: %d\n", *p);
   948                          WRAP_ERR0(ERR_HM_END, *p);
   949                          // NOTICE: should tb_write_struct_end(), then J2T_DROP(self) in Go handler
   950                      }
   951                      else
   952                      {
   953                          J2T_STORE(tb_write_struct_end(buf));
   954                      }
   955                  }
   956                  else
   957                  {
   958                      if (!null_val)
   959                      {
   960                          vt->ex.ec.size += 1;
   961                      }
   962                      else
   963                      {
   964                          // last element value is null, so must rewind to written key
   965                          null_val = false;
   966                          buf->len = unwindPos;
   967                      }
   968                      tb_write_map_end(buf, vt->ex.ec.bp, vt->ex.ec.size);
   969                  }
   970                  J2T_DROP(self);
   971                  continue;
   972              case ',':
   973                  xprintf("[J2T_OBJ] add\n");
   974                  if (dc->type == TTYPE_MAP)
   975                  {
   976                      if (!null_val)
   977                      {
   978                          vt->ex.ec.size += 1;
   979                      }
   980                      else
   981                      {
   982                          null_val = false;
   983                          buf->len = unwindPos;
   984                      }
   985                  }
   986                  else
   987                  {
   988                      if (null_val)
   989                      {
   990                          null_val = false;
   991                          bm_set_req(vt->ex.es.reqs, lastField->ID, lastField->required);
   992                          buf->len = unwindPos;
   993                      }
   994                  }
   995                  J2T_PUSH(self, J2T_KEY, *p, dc);
   996                  continue;
   997              default:
   998                  WRAP_ERR2(ERR_INVAL, ch, J2T_OBJ);
   999              }
  1000          }
  1001  
  1002              /* object keys */
  1003          case J2T_KEY:
  1004          {
  1005              xprintf("[J2T_KEY] 0\n");
  1006              J2T_CHAR('"', J2T_KEY);
  1007              j2t_key(false);
  1008              continue;
  1009          }
  1010  
  1011          /* object element */
  1012          case J2T_ELEM:
  1013          {
  1014              xprintf("[J2T_ELEM] 0\n");
  1015              J2T_CHAR(':', J2T_ELEM);
  1016              J2T_REPL(self, J2T_VAL | J2T_EX(st), *p, dc);
  1017              continue;
  1018          }
  1019          }
  1020          // skip
  1021          if unlikely (IS_STATE_SKIP(st))
  1022          {
  1023              xprintf("[J2T_VAL] skip: %d\n", *p);
  1024              *p -= 1;
  1025              long s = *p;
  1026              self->sm.sp = 0;
  1027              J2T_XERR(skip_one(src, p, &self->sm), s);
  1028              continue;
  1029          }
  1030          // value-mapping
  1031          if unlikely (flag & F_ENABLE_VM && IS_STATE_VM(st))
  1032          {
  1033              xprintf("[J2T_VAL] value mapping\n");
  1034              J2T_STORE_NEXT(j2t_field_vm(self, buf, src, p, vt));
  1035              continue;
  1036          }
  1037          // normal value
  1038          xprintf("[J2T_VAL] switch\n");
  1039          /* simple values */
  1040          switch (ch)
  1041          {
  1042          case '0': /* fallthrough */
  1043          case '1': /* fallthrough */
  1044          case '2': /* fallthrough */
  1045          case '3': /* fallthrough */
  1046          case '4': /* fallthrough */
  1047          case '5': /* fallthrough */
  1048          case '6': /* fallthrough */
  1049          case '7': /* fallthrough */
  1050          case '8': /* fallthrough */
  1051          case '9': /* fallthrough */
  1052          case '-':
  1053          {
  1054              xprintf("[J2T_VAL] number\n");
  1055              *p -= 1;
  1056              J2T_STORE_NEXT(j2t_number(buf, dc, src, p, &self->jt));
  1057              break;
  1058          }
  1059          case 'n':
  1060          {
  1061              xprintf("[J2T_VAL] null\n");
  1062              long s = *p;
  1063              J2T_XERR(advance_dword(src, p, 1, *p - 1, VS_NULL), s);
  1064              null_val = true;
  1065              break;
  1066          }
  1067          case 't':
  1068          {
  1069              xprintf("[J2T_VAL] true\n");
  1070              long s = *p;
  1071              J2T_XERR(advance_dword(src, p, 1, *p - 1, VS_TRUE), s);
  1072              J2T_EXP(TTYPE_BOOL, dc->type);
  1073              J2T_STORE_NEXT(tb_write_bool(buf, true));
  1074              break;
  1075          }
  1076          case 'f':
  1077          {
  1078              xprintf("[J2T_VAL] false\n");
  1079              long s = *p;
  1080              J2T_XERR(advance_dword(src, p, 0, *p - 1, VS_ALSE), s);
  1081              J2T_EXP(TTYPE_BOOL, dc->type);
  1082              J2T_STORE_NEXT(tb_write_bool(buf, false));
  1083              break;
  1084          }
  1085          case '[':
  1086          {
  1087              xprintf("[J2T_VAL] array\n");
  1088              J2T_EXP2(TTYPE_LIST, TTYPE_SET, dc->type);
  1089              J2TState *v = &self->vt[self->sp];
  1090              // TODO: since the encoding of list and set, we call only one type's func here.
  1091              // add thrift type choose for corresponding func
  1092              v->ex.ec.size = 0;
  1093              xprintf("[J2T_ARRAY]ex size: %d, vt: %d, vt.ex.ec: %d, vt.ex.ec.bp: %d, vt.ex.ec.size: %d\n", sizeof(J2TExtra), vt, &vt->ex.ec, &vt->ex.ec.bp, &vt->ex.ec.size);
  1094              J2T_STORE_NEXT(tb_write_list_begin(buf, dc->elem->type, &v->ex.ec.bp)); // pass write-back address bp to v.ex.ec.bp
  1095              J2T_PUSH_EX(self, J2T_ARR_0, *p, dc, v->ex);                            // pass bp to state
  1096              break;
  1097          }
  1098          case '{':
  1099          {
  1100              xprintf("[J2T_VAL] object\n");
  1101              J2T_EXP2(TTYPE_STRUCT, TTYPE_MAP, dc->type);
  1102              J2TState *v = &self->vt[self->sp];
  1103              if (dc->type == TTYPE_STRUCT)
  1104              {
  1105                  xprintf("[J2T_VAL] object struct name: %s\n", &dc->st->name);
  1106                  tb_write_struct_begin(buf);
  1107                  J2TExtra_Struct es = {.sd = dc->st};
  1108                  v->ex.es = es;
  1109                  J2T_PUSH(self, J2T_OBJ_0, *p, dc);
  1110                  J2T_STORE(bm_malloc_reqs(&self->reqs_cache, dc->st->reqs, &v->ex.es.reqs, *p));
  1111                  if ((flag & F_ENABLE_HM) != 0 && dc->st->hms.len > 0)
  1112                  {
  1113                      xprintf("[J2T_VAL] HTTP_MAPPING begin pos: %d\n", *p - 1);
  1114                      WRAP_ERR0(ERR_HM, *p - 1);
  1115                  }
  1116              }
  1117              else
  1118              {
  1119                  J2TExtra_Cont ec = {};
  1120                  v->ex.ec = ec;
  1121                  J2T_STORE_NEXT(tb_write_map_begin(buf, dc->key->type, dc->elem->type, &v->ex.ec.bp)); // pass write-back address bp to v.ex.ec.bp
  1122                  J2T_PUSH(self, J2T_OBJ_0, *p, dc);
  1123              }
  1124              break;
  1125          }
  1126          case '"':
  1127          {
  1128              xprintf("[J2T_VAL] string\n");
  1129              if (dc->type == TTYPE_STRING)
  1130              {
  1131                  if unlikely ((flag & F_NO_BASE64) == 0 && memeq(dc->name.buf, "binary", 6))
  1132                  {
  1133                      J2T_STORE_NEXT(j2t_binary(buf, src, p, 0));
  1134                  }
  1135                  else
  1136                  {
  1137                      J2T_STORE_NEXT(j2t_string(buf, src, p, 0));
  1138                  }
  1139              }
  1140              else if ((flag & F_ENABLE_I2S) != 0 && (dc->type == TTYPE_I64 || dc->type == TTYPE_I32 || dc->type == TTYPE_I16 || dc->type == TTYPE_BYTE || dc->type == TTYPE_DOUBLE))
  1141              {
  1142                  J2T_STORE_NEXT(j2t_number(buf, dc, src, p, &self->jt));
  1143                  long x = *p;
  1144                  if (x >= src->len)
  1145                  {
  1146                      WRAP_ERR(ERR_EOF, J2T_VAL);
  1147                  }
  1148                  // must end with a comma
  1149                  if (src->buf[x] != '"')
  1150                  {
  1151                      WRAP_ERR2(ERR_INVAL, src->buf[x], J2T_VAL);
  1152                  }
  1153                  *p += 1;
  1154              }
  1155              else
  1156              {
  1157                  WRAP_ERR2(ERR_DISMATCH_TYPE, dc->type, TTYPE_STRING);
  1158              }
  1159              break;
  1160          }
  1161          case 0:
  1162              WRAP_ERR(ERR_EOF, J2T_VAL);
  1163          default:
  1164              WRAP_ERR2(ERR_INVAL, ch, J2T_VAL);
  1165          }
  1166      }
  1167  
  1168      xprintf("[J2T] return\n");
  1169      /* all done */
  1170      return 0;
  1171  }