github.com/matrixorigin/matrixone@v1.2.0/pkg/container/bytejson/bytejson.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package bytejson
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/json"
    20  	"fmt"
    21  	"math"
    22  	"sort"
    23  	"strconv"
    24  	"strings"
    25  
    26  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    27  	"github.com/matrixorigin/matrixone/pkg/common/util"
    28  )
    29  
    30  func (bj ByteJson) String() string {
    31  	ret, _ := bj.MarshalJSON()
    32  	return string(ret)
    33  }
    34  
    35  func (bj ByteJson) Unquote() (string, error) {
    36  	if bj.Type != TpCodeString {
    37  		return bj.String(), nil
    38  	}
    39  	str := bj.GetString()
    40  	if len(str) < 2 || (str[0] != '"' || str[len(str)-1] != '"') {
    41  		return string(str), nil
    42  	}
    43  	str = str[1 : len(str)-1]
    44  	var sb strings.Builder
    45  	for i := 0; i < len(str); i++ {
    46  		if str[i] != '\\' {
    47  			sb.WriteByte(str[i])
    48  			continue
    49  		}
    50  		i++
    51  		if trans, ok := escapedChars[str[i]]; ok {
    52  			sb.WriteByte(trans)
    53  			continue
    54  		}
    55  		if str[i] == 'u' { // transform unicode to utf8
    56  			if i+4 > len(str) {
    57  				return "", moerr.NewInvalidInputNoCtx("invalid unicode")
    58  			}
    59  			unicodeStr := string(str[i-1 : i+5])
    60  			content := strings.Replace(strconv.Quote(unicodeStr), `\\u`, `\u`, -1)
    61  			text, err := strconv.Unquote(content)
    62  			if err != nil {
    63  				return "", moerr.NewInvalidInputNoCtx("invalid unicode")
    64  			}
    65  			sb.WriteString(text)
    66  			i += 4
    67  			continue
    68  		}
    69  		sb.WriteByte(str[i])
    70  	}
    71  	return sb.String(), nil
    72  }
    73  
    74  // MarshalJSON transform bytejson to []byte,for visible
    75  func (bj ByteJson) MarshalJSON() ([]byte, error) {
    76  	ret := make([]byte, 0, len(bj.Data)*3/2)
    77  	return bj.to(ret)
    78  }
    79  
    80  // Marshal transform bytejson to []byte,for storage
    81  func (bj ByteJson) Marshal() ([]byte, error) {
    82  	buf := make([]byte, len(bj.Data)+1)
    83  	buf[0] = byte(bj.Type)
    84  	copy(buf[1:], bj.Data)
    85  	return buf, nil
    86  }
    87  
    88  // Unmarshal transform storage []byte  to bytejson
    89  func (bj *ByteJson) Unmarshal(buf []byte) error {
    90  	//TODO add validate checker
    91  	bj.Type = TpCode(buf[0])
    92  	bj.Data = buf[1:]
    93  	return nil
    94  }
    95  
    96  // UnmarshalJSON transform visible []byte to bytejson
    97  func (bj *ByteJson) UnmarshalJSON(data []byte) error {
    98  	var decoder = json.NewDecoder(bytes.NewReader(data))
    99  	decoder.UseNumber()
   100  	var in interface{}
   101  	err := decoder.Decode(&in)
   102  	if err != nil {
   103  		return nil
   104  	}
   105  	buf := make([]byte, 0, len(data))
   106  	if tpCode, buf, err := addElem(buf, in); err != nil {
   107  		return err
   108  	} else {
   109  		bj.Data = buf
   110  		bj.Type = tpCode
   111  	}
   112  	return nil
   113  }
   114  
   115  func (bj *ByteJson) UnmarshalObject(obj interface{}) (err error) {
   116  	buf := make([]byte, 0, 64)
   117  	var tpCode TpCode
   118  	if tpCode, buf, err = addElem(buf, obj); err != nil {
   119  		return
   120  	}
   121  	bj.Type = tpCode
   122  	bj.Data = buf
   123  	return
   124  }
   125  
   126  func (bj ByteJson) IsNull() bool {
   127  	return bj.Type == TpCodeLiteral && bj.Data[0] == LiteralNull
   128  }
   129  
   130  func (bj ByteJson) GetElemCnt() int {
   131  	return int(endian.Uint32(bj.Data))
   132  }
   133  
   134  func (bj ByteJson) GetInt64() int64 {
   135  	return int64(bj.GetUint64())
   136  }
   137  func (bj ByteJson) GetUint64() uint64 {
   138  	return endian.Uint64(bj.Data)
   139  }
   140  
   141  func (bj ByteJson) GetFloat64() float64 {
   142  	return math.Float64frombits(bj.GetUint64())
   143  }
   144  
   145  func (bj ByteJson) GetString() []byte {
   146  	num, length := calStrLen(bj.Data)
   147  	return bj.Data[length : length+num]
   148  }
   149  
   150  func (bj ByteJson) to(buf []byte) ([]byte, error) {
   151  	var err error
   152  	switch bj.Type {
   153  	case TpCodeArray:
   154  		buf, err = bj.toArray(buf)
   155  	case TpCodeObject:
   156  		buf, err = bj.toObject(buf)
   157  	case TpCodeInt64:
   158  		buf = bj.toInt64(buf)
   159  	case TpCodeUint64:
   160  		buf = bj.toUint64(buf)
   161  	case TpCodeLiteral:
   162  		buf = bj.toLiteral(buf)
   163  	case TpCodeFloat64:
   164  		buf, err = bj.toFloat64(buf)
   165  	case TpCodeString:
   166  		buf = bj.toString(buf)
   167  	default:
   168  		err = moerr.NewInvalidInputNoCtx("invalid json type '%v'", bj.Type)
   169  	}
   170  	return buf, err
   171  }
   172  
   173  func (bj ByteJson) toArray(buf []byte) ([]byte, error) {
   174  	cnt := bj.GetElemCnt()
   175  	buf = append(buf, '[')
   176  	var err error
   177  	for i := 0; i < cnt; i++ {
   178  		if i != 0 {
   179  			buf = append(buf, ", "...)
   180  		}
   181  		buf, err = bj.getArrayElem(i).to(buf)
   182  		if err != nil {
   183  			return nil, err
   184  		}
   185  	}
   186  	return append(buf, ']'), nil
   187  }
   188  
   189  func (bj ByteJson) toObject(buf []byte) ([]byte, error) {
   190  	cnt := bj.GetElemCnt()
   191  	buf = append(buf, '{')
   192  	for i := 0; i < cnt; i++ {
   193  		if i != 0 {
   194  			buf = append(buf, ", "...)
   195  		}
   196  		var err error
   197  		buf = toString(buf, bj.getObjectKey(i))
   198  		buf = append(buf, ": "...)
   199  		buf, err = bj.getObjectVal(i).to(buf)
   200  		if err != nil {
   201  			return nil, err
   202  		}
   203  	}
   204  	return append(buf, '}'), nil
   205  }
   206  
   207  func (bj ByteJson) toInt64(buf []byte) []byte {
   208  	return strconv.AppendInt(buf, bj.GetInt64(), 10)
   209  }
   210  func (bj ByteJson) toUint64(buf []byte) []byte {
   211  	return strconv.AppendUint(buf, bj.GetUint64(), 10)
   212  }
   213  
   214  func (bj ByteJson) toLiteral(buf []byte) []byte {
   215  	litTp := bj.Data[0]
   216  	switch litTp {
   217  	case LiteralNull:
   218  		buf = append(buf, "null"...)
   219  	case LiteralTrue:
   220  		buf = append(buf, "true"...)
   221  	case LiteralFalse:
   222  		buf = append(buf, "false"...)
   223  	default:
   224  		panic(fmt.Sprintf("invalid literal type:%d", litTp))
   225  	}
   226  	return buf
   227  }
   228  
   229  func (bj ByteJson) toFloat64(buf []byte) ([]byte, error) {
   230  	f := bj.GetFloat64()
   231  	err := checkFloat64(f)
   232  	if err != nil {
   233  		return nil, err
   234  	}
   235  	// https://github.com/golang/go/issues/14135
   236  	var format byte
   237  	abs := math.Abs(f)
   238  	if abs == 0 || 1e-6 <= abs && abs < 1e21 {
   239  		format = 'f'
   240  	} else {
   241  		format = 'e'
   242  	}
   243  	buf = strconv.AppendFloat(buf, f, format, -1, 64)
   244  	return buf, nil
   245  }
   246  
   247  // transform byte string to visible string
   248  func (bj ByteJson) toString(buf []byte) []byte {
   249  	data := bj.GetString()
   250  	return toString(buf, data)
   251  }
   252  
   253  func (bj ByteJson) getObjectKey(i int) []byte {
   254  	keyOff := int(endian.Uint32(bj.Data[headerSize+i*keyEntrySize:]))
   255  	keyLen := int(endian.Uint16(bj.Data[headerSize+i*keyEntrySize+keyOriginOff:]))
   256  	return bj.Data[keyOff : keyOff+keyLen]
   257  }
   258  
   259  func (bj ByteJson) getArrayElem(i int) ByteJson {
   260  	return bj.getValEntry(headerSize + i*valEntrySize)
   261  }
   262  
   263  func (bj ByteJson) getObjectVal(i int) ByteJson {
   264  	cnt := bj.GetElemCnt()
   265  	return bj.getValEntry(headerSize + cnt*keyEntrySize + i*valEntrySize)
   266  }
   267  
   268  func (bj ByteJson) getValEntry(off int) ByteJson {
   269  	tpCode := bj.Data[off]
   270  	valOff := endian.Uint32(bj.Data[off+valTypeSize:])
   271  	switch TpCode(tpCode) {
   272  	case TpCodeLiteral:
   273  		return ByteJson{Type: TpCodeLiteral, Data: bj.Data[off+valTypeSize : off+valTypeSize+1]}
   274  	case TpCodeUint64, TpCodeInt64, TpCodeFloat64:
   275  		return ByteJson{Type: TpCode(tpCode), Data: bj.Data[valOff : valOff+numberSize]}
   276  	case TpCodeString:
   277  		num, length := calStrLen(bj.Data[valOff:])
   278  		totalLen := uint32(num) + uint32(length)
   279  		return ByteJson{Type: TpCode(tpCode), Data: bj.Data[valOff : valOff+totalLen]}
   280  	}
   281  	dataBytes := endian.Uint32(bj.Data[valOff+docSizeOff:])
   282  	return ByteJson{Type: TpCode(tpCode), Data: bj.Data[valOff : valOff+dataBytes]}
   283  }
   284  
   285  func (bj ByteJson) queryValByKey(key []byte) ByteJson {
   286  	cnt := bj.GetElemCnt()
   287  	idx := sort.Search(cnt, func(i int) bool {
   288  		return bytes.Compare(bj.getObjectKey(i), key) >= 0
   289  	})
   290  	if idx >= cnt || !bytes.Equal(bj.getObjectKey(idx), key) {
   291  		dt := make([]byte, 1)
   292  		dt[0] = LiteralNull
   293  		return ByteJson{
   294  			Type: TpCodeLiteral,
   295  			Data: dt,
   296  		}
   297  	}
   298  	return bj.getObjectVal(idx)
   299  }
   300  
   301  func (bj ByteJson) query(cur []ByteJson, path *Path) []ByteJson {
   302  	if path.empty() {
   303  		cur = append(cur, bj)
   304  		return cur
   305  	}
   306  	sub, nPath := path.step()
   307  
   308  	if sub.tp == subPathDoubleStar {
   309  		cur = bj.query(cur, &nPath)
   310  		if bj.Type == TpCodeObject {
   311  			cnt := bj.GetElemCnt()
   312  			for i := 0; i < cnt; i++ {
   313  				cur = bj.getObjectVal(i).query(cur, path) // take care here, the argument is path,not nPath
   314  			}
   315  		} else if bj.Type == TpCodeArray {
   316  			cnt := bj.GetElemCnt()
   317  			for i := 0; i < cnt; i++ {
   318  				cur = bj.getArrayElem(i).query(cur, path) // take care here, the argument is path,not nPath
   319  			}
   320  		}
   321  		return cur
   322  	}
   323  
   324  	if bj.Type == TpCodeObject {
   325  		switch sub.tp {
   326  		case subPathIdx:
   327  			start, _, _ := sub.idx.genIndex(1)
   328  			if start == 0 {
   329  				cur = bj.query(cur, &nPath)
   330  			}
   331  		case subPathRange:
   332  			se := sub.iRange.genRange(bj.GetElemCnt())
   333  			if se[0] == 0 {
   334  				cur = bj.query(cur, &nPath)
   335  			}
   336  		case subPathKey:
   337  			cnt := bj.GetElemCnt()
   338  			if sub.key == "*" {
   339  				for i := 0; i < cnt; i++ {
   340  					cur = bj.getObjectVal(i).query(cur, &nPath)
   341  				}
   342  			} else {
   343  				tmp := bj.queryValByKey(util.UnsafeStringToBytes(sub.key))
   344  				cur = tmp.query(cur, &nPath)
   345  			}
   346  		}
   347  		return cur
   348  	}
   349  
   350  	if bj.Type == TpCodeArray {
   351  		cnt := bj.GetElemCnt()
   352  		switch sub.tp {
   353  		case subPathIdx:
   354  			idx, _, last := sub.idx.genIndex(cnt)
   355  			if last && idx < 0 || cnt <= idx {
   356  				tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}}
   357  				cur = append(cur, tmp)
   358  				return cur
   359  			}
   360  			if idx == subPathIdxALL {
   361  				for i := 0; i < cnt; i++ {
   362  					cur = bj.getArrayElem(i).query(cur, &nPath)
   363  				}
   364  			} else {
   365  				cur = bj.getArrayElem(idx).query(cur, &nPath)
   366  			}
   367  		case subPathRange:
   368  			se := sub.iRange.genRange(cnt)
   369  			if se[0] == subPathIdxErr {
   370  				tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}}
   371  				cur = append(cur, tmp)
   372  				return cur
   373  			}
   374  			for i := se[0]; i <= se[1]; i++ {
   375  				cur = bj.getArrayElem(i).query(cur, &nPath)
   376  			}
   377  		}
   378  	}
   379  	return cur
   380  }
   381  func (bj ByteJson) Query(paths []*Path) *ByteJson {
   382  	out := make([]ByteJson, 0, len(paths))
   383  	for _, path := range paths {
   384  		tmp := bj.query(nil, path)
   385  		if len(tmp) > 0 {
   386  			allNull := checkAllNull(tmp)
   387  			if !allNull {
   388  				out = append(out, tmp...)
   389  			}
   390  		}
   391  	}
   392  	if len(out) == 0 {
   393  		return &ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}}
   394  	}
   395  	if len(out) == 1 && len(paths) == 1 {
   396  		return &out[0]
   397  	}
   398  	allNull := checkAllNull(out)
   399  	if allNull {
   400  		return &ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}}
   401  	}
   402  	return mergeToArray(out)
   403  }
   404  
   405  func (bj ByteJson) canUnnest() bool {
   406  	return bj.Type == TpCodeArray || bj.Type == TpCodeObject
   407  }
   408  
   409  func (bj ByteJson) queryWithSubPath(keys []string, vals []ByteJson, path *Path, pathStr string) ([]string, []ByteJson) {
   410  	if path.empty() {
   411  		keys = append(keys, pathStr)
   412  		vals = append(vals, bj)
   413  		return keys, vals
   414  	}
   415  	sub, nPath := path.step()
   416  	if sub.tp == subPathDoubleStar {
   417  		keys, vals = bj.queryWithSubPath(keys, vals, &nPath, pathStr)
   418  		if bj.Type == TpCodeObject {
   419  			cnt := bj.GetElemCnt()
   420  			for i := 0; i < cnt; i++ {
   421  				newPathStr := fmt.Sprintf("%s.%s", pathStr, bj.getObjectKey(i))
   422  				keys, vals = bj.getObjectVal(i).queryWithSubPath(keys, vals, path, newPathStr) // take care here, the argument is path,not nPath
   423  			}
   424  		} else if bj.Type == TpCodeArray {
   425  			cnt := bj.GetElemCnt()
   426  			for i := 0; i < cnt; i++ {
   427  				newPathStr := fmt.Sprintf("%s[%d]", pathStr, i)
   428  				keys, vals = bj.getArrayElem(i).queryWithSubPath(keys, vals, path, newPathStr) // take care here, the argument is path,not nPath
   429  			}
   430  		}
   431  		return keys, vals
   432  	}
   433  	if bj.Type == TpCodeObject {
   434  		cnt := bj.GetElemCnt()
   435  		switch sub.tp {
   436  		case subPathIdx:
   437  			start, _, _ := sub.idx.genIndex(1)
   438  			if start == 0 {
   439  				newPathStr := fmt.Sprintf("%s[%d]", pathStr, start)
   440  				keys, vals = bj.queryWithSubPath(keys, vals, &nPath, newPathStr)
   441  			}
   442  		case subPathRange:
   443  			se := sub.iRange.genRange(cnt)
   444  			if se[0] == 0 {
   445  				newPathStr := fmt.Sprintf("%s[%d]", pathStr, se[0])
   446  				keys, vals = bj.queryWithSubPath(keys, vals, &nPath, newPathStr)
   447  			}
   448  		case subPathKey:
   449  			if sub.key == "*" {
   450  				for i := 0; i < cnt; i++ {
   451  					newPathStr := fmt.Sprintf("%s.%s", pathStr, bj.getObjectKey(i))
   452  					keys, vals = bj.getObjectVal(i).queryWithSubPath(keys, vals, &nPath, newPathStr)
   453  				}
   454  			} else {
   455  				tmp := bj.queryValByKey(util.UnsafeStringToBytes(sub.key))
   456  				newPathStr := fmt.Sprintf("%s.%s", pathStr, sub.key)
   457  				keys, vals = tmp.queryWithSubPath(keys, vals, &nPath, newPathStr)
   458  			}
   459  		}
   460  	}
   461  	if bj.Type == TpCodeArray {
   462  		cnt := bj.GetElemCnt()
   463  		switch sub.tp {
   464  		case subPathIdx:
   465  			idx, _, last := sub.idx.genIndex(cnt)
   466  			if last && idx < 0 {
   467  				tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}}
   468  				newPathStr := fmt.Sprintf("%s[%d]", pathStr, sub.idx.num)
   469  				keys = append(keys, newPathStr)
   470  				vals = append(vals, tmp)
   471  				return keys, vals
   472  			}
   473  			if idx == subPathIdxALL {
   474  				for i := 0; i < cnt; i++ {
   475  					newPathStr := fmt.Sprintf("%s[%d]", pathStr, i)
   476  					keys, vals = bj.getArrayElem(i).queryWithSubPath(keys, vals, &nPath, newPathStr)
   477  				}
   478  			} else {
   479  				newPathStr := fmt.Sprintf("%s[%d]", pathStr, idx)
   480  				keys, vals = bj.getArrayElem(idx).queryWithSubPath(keys, vals, &nPath, newPathStr)
   481  			}
   482  		case subPathRange:
   483  			se := sub.iRange.genRange(cnt)
   484  			if se[0] == subPathIdxErr {
   485  				tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}}
   486  				newPathStr := fmt.Sprintf("%s[%d to %d]", pathStr, sub.iRange.start.num, sub.iRange.end.num)
   487  				keys = append(keys, newPathStr)
   488  				vals = append(vals, tmp)
   489  				return keys, vals
   490  			}
   491  			for i := se[0]; i <= se[1]; i++ {
   492  				newPathStr := fmt.Sprintf("%s[%d]", pathStr, i)
   493  				keys, vals = bj.getArrayElem(i).queryWithSubPath(keys, vals, &nPath, newPathStr)
   494  			}
   495  		}
   496  	}
   497  	return keys, vals
   498  }
   499  
   500  func (bj ByteJson) unnestWithParams(out []UnnestResult, outer, recursive bool, mode string, pathStr string, this *ByteJson, filterMap map[string]struct{}) []UnnestResult {
   501  	if !bj.canUnnest() {
   502  		index, key := genIndexOrKey(pathStr)
   503  		tmp := UnnestResult{}
   504  		genUnnestResult(tmp, index, key, util.UnsafeStringToBytes(pathStr), &bj, this, filterMap)
   505  		out = append(out, tmp)
   506  		return out
   507  	}
   508  	if bj.Type == TpCodeObject && mode != "array" {
   509  		cnt := bj.GetElemCnt()
   510  		for i := 0; i < cnt; i++ {
   511  			key := bj.getObjectKey(i)
   512  			val := bj.getObjectVal(i)
   513  			newPathStr := fmt.Sprintf("%s.%s", pathStr, key)
   514  			tmp := UnnestResult{}
   515  			genUnnestResult(tmp, nil, key, util.UnsafeStringToBytes(newPathStr), &val, this, filterMap)
   516  			out = append(out, tmp)
   517  			if val.canUnnest() && recursive {
   518  				out = val.unnestWithParams(out, outer, recursive, mode, newPathStr, &val, filterMap)
   519  			}
   520  		}
   521  	}
   522  	if bj.Type == TpCodeArray && mode != "object" {
   523  		cnt := bj.GetElemCnt()
   524  		for i := 0; i < cnt; i++ {
   525  			val := bj.getArrayElem(i)
   526  			newPathStr := fmt.Sprintf("%s[%d]", pathStr, i)
   527  			tmp := UnnestResult{}
   528  			genUnnestResult(tmp, util.UnsafeStringToBytes(strconv.Itoa(i)), nil, util.UnsafeStringToBytes(newPathStr), &val, this, filterMap)
   529  			out = append(out, tmp)
   530  			if val.canUnnest() && recursive {
   531  				out = val.unnestWithParams(out, outer, recursive, mode, newPathStr, &val, filterMap)
   532  			}
   533  		}
   534  	}
   535  	return out
   536  }
   537  
   538  func (bj ByteJson) unnest(out []UnnestResult, path *Path, outer, recursive bool, mode string, filterMap map[string]struct{}) ([]UnnestResult, error) {
   539  
   540  	keys := make([]string, 0, 1)
   541  	vals := make([]ByteJson, 0, 1)
   542  	keys, vals = bj.queryWithSubPath(keys, vals, path, "$")
   543  	if len(keys) != len(vals) {
   544  		return nil, moerr.NewInvalidInputNoCtx("len(key) and len(val) are not equal, len(key)=%d, len(val)=%d", len(keys), len(vals))
   545  	}
   546  	for i := 0; i < len(keys); i++ {
   547  		if vals[i].canUnnest() {
   548  			out = vals[i].unnestWithParams(out, outer, recursive, mode, keys[i], &vals[i], filterMap)
   549  		}
   550  	}
   551  	if len(out) == 0 && outer {
   552  		for i := 0; i < len(keys); i++ {
   553  			tmp := UnnestResult{}
   554  			out = append(out, tmp)
   555  		}
   556  		if _, ok := filterMap["path"]; ok {
   557  			for i := 0; i < len(keys); i++ {
   558  				out[i]["path"] = util.UnsafeStringToBytes(keys[i])
   559  			}
   560  		}
   561  		if _, ok := filterMap["this"]; ok {
   562  			for i := 0; i < len(vals); i++ {
   563  				dt, err := vals[i].Marshal()
   564  				if err != nil {
   565  					return nil, err
   566  				}
   567  				out[i]["this"] = dt
   568  			}
   569  		}
   570  
   571  	}
   572  	return out, nil
   573  }
   574  
   575  // Unnest returns a slice of UnnestResult, each UnnestResult contains filtered data, if param filters is nil, return all fields.
   576  func (bj ByteJson) Unnest(path *Path, outer, recursive bool, mode string, filterMap map[string]struct{}) ([]UnnestResult, error) {
   577  	if !checkMode(mode) {
   578  		return nil, moerr.NewInvalidInputNoCtx("mode must be one of [object, array, both]")
   579  	}
   580  	out := make([]UnnestResult, 0, 1)
   581  	out, err := bj.unnest(out, path, outer, recursive, mode, filterMap)
   582  	return out, err
   583  }
   584  
   585  func genUnnestResult(res UnnestResult, index, key, path []byte, value, this *ByteJson, filterMap map[string]struct{}) UnnestResult {
   586  	if _, ok := filterMap["index"]; ok {
   587  		res["index"] = index
   588  	}
   589  	if _, ok := filterMap["key"]; ok {
   590  		res["key"] = key
   591  	}
   592  	if _, ok := filterMap["path"]; ok {
   593  		res["path"] = path
   594  	}
   595  	if _, ok := filterMap["value"]; ok {
   596  		dt, _ := value.Marshal()
   597  		res["value"] = dt
   598  	}
   599  	if _, ok := filterMap["this"]; ok {
   600  		dt, _ := this.Marshal()
   601  		res["this"] = dt
   602  	}
   603  	return res
   604  }
   605  
   606  func ParseJsonByteFromString(s string) ([]byte, error) {
   607  	var decoder = json.NewDecoder(strings.NewReader(s))
   608  	decoder.UseNumber()
   609  	var in interface{}
   610  	err := decoder.Decode(&in)
   611  	if err != nil {
   612  		return nil, err
   613  	}
   614  	buf := make([]byte, 1, len(s)+1)
   615  	switch x := in.(type) {
   616  	case nil:
   617  		buf[0] = byte(TpCodeLiteral)
   618  		buf = append(buf, LiteralNull)
   619  	case bool:
   620  		buf[0] = byte(TpCodeLiteral)
   621  		lit := LiteralFalse
   622  		if x {
   623  			lit = LiteralTrue
   624  		}
   625  		buf = append(buf, lit)
   626  	case int64:
   627  		buf[0] = byte(TpCodeInt64)
   628  		buf = addUint64(buf, uint64(x))
   629  	case uint64:
   630  		buf[0] = byte(TpCodeUint64)
   631  		buf = addUint64(buf, x)
   632  	case json.Number:
   633  		if strings.ContainsAny(string(x), "Ee.") {
   634  			val, err := x.Float64()
   635  			buf[0] = byte(TpCodeFloat64)
   636  			if err != nil {
   637  				return nil, moerr.NewInvalidInputNoCtx("json number %v", in)
   638  			}
   639  			if err = checkFloat64(val); err != nil {
   640  				return nil, err
   641  			}
   642  			return addFloat64(buf, val), nil
   643  		}
   644  		if val, err := x.Int64(); err == nil {
   645  			buf[0] = byte(TpCodeInt64)
   646  			return addInt64(buf, val), nil
   647  		}
   648  		if val, err := strconv.ParseUint(string(x), 10, 64); err == nil {
   649  			buf[0] = byte(TpCodeUint64)
   650  			return addUint64(buf, val), nil
   651  		}
   652  		if val, err := x.Float64(); err == nil {
   653  			buf[0] = byte(TpCodeFloat64)
   654  			if err = checkFloat64(val); err != nil {
   655  				return nil, err
   656  			}
   657  			return addFloat64(buf, val), nil
   658  		}
   659  	case string:
   660  		buf[0] = byte(TpCodeString)
   661  		buf = addString(buf, x)
   662  	case ByteJson:
   663  		buf[0] = byte(x.Type)
   664  		buf = append(buf, x.Data...)
   665  	case []interface{}:
   666  		buf[0] = byte(TpCodeArray)
   667  		buf, err = addArray(buf, x)
   668  	case map[string]interface{}:
   669  		buf[0] = byte(TpCodeObject)
   670  		buf, err = addObject(buf, x)
   671  	default:
   672  		return nil, moerr.NewInvalidInputNoCtx("json element %v", in)
   673  	}
   674  	return buf, err
   675  }