ptr.go 1.8 KB

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