ptr.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package decoder
  2. import (
  3. "fmt"
  4. "unsafe"
  5. "github.com/goccy/go-json/internal/runtime"
  6. )
  7. type ptrDecoder struct {
  8. dec Decoder
  9. typ *runtime.Type
  10. structName string
  11. fieldName string
  12. }
  13. func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder {
  14. return &ptrDecoder{
  15. dec: dec,
  16. typ: typ,
  17. structName: structName,
  18. fieldName: fieldName,
  19. }
  20. }
  21. func (d *ptrDecoder) contentDecoder() Decoder {
  22. dec, ok := d.dec.(*ptrDecoder)
  23. if !ok {
  24. return d.dec
  25. }
  26. return dec.contentDecoder()
  27. }
  28. //nolint:golint
  29. //go:linkname unsafe_New reflect.unsafe_New
  30. func unsafe_New(*runtime.Type) unsafe.Pointer
  31. func UnsafeNew(t *runtime.Type) unsafe.Pointer {
  32. return unsafe_New(t)
  33. }
  34. func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
  35. if s.skipWhiteSpace() == nul {
  36. s.read()
  37. }
  38. if s.char() == 'n' {
  39. if err := nullBytes(s); err != nil {
  40. return err
  41. }
  42. *(*unsafe.Pointer)(p) = nil
  43. return nil
  44. }
  45. var newptr unsafe.Pointer
  46. if *(*unsafe.Pointer)(p) == nil {
  47. newptr = unsafe_New(d.typ)
  48. *(*unsafe.Pointer)(p) = newptr
  49. } else {
  50. newptr = *(*unsafe.Pointer)(p)
  51. }
  52. if err := d.dec.DecodeStream(s, depth, newptr); err != nil {
  53. return err
  54. }
  55. return nil
  56. }
  57. func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
  58. buf := ctx.Buf
  59. cursor = skipWhiteSpace(buf, cursor)
  60. if buf[cursor] == 'n' {
  61. if err := validateNull(buf, cursor); err != nil {
  62. return 0, err
  63. }
  64. if p != nil {
  65. *(*unsafe.Pointer)(p) = nil
  66. }
  67. cursor += 4
  68. return cursor, nil
  69. }
  70. var newptr unsafe.Pointer
  71. if *(*unsafe.Pointer)(p) == nil {
  72. newptr = unsafe_New(d.typ)
  73. *(*unsafe.Pointer)(p) = newptr
  74. } else {
  75. newptr = *(*unsafe.Pointer)(p)
  76. }
  77. c, err := d.dec.Decode(ctx, cursor, depth, newptr)
  78. if err != nil {
  79. return 0, err
  80. }
  81. cursor = c
  82. return cursor, nil
  83. }
  84. func (d *ptrDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
  85. return nil, 0, fmt.Errorf("json: ptr decoder does not support decode path")
  86. }