map.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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.skipWhiteSpace() == '}' {
  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. }
  174. func (d *mapDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
  175. buf := ctx.Buf
  176. depth++
  177. if depth > maxDecodeNestingDepth {
  178. return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
  179. }
  180. cursor = skipWhiteSpace(buf, cursor)
  181. buflen := int64(len(buf))
  182. if buflen < 2 {
  183. return nil, 0, errors.ErrExpected("{} for map", cursor)
  184. }
  185. switch buf[cursor] {
  186. case 'n':
  187. if err := validateNull(buf, cursor); err != nil {
  188. return nil, 0, err
  189. }
  190. cursor += 4
  191. return [][]byte{nullbytes}, cursor, nil
  192. case '{':
  193. default:
  194. return nil, 0, errors.ErrExpected("{ character for map value", cursor)
  195. }
  196. cursor++
  197. cursor = skipWhiteSpace(buf, cursor)
  198. if buf[cursor] == '}' {
  199. cursor++
  200. return nil, cursor, nil
  201. }
  202. keyDecoder, ok := d.keyDecoder.(*stringDecoder)
  203. if !ok {
  204. return nil, 0, &errors.UnmarshalTypeError{
  205. Value: "string",
  206. Type: reflect.TypeOf(""),
  207. Offset: cursor,
  208. Struct: d.structName,
  209. Field: d.fieldName,
  210. }
  211. }
  212. ret := [][]byte{}
  213. for {
  214. key, keyCursor, err := keyDecoder.decodeByte(buf, cursor)
  215. if err != nil {
  216. return nil, 0, err
  217. }
  218. cursor = skipWhiteSpace(buf, keyCursor)
  219. if buf[cursor] != ':' {
  220. return nil, 0, errors.ErrExpected("colon after object key", cursor)
  221. }
  222. cursor++
  223. child, found, err := ctx.Option.Path.Field(string(key))
  224. if err != nil {
  225. return nil, 0, err
  226. }
  227. if found {
  228. if child != nil {
  229. oldPath := ctx.Option.Path.node
  230. ctx.Option.Path.node = child
  231. paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth)
  232. if err != nil {
  233. return nil, 0, err
  234. }
  235. ctx.Option.Path.node = oldPath
  236. ret = append(ret, paths...)
  237. cursor = c
  238. } else {
  239. start := cursor
  240. end, err := skipValue(buf, cursor, depth)
  241. if err != nil {
  242. return nil, 0, err
  243. }
  244. ret = append(ret, buf[start:end])
  245. cursor = end
  246. }
  247. } else {
  248. c, err := skipValue(buf, cursor, depth)
  249. if err != nil {
  250. return nil, 0, err
  251. }
  252. cursor = c
  253. }
  254. cursor = skipWhiteSpace(buf, cursor)
  255. if buf[cursor] == '}' {
  256. cursor++
  257. return ret, cursor, nil
  258. }
  259. if buf[cursor] != ',' {
  260. return nil, 0, errors.ErrExpected("comma after object value", cursor)
  261. }
  262. cursor++
  263. }
  264. }