map.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package decoder
  2. import (
  3. "reflect"
  4. "unsafe"
  5. "github.com/goccy/go-json/internal/errors"
  6. "github.com/goccy/go-json/internal/runtime"
  7. )
  8. type mapDecoder struct {
  9. mapType *runtime.Type
  10. keyType *runtime.Type
  11. valueType *runtime.Type
  12. canUseAssignFaststrType bool
  13. keyDecoder Decoder
  14. valueDecoder Decoder
  15. structName string
  16. fieldName string
  17. }
  18. func newMapDecoder(mapType *runtime.Type, keyType *runtime.Type, keyDec Decoder, valueType *runtime.Type, valueDec Decoder, structName, fieldName string) *mapDecoder {
  19. return &mapDecoder{
  20. mapType: mapType,
  21. keyDecoder: keyDec,
  22. keyType: keyType,
  23. canUseAssignFaststrType: canUseAssignFaststrType(keyType, valueType),
  24. valueType: valueType,
  25. valueDecoder: valueDec,
  26. structName: structName,
  27. fieldName: fieldName,
  28. }
  29. }
  30. const (
  31. mapMaxElemSize = 128
  32. )
  33. // See detail: https://github.com/goccy/go-json/pull/283
  34. func canUseAssignFaststrType(key *runtime.Type, value *runtime.Type) bool {
  35. indirectElem := value.Size() > mapMaxElemSize
  36. if indirectElem {
  37. return false
  38. }
  39. return key.Kind() == reflect.String
  40. }
  41. //go:linkname makemap reflect.makemap
  42. func makemap(*runtime.Type, int) unsafe.Pointer
  43. //nolint:golint
  44. //go:linkname mapassign_faststr runtime.mapassign_faststr
  45. //go:noescape
  46. func mapassign_faststr(t *runtime.Type, m unsafe.Pointer, s string) unsafe.Pointer
  47. //go:linkname mapassign reflect.mapassign
  48. //go:noescape
  49. func mapassign(t *runtime.Type, m unsafe.Pointer, k, v unsafe.Pointer)
  50. func (d *mapDecoder) mapassign(t *runtime.Type, m, k, v unsafe.Pointer) {
  51. if d.canUseAssignFaststrType {
  52. mapV := mapassign_faststr(t, m, *(*string)(k))
  53. typedmemmove(d.valueType, mapV, v)
  54. } else {
  55. mapassign(t, m, k, v)
  56. }
  57. }
  58. func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
  59. depth++
  60. if depth > maxDecodeNestingDepth {
  61. return errors.ErrExceededMaxDepth(s.char(), s.cursor)
  62. }
  63. switch s.skipWhiteSpace() {
  64. case 'n':
  65. if err := nullBytes(s); err != nil {
  66. return err
  67. }
  68. **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
  69. return nil
  70. case '{':
  71. default:
  72. return errors.ErrExpected("{ character for map value", s.totalOffset())
  73. }
  74. mapValue := *(*unsafe.Pointer)(p)
  75. if mapValue == nil {
  76. mapValue = makemap(d.mapType, 0)
  77. }
  78. s.cursor++
  79. if s.equalChar('}') {
  80. *(*unsafe.Pointer)(p) = mapValue
  81. s.cursor++
  82. return nil
  83. }
  84. for {
  85. k := unsafe_New(d.keyType)
  86. if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
  87. return err
  88. }
  89. s.skipWhiteSpace()
  90. if !s.equalChar(':') {
  91. return errors.ErrExpected("colon after object key", s.totalOffset())
  92. }
  93. s.cursor++
  94. v := unsafe_New(d.valueType)
  95. if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil {
  96. return err
  97. }
  98. d.mapassign(d.mapType, mapValue, k, v)
  99. s.skipWhiteSpace()
  100. if s.equalChar('}') {
  101. **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
  102. s.cursor++
  103. return nil
  104. }
  105. if !s.equalChar(',') {
  106. return errors.ErrExpected("comma after object value", s.totalOffset())
  107. }
  108. s.cursor++
  109. }
  110. }
  111. func (d *mapDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
  112. buf := ctx.Buf
  113. depth++
  114. if depth > maxDecodeNestingDepth {
  115. return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
  116. }
  117. cursor = skipWhiteSpace(buf, cursor)
  118. buflen := int64(len(buf))
  119. if buflen < 2 {
  120. return 0, errors.ErrExpected("{} for map", cursor)
  121. }
  122. switch buf[cursor] {
  123. case 'n':
  124. if err := validateNull(buf, cursor); err != nil {
  125. return 0, err
  126. }
  127. cursor += 4
  128. **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
  129. return cursor, nil
  130. case '{':
  131. default:
  132. return 0, errors.ErrExpected("{ character for map value", cursor)
  133. }
  134. cursor++
  135. cursor = skipWhiteSpace(buf, cursor)
  136. mapValue := *(*unsafe.Pointer)(p)
  137. if mapValue == nil {
  138. mapValue = makemap(d.mapType, 0)
  139. }
  140. if buf[cursor] == '}' {
  141. **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
  142. cursor++
  143. return cursor, nil
  144. }
  145. for {
  146. k := unsafe_New(d.keyType)
  147. keyCursor, err := d.keyDecoder.Decode(ctx, cursor, depth, k)
  148. if err != nil {
  149. return 0, err
  150. }
  151. cursor = skipWhiteSpace(buf, keyCursor)
  152. if buf[cursor] != ':' {
  153. return 0, errors.ErrExpected("colon after object key", cursor)
  154. }
  155. cursor++
  156. v := unsafe_New(d.valueType)
  157. valueCursor, err := d.valueDecoder.Decode(ctx, cursor, depth, v)
  158. if err != nil {
  159. return 0, err
  160. }
  161. d.mapassign(d.mapType, mapValue, k, v)
  162. cursor = skipWhiteSpace(buf, valueCursor)
  163. if buf[cursor] == '}' {
  164. **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
  165. cursor++
  166. return cursor, nil
  167. }
  168. if buf[cursor] != ',' {
  169. return 0, errors.ErrExpected("comma after object value", cursor)
  170. }
  171. cursor++
  172. }
  173. }