compile_struct.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package optdec
  2. import (
  3. "fmt"
  4. "reflect"
  5. caching "github.com/bytedance/sonic/internal/optcaching"
  6. "github.com/bytedance/sonic/internal/rt"
  7. "github.com/bytedance/sonic/internal/resolver"
  8. )
  9. const (
  10. _MAX_FIELDS = 50 // cutoff at 50 fields struct
  11. )
  12. func (c *compiler) compileIntStringOption(vt reflect.Type) decFunc {
  13. switch vt.Size() {
  14. case 4:
  15. switch vt.Kind() {
  16. case reflect.Uint:
  17. fallthrough
  18. case reflect.Uintptr:
  19. return &u32StringDecoder{}
  20. case reflect.Int:
  21. return &i32StringDecoder{}
  22. }
  23. case 8:
  24. switch vt.Kind() {
  25. case reflect.Uint:
  26. fallthrough
  27. case reflect.Uintptr:
  28. return &u64StringDecoder{}
  29. case reflect.Int:
  30. return &i64StringDecoder{}
  31. }
  32. default:
  33. panic("not supported pointer size: " + fmt.Sprint(vt.Size()))
  34. }
  35. panic("unreachable")
  36. }
  37. func isInteger(vt reflect.Type) bool {
  38. switch vt.Kind() {
  39. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr, reflect.Int: return true
  40. default: return false
  41. }
  42. }
  43. func (c *compiler) assertStringOptTypes(vt reflect.Type) {
  44. if c.depth > _CompileMaxDepth {
  45. panic(*stackOverflow)
  46. }
  47. c.depth += 1
  48. defer func () {
  49. c.depth -= 1
  50. }()
  51. if isInteger(vt) {
  52. return
  53. }
  54. switch vt.Kind() {
  55. case reflect.String, reflect.Bool, reflect.Float32, reflect.Float64:
  56. return
  57. case reflect.Ptr: c.assertStringOptTypes(vt.Elem())
  58. default:
  59. panicForInvalidStrType(vt)
  60. }
  61. }
  62. func (c *compiler) compileFieldStringOption(vt reflect.Type) decFunc {
  63. c.assertStringOptTypes(vt)
  64. unmDec := c.tryCompilePtrUnmarshaler(vt, true)
  65. if unmDec != nil {
  66. return unmDec
  67. }
  68. switch vt.Kind() {
  69. case reflect.String:
  70. if vt == jsonNumberType {
  71. return &numberStringDecoder{}
  72. }
  73. return &strStringDecoder{}
  74. case reflect.Bool:
  75. return &boolStringDecoder{}
  76. case reflect.Int8:
  77. return &i8StringDecoder{}
  78. case reflect.Int16:
  79. return &i16StringDecoder{}
  80. case reflect.Int32:
  81. return &i32StringDecoder{}
  82. case reflect.Int64:
  83. return &i64StringDecoder{}
  84. case reflect.Uint8:
  85. return &u8StringDecoder{}
  86. case reflect.Uint16:
  87. return &u16StringDecoder{}
  88. case reflect.Uint32:
  89. return &u32StringDecoder{}
  90. case reflect.Uint64:
  91. return &u64StringDecoder{}
  92. case reflect.Float32:
  93. return &f32StringDecoder{}
  94. case reflect.Float64:
  95. return &f64StringDecoder{}
  96. case reflect.Uint:
  97. fallthrough
  98. case reflect.Uintptr:
  99. fallthrough
  100. case reflect.Int:
  101. return c.compileIntStringOption(vt)
  102. case reflect.Ptr:
  103. return &ptrStrDecoder{
  104. typ: rt.UnpackType(vt.Elem()),
  105. deref: c.compileFieldStringOption(vt.Elem()),
  106. }
  107. default:
  108. panicForInvalidStrType(vt)
  109. return nil
  110. }
  111. }
  112. func (c *compiler) compileStruct(vt reflect.Type) decFunc {
  113. c.enter(vt)
  114. defer c.exit(vt)
  115. if c.namedPtr {
  116. c.namedPtr = false
  117. return c.compileStructBody(vt)
  118. }
  119. if c.depth >= c.opts.MaxInlineDepth + 1 || (c.counts > 0 && vt.NumField() >= _MAX_FIELDS) {
  120. return &recuriveDecoder{
  121. typ: rt.UnpackType(vt),
  122. }
  123. } else {
  124. return c.compileStructBody(vt)
  125. }
  126. }
  127. func (c *compiler) compileStructBody(vt reflect.Type) decFunc {
  128. fv := resolver.ResolveStruct(vt)
  129. entries := make([]fieldEntry, 0, len(fv))
  130. for _, f := range fv {
  131. var dec decFunc
  132. /* dealt with field tag options */
  133. if f.Opts&resolver.F_stringize != 0 {
  134. dec = c.compileFieldStringOption(f.Type)
  135. } else {
  136. dec = c.compile(f.Type)
  137. }
  138. /* deal with embedded pointer fields */
  139. if f.Path[0].Kind == resolver.F_deref {
  140. dec = &embeddedFieldPtrDecoder{
  141. field: f,
  142. fieldDec: dec,
  143. fieldName: f.Name,
  144. }
  145. }
  146. entries = append(entries, fieldEntry{
  147. FieldMeta: f,
  148. fieldDec: dec,
  149. })
  150. }
  151. return &structDecoder{
  152. fieldMap: caching.NewFieldLookup(fv),
  153. fields: entries,
  154. structName: vt.Name(),
  155. typ: vt,
  156. }
  157. }