code.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. package encoder
  2. import (
  3. "fmt"
  4. "unsafe"
  5. "github.com/goccy/go-json/internal/runtime"
  6. )
  7. type Code interface {
  8. Kind() CodeKind
  9. ToOpcode(*compileContext) Opcodes
  10. Filter(*FieldQuery) Code
  11. }
  12. type AnonymousCode interface {
  13. ToAnonymousOpcode(*compileContext) Opcodes
  14. }
  15. type Opcodes []*Opcode
  16. func (o Opcodes) First() *Opcode {
  17. if len(o) == 0 {
  18. return nil
  19. }
  20. return o[0]
  21. }
  22. func (o Opcodes) Last() *Opcode {
  23. if len(o) == 0 {
  24. return nil
  25. }
  26. return o[len(o)-1]
  27. }
  28. func (o Opcodes) Add(codes ...*Opcode) Opcodes {
  29. return append(o, codes...)
  30. }
  31. type CodeKind int
  32. const (
  33. CodeKindInterface CodeKind = iota
  34. CodeKindPtr
  35. CodeKindInt
  36. CodeKindUint
  37. CodeKindFloat
  38. CodeKindString
  39. CodeKindBool
  40. CodeKindStruct
  41. CodeKindMap
  42. CodeKindSlice
  43. CodeKindArray
  44. CodeKindBytes
  45. CodeKindMarshalJSON
  46. CodeKindMarshalText
  47. CodeKindRecursive
  48. )
  49. type IntCode struct {
  50. typ *runtime.Type
  51. bitSize uint8
  52. isString bool
  53. isPtr bool
  54. }
  55. func (c *IntCode) Kind() CodeKind {
  56. return CodeKindInt
  57. }
  58. func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes {
  59. var code *Opcode
  60. switch {
  61. case c.isPtr:
  62. code = newOpCode(ctx, c.typ, OpIntPtr)
  63. case c.isString:
  64. code = newOpCode(ctx, c.typ, OpIntString)
  65. default:
  66. code = newOpCode(ctx, c.typ, OpInt)
  67. }
  68. code.NumBitSize = c.bitSize
  69. ctx.incIndex()
  70. return Opcodes{code}
  71. }
  72. func (c *IntCode) Filter(_ *FieldQuery) Code {
  73. return c
  74. }
  75. type UintCode struct {
  76. typ *runtime.Type
  77. bitSize uint8
  78. isString bool
  79. isPtr bool
  80. }
  81. func (c *UintCode) Kind() CodeKind {
  82. return CodeKindUint
  83. }
  84. func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes {
  85. var code *Opcode
  86. switch {
  87. case c.isPtr:
  88. code = newOpCode(ctx, c.typ, OpUintPtr)
  89. case c.isString:
  90. code = newOpCode(ctx, c.typ, OpUintString)
  91. default:
  92. code = newOpCode(ctx, c.typ, OpUint)
  93. }
  94. code.NumBitSize = c.bitSize
  95. ctx.incIndex()
  96. return Opcodes{code}
  97. }
  98. func (c *UintCode) Filter(_ *FieldQuery) Code {
  99. return c
  100. }
  101. type FloatCode struct {
  102. typ *runtime.Type
  103. bitSize uint8
  104. isPtr bool
  105. }
  106. func (c *FloatCode) Kind() CodeKind {
  107. return CodeKindFloat
  108. }
  109. func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes {
  110. var code *Opcode
  111. switch {
  112. case c.isPtr:
  113. switch c.bitSize {
  114. case 32:
  115. code = newOpCode(ctx, c.typ, OpFloat32Ptr)
  116. default:
  117. code = newOpCode(ctx, c.typ, OpFloat64Ptr)
  118. }
  119. default:
  120. switch c.bitSize {
  121. case 32:
  122. code = newOpCode(ctx, c.typ, OpFloat32)
  123. default:
  124. code = newOpCode(ctx, c.typ, OpFloat64)
  125. }
  126. }
  127. ctx.incIndex()
  128. return Opcodes{code}
  129. }
  130. func (c *FloatCode) Filter(_ *FieldQuery) Code {
  131. return c
  132. }
  133. type StringCode struct {
  134. typ *runtime.Type
  135. isPtr bool
  136. }
  137. func (c *StringCode) Kind() CodeKind {
  138. return CodeKindString
  139. }
  140. func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes {
  141. isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType)
  142. var code *Opcode
  143. if c.isPtr {
  144. if isJSONNumberType {
  145. code = newOpCode(ctx, c.typ, OpNumberPtr)
  146. } else {
  147. code = newOpCode(ctx, c.typ, OpStringPtr)
  148. }
  149. } else {
  150. if isJSONNumberType {
  151. code = newOpCode(ctx, c.typ, OpNumber)
  152. } else {
  153. code = newOpCode(ctx, c.typ, OpString)
  154. }
  155. }
  156. ctx.incIndex()
  157. return Opcodes{code}
  158. }
  159. func (c *StringCode) Filter(_ *FieldQuery) Code {
  160. return c
  161. }
  162. type BoolCode struct {
  163. typ *runtime.Type
  164. isPtr bool
  165. }
  166. func (c *BoolCode) Kind() CodeKind {
  167. return CodeKindBool
  168. }
  169. func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes {
  170. var code *Opcode
  171. switch {
  172. case c.isPtr:
  173. code = newOpCode(ctx, c.typ, OpBoolPtr)
  174. default:
  175. code = newOpCode(ctx, c.typ, OpBool)
  176. }
  177. ctx.incIndex()
  178. return Opcodes{code}
  179. }
  180. func (c *BoolCode) Filter(_ *FieldQuery) Code {
  181. return c
  182. }
  183. type BytesCode struct {
  184. typ *runtime.Type
  185. isPtr bool
  186. }
  187. func (c *BytesCode) Kind() CodeKind {
  188. return CodeKindBytes
  189. }
  190. func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes {
  191. var code *Opcode
  192. switch {
  193. case c.isPtr:
  194. code = newOpCode(ctx, c.typ, OpBytesPtr)
  195. default:
  196. code = newOpCode(ctx, c.typ, OpBytes)
  197. }
  198. ctx.incIndex()
  199. return Opcodes{code}
  200. }
  201. func (c *BytesCode) Filter(_ *FieldQuery) Code {
  202. return c
  203. }
  204. type SliceCode struct {
  205. typ *runtime.Type
  206. value Code
  207. }
  208. func (c *SliceCode) Kind() CodeKind {
  209. return CodeKindSlice
  210. }
  211. func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
  212. // header => opcode => elem => end
  213. // ^ |
  214. // |________|
  215. size := c.typ.Elem().Size()
  216. header := newSliceHeaderCode(ctx, c.typ)
  217. ctx.incIndex()
  218. ctx.incIndent()
  219. codes := c.value.ToOpcode(ctx)
  220. ctx.decIndent()
  221. codes.First().Flags |= IndirectFlags
  222. elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size)
  223. ctx.incIndex()
  224. end := newOpCode(ctx, c.typ, OpSliceEnd)
  225. ctx.incIndex()
  226. header.End = end
  227. header.Next = codes.First()
  228. codes.Last().Next = elemCode
  229. elemCode.Next = codes.First()
  230. elemCode.End = end
  231. return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
  232. }
  233. func (c *SliceCode) Filter(_ *FieldQuery) Code {
  234. return c
  235. }
  236. type ArrayCode struct {
  237. typ *runtime.Type
  238. value Code
  239. }
  240. func (c *ArrayCode) Kind() CodeKind {
  241. return CodeKindArray
  242. }
  243. func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
  244. // header => opcode => elem => end
  245. // ^ |
  246. // |________|
  247. elem := c.typ.Elem()
  248. alen := c.typ.Len()
  249. size := elem.Size()
  250. header := newArrayHeaderCode(ctx, c.typ, alen)
  251. ctx.incIndex()
  252. ctx.incIndent()
  253. codes := c.value.ToOpcode(ctx)
  254. ctx.decIndent()
  255. codes.First().Flags |= IndirectFlags
  256. elemCode := newArrayElemCode(ctx, elem, header, alen, size)
  257. ctx.incIndex()
  258. end := newOpCode(ctx, c.typ, OpArrayEnd)
  259. ctx.incIndex()
  260. header.End = end
  261. header.Next = codes.First()
  262. codes.Last().Next = elemCode
  263. elemCode.Next = codes.First()
  264. elemCode.End = end
  265. return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
  266. }
  267. func (c *ArrayCode) Filter(_ *FieldQuery) Code {
  268. return c
  269. }
  270. type MapCode struct {
  271. typ *runtime.Type
  272. key Code
  273. value Code
  274. }
  275. func (c *MapCode) Kind() CodeKind {
  276. return CodeKindMap
  277. }
  278. func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
  279. // header => code => value => code => key => code => value => code => end
  280. // ^ |
  281. // |_______________________|
  282. header := newMapHeaderCode(ctx, c.typ)
  283. ctx.incIndex()
  284. keyCodes := c.key.ToOpcode(ctx)
  285. value := newMapValueCode(ctx, c.typ.Elem(), header)
  286. ctx.incIndex()
  287. ctx.incIndent()
  288. valueCodes := c.value.ToOpcode(ctx)
  289. ctx.decIndent()
  290. valueCodes.First().Flags |= IndirectFlags
  291. key := newMapKeyCode(ctx, c.typ.Key(), header)
  292. ctx.incIndex()
  293. end := newMapEndCode(ctx, c.typ, header)
  294. ctx.incIndex()
  295. header.Next = keyCodes.First()
  296. keyCodes.Last().Next = value
  297. value.Next = valueCodes.First()
  298. valueCodes.Last().Next = key
  299. key.Next = keyCodes.First()
  300. header.End = end
  301. key.End = end
  302. value.End = end
  303. return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
  304. }
  305. func (c *MapCode) Filter(_ *FieldQuery) Code {
  306. return c
  307. }
  308. type StructCode struct {
  309. typ *runtime.Type
  310. fields []*StructFieldCode
  311. isPtr bool
  312. disableIndirectConversion bool
  313. isIndirect bool
  314. isRecursive bool
  315. }
  316. func (c *StructCode) Kind() CodeKind {
  317. return CodeKindStruct
  318. }
  319. func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
  320. if field.isAnonymous {
  321. return c.lastAnonymousFieldCode(firstField)
  322. }
  323. lastField := firstField
  324. for lastField.NextField != nil {
  325. lastField = lastField.NextField
  326. }
  327. return lastField
  328. }
  329. func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {
  330. // firstField is special StructHead operation for anonymous structure.
  331. // So, StructHead's next operation is truly struct head operation.
  332. lastField := firstField.Next
  333. for lastField.NextField != nil {
  334. lastField = lastField.NextField
  335. }
  336. return lastField
  337. }
  338. func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
  339. // header => code => structField => code => end
  340. // ^ |
  341. // |__________|
  342. if c.isRecursive {
  343. recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
  344. recursive.Type = c.typ
  345. ctx.incIndex()
  346. *ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
  347. return Opcodes{recursive}
  348. }
  349. codes := Opcodes{}
  350. var prevField *Opcode
  351. ctx.incIndent()
  352. for idx, field := range c.fields {
  353. isFirstField := idx == 0
  354. isEndField := idx == len(c.fields)-1
  355. fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField)
  356. for _, code := range fieldCodes {
  357. if c.isIndirect {
  358. code.Flags |= IndirectFlags
  359. }
  360. }
  361. firstField := fieldCodes.First()
  362. if len(codes) > 0 {
  363. codes.Last().Next = firstField
  364. firstField.Idx = codes.First().Idx
  365. }
  366. if prevField != nil {
  367. prevField.NextField = firstField
  368. }
  369. if isEndField {
  370. endField := fieldCodes.Last()
  371. if field.isAnonymous {
  372. firstField.End = endField
  373. lastField := c.lastAnonymousFieldCode(firstField)
  374. lastField.NextField = endField
  375. }
  376. if len(codes) > 0 {
  377. codes.First().End = endField
  378. } else {
  379. firstField.End = endField
  380. }
  381. codes = codes.Add(fieldCodes...)
  382. break
  383. }
  384. prevField = c.lastFieldCode(field, firstField)
  385. codes = codes.Add(fieldCodes...)
  386. }
  387. if len(codes) == 0 {
  388. head := &Opcode{
  389. Op: OpStructHead,
  390. Idx: opcodeOffset(ctx.ptrIndex),
  391. Type: c.typ,
  392. DisplayIdx: ctx.opcodeIndex,
  393. Indent: ctx.indent,
  394. }
  395. ctx.incOpcodeIndex()
  396. end := &Opcode{
  397. Op: OpStructEnd,
  398. Idx: opcodeOffset(ctx.ptrIndex),
  399. DisplayIdx: ctx.opcodeIndex,
  400. Indent: ctx.indent,
  401. }
  402. head.NextField = end
  403. head.Next = end
  404. head.End = end
  405. codes = codes.Add(head, end)
  406. ctx.incIndex()
  407. }
  408. ctx.decIndent()
  409. ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes
  410. return codes
  411. }
  412. func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
  413. // header => code => structField => code => end
  414. // ^ |
  415. // |__________|
  416. if c.isRecursive {
  417. recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
  418. recursive.Type = c.typ
  419. ctx.incIndex()
  420. *ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
  421. return Opcodes{recursive}
  422. }
  423. codes := Opcodes{}
  424. var prevField *Opcode
  425. for idx, field := range c.fields {
  426. isFirstField := idx == 0
  427. isEndField := idx == len(c.fields)-1
  428. fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField)
  429. for _, code := range fieldCodes {
  430. if c.isIndirect {
  431. code.Flags |= IndirectFlags
  432. }
  433. }
  434. firstField := fieldCodes.First()
  435. if len(codes) > 0 {
  436. codes.Last().Next = firstField
  437. firstField.Idx = codes.First().Idx
  438. }
  439. if prevField != nil {
  440. prevField.NextField = firstField
  441. }
  442. if isEndField {
  443. lastField := fieldCodes.Last()
  444. if len(codes) > 0 {
  445. codes.First().End = lastField
  446. } else {
  447. firstField.End = lastField
  448. }
  449. }
  450. prevField = firstField
  451. codes = codes.Add(fieldCodes...)
  452. }
  453. return codes
  454. }
  455. func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
  456. fields := make([]*StructFieldCode, 0, len(c.fields))
  457. for _, field := range c.fields {
  458. if field.isAnonymous {
  459. structCode := field.getAnonymousStruct()
  460. if structCode != nil && !structCode.isRecursive {
  461. structCode.removeFieldsByTags(tags)
  462. if len(structCode.fields) > 0 {
  463. fields = append(fields, field)
  464. }
  465. continue
  466. }
  467. }
  468. if tags.ExistsKey(field.key) {
  469. continue
  470. }
  471. fields = append(fields, field)
  472. }
  473. c.fields = fields
  474. }
  475. func (c *StructCode) enableIndirect() {
  476. if c.isIndirect {
  477. return
  478. }
  479. c.isIndirect = true
  480. if len(c.fields) == 0 {
  481. return
  482. }
  483. structCode := c.fields[0].getStruct()
  484. if structCode == nil {
  485. return
  486. }
  487. structCode.enableIndirect()
  488. }
  489. func (c *StructCode) Filter(query *FieldQuery) Code {
  490. fieldMap := map[string]*FieldQuery{}
  491. for _, field := range query.Fields {
  492. fieldMap[field.Name] = field
  493. }
  494. fields := make([]*StructFieldCode, 0, len(c.fields))
  495. for _, field := range c.fields {
  496. query, exists := fieldMap[field.key]
  497. if !exists {
  498. continue
  499. }
  500. fieldCode := &StructFieldCode{
  501. typ: field.typ,
  502. key: field.key,
  503. tag: field.tag,
  504. value: field.value,
  505. offset: field.offset,
  506. isAnonymous: field.isAnonymous,
  507. isTaggedKey: field.isTaggedKey,
  508. isNilableType: field.isNilableType,
  509. isNilCheck: field.isNilCheck,
  510. isAddrForMarshaler: field.isAddrForMarshaler,
  511. isNextOpPtrType: field.isNextOpPtrType,
  512. }
  513. if len(query.Fields) > 0 {
  514. fieldCode.value = fieldCode.value.Filter(query)
  515. }
  516. fields = append(fields, fieldCode)
  517. }
  518. return &StructCode{
  519. typ: c.typ,
  520. fields: fields,
  521. isPtr: c.isPtr,
  522. disableIndirectConversion: c.disableIndirectConversion,
  523. isIndirect: c.isIndirect,
  524. isRecursive: c.isRecursive,
  525. }
  526. }
  527. type StructFieldCode struct {
  528. typ *runtime.Type
  529. key string
  530. tag *runtime.StructTag
  531. value Code
  532. offset uintptr
  533. isAnonymous bool
  534. isTaggedKey bool
  535. isNilableType bool
  536. isNilCheck bool
  537. isAddrForMarshaler bool
  538. isNextOpPtrType bool
  539. isMarshalerContext bool
  540. }
  541. func (c *StructFieldCode) getStruct() *StructCode {
  542. value := c.value
  543. ptr, ok := value.(*PtrCode)
  544. if ok {
  545. value = ptr.value
  546. }
  547. structCode, ok := value.(*StructCode)
  548. if ok {
  549. return structCode
  550. }
  551. return nil
  552. }
  553. func (c *StructFieldCode) getAnonymousStruct() *StructCode {
  554. if !c.isAnonymous {
  555. return nil
  556. }
  557. return c.getStruct()
  558. }
  559. func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType {
  560. headType := code.ToHeaderType(tag.IsString)
  561. if tag.IsOmitEmpty {
  562. headType = headType.HeadToOmitEmptyHead()
  563. }
  564. return headType
  565. }
  566. func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType {
  567. fieldType := code.ToFieldType(tag.IsString)
  568. if tag.IsOmitEmpty {
  569. fieldType = fieldType.FieldToOmitEmptyField()
  570. }
  571. return fieldType
  572. }
  573. func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
  574. value := valueCodes.First()
  575. op := optimizeStructHeader(value, c.tag)
  576. field.Op = op
  577. if value.Flags&MarshalerContextFlags != 0 {
  578. field.Flags |= MarshalerContextFlags
  579. }
  580. field.NumBitSize = value.NumBitSize
  581. field.PtrNum = value.PtrNum
  582. field.FieldQuery = value.FieldQuery
  583. fieldCodes := Opcodes{field}
  584. if op.IsMultipleOpHead() {
  585. field.Next = value
  586. fieldCodes = fieldCodes.Add(valueCodes...)
  587. } else {
  588. ctx.decIndex()
  589. }
  590. return fieldCodes
  591. }
  592. func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
  593. value := valueCodes.First()
  594. op := optimizeStructField(value, c.tag)
  595. field.Op = op
  596. if value.Flags&MarshalerContextFlags != 0 {
  597. field.Flags |= MarshalerContextFlags
  598. }
  599. field.NumBitSize = value.NumBitSize
  600. field.PtrNum = value.PtrNum
  601. field.FieldQuery = value.FieldQuery
  602. fieldCodes := Opcodes{field}
  603. if op.IsMultipleOpField() {
  604. field.Next = value
  605. fieldCodes = fieldCodes.Add(valueCodes...)
  606. } else {
  607. ctx.decIndex()
  608. }
  609. return fieldCodes
  610. }
  611. func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes {
  612. end := &Opcode{
  613. Op: OpStructEnd,
  614. Idx: opcodeOffset(ctx.ptrIndex),
  615. DisplayIdx: ctx.opcodeIndex,
  616. Indent: ctx.indent,
  617. }
  618. codes.Last().Next = end
  619. codes.First().NextField = end
  620. codes = codes.Add(end)
  621. ctx.incOpcodeIndex()
  622. return codes
  623. }
  624. func (c *StructFieldCode) structKey(ctx *compileContext) string {
  625. if ctx.escapeKey {
  626. rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
  627. return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
  628. }
  629. return fmt.Sprintf(`"%s":`, c.key)
  630. }
  631. func (c *StructFieldCode) flags() OpFlags {
  632. var flags OpFlags
  633. if c.isTaggedKey {
  634. flags |= IsTaggedKeyFlags
  635. }
  636. if c.isNilableType {
  637. flags |= IsNilableTypeFlags
  638. }
  639. if c.isNilCheck {
  640. flags |= NilCheckFlags
  641. }
  642. if c.isAddrForMarshaler {
  643. flags |= AddrForMarshalerFlags
  644. }
  645. if c.isNextOpPtrType {
  646. flags |= IsNextOpPtrTypeFlags
  647. }
  648. if c.isAnonymous {
  649. flags |= AnonymousKeyFlags
  650. }
  651. if c.isMarshalerContext {
  652. flags |= MarshalerContextFlags
  653. }
  654. return flags
  655. }
  656. func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes {
  657. if c.isAnonymous {
  658. anonymCode, ok := c.value.(AnonymousCode)
  659. if ok {
  660. return anonymCode.ToAnonymousOpcode(ctx)
  661. }
  662. }
  663. return c.value.ToOpcode(ctx)
  664. }
  665. func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
  666. field := &Opcode{
  667. Idx: opcodeOffset(ctx.ptrIndex),
  668. Flags: c.flags(),
  669. Key: c.structKey(ctx),
  670. Offset: uint32(c.offset),
  671. Type: c.typ,
  672. DisplayIdx: ctx.opcodeIndex,
  673. Indent: ctx.indent,
  674. DisplayKey: c.key,
  675. }
  676. ctx.incIndex()
  677. valueCodes := c.toValueOpcodes(ctx)
  678. if isFirstField {
  679. codes := c.headerOpcodes(ctx, field, valueCodes)
  680. if isEndField {
  681. codes = c.addStructEndCode(ctx, codes)
  682. }
  683. return codes
  684. }
  685. codes := c.fieldOpcodes(ctx, field, valueCodes)
  686. if isEndField {
  687. if isEnableStructEndOptimization(c.value) {
  688. field.Op = field.Op.FieldToEnd()
  689. } else {
  690. codes = c.addStructEndCode(ctx, codes)
  691. }
  692. }
  693. return codes
  694. }
  695. func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
  696. field := &Opcode{
  697. Idx: opcodeOffset(ctx.ptrIndex),
  698. Flags: c.flags() | AnonymousHeadFlags,
  699. Key: c.structKey(ctx),
  700. Offset: uint32(c.offset),
  701. Type: c.typ,
  702. DisplayIdx: ctx.opcodeIndex,
  703. Indent: ctx.indent,
  704. DisplayKey: c.key,
  705. }
  706. ctx.incIndex()
  707. valueCodes := c.toValueOpcodes(ctx)
  708. if isFirstField {
  709. return c.headerOpcodes(ctx, field, valueCodes)
  710. }
  711. return c.fieldOpcodes(ctx, field, valueCodes)
  712. }
  713. func isEnableStructEndOptimization(value Code) bool {
  714. switch value.Kind() {
  715. case CodeKindInt,
  716. CodeKindUint,
  717. CodeKindFloat,
  718. CodeKindString,
  719. CodeKindBool,
  720. CodeKindBytes:
  721. return true
  722. case CodeKindPtr:
  723. return isEnableStructEndOptimization(value.(*PtrCode).value)
  724. default:
  725. return false
  726. }
  727. }
  728. type InterfaceCode struct {
  729. typ *runtime.Type
  730. fieldQuery *FieldQuery
  731. isPtr bool
  732. }
  733. func (c *InterfaceCode) Kind() CodeKind {
  734. return CodeKindInterface
  735. }
  736. func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes {
  737. var code *Opcode
  738. switch {
  739. case c.isPtr:
  740. code = newOpCode(ctx, c.typ, OpInterfacePtr)
  741. default:
  742. code = newOpCode(ctx, c.typ, OpInterface)
  743. }
  744. code.FieldQuery = c.fieldQuery
  745. if c.typ.NumMethod() > 0 {
  746. code.Flags |= NonEmptyInterfaceFlags
  747. }
  748. ctx.incIndex()
  749. return Opcodes{code}
  750. }
  751. func (c *InterfaceCode) Filter(query *FieldQuery) Code {
  752. return &InterfaceCode{
  753. typ: c.typ,
  754. fieldQuery: query,
  755. isPtr: c.isPtr,
  756. }
  757. }
  758. type MarshalJSONCode struct {
  759. typ *runtime.Type
  760. fieldQuery *FieldQuery
  761. isAddrForMarshaler bool
  762. isNilableType bool
  763. isMarshalerContext bool
  764. }
  765. func (c *MarshalJSONCode) Kind() CodeKind {
  766. return CodeKindMarshalJSON
  767. }
  768. func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes {
  769. code := newOpCode(ctx, c.typ, OpMarshalJSON)
  770. code.FieldQuery = c.fieldQuery
  771. if c.isAddrForMarshaler {
  772. code.Flags |= AddrForMarshalerFlags
  773. }
  774. if c.isMarshalerContext {
  775. code.Flags |= MarshalerContextFlags
  776. }
  777. if c.isNilableType {
  778. code.Flags |= IsNilableTypeFlags
  779. } else {
  780. code.Flags &= ^IsNilableTypeFlags
  781. }
  782. ctx.incIndex()
  783. return Opcodes{code}
  784. }
  785. func (c *MarshalJSONCode) Filter(query *FieldQuery) Code {
  786. return &MarshalJSONCode{
  787. typ: c.typ,
  788. fieldQuery: query,
  789. isAddrForMarshaler: c.isAddrForMarshaler,
  790. isNilableType: c.isNilableType,
  791. isMarshalerContext: c.isMarshalerContext,
  792. }
  793. }
  794. type MarshalTextCode struct {
  795. typ *runtime.Type
  796. fieldQuery *FieldQuery
  797. isAddrForMarshaler bool
  798. isNilableType bool
  799. }
  800. func (c *MarshalTextCode) Kind() CodeKind {
  801. return CodeKindMarshalText
  802. }
  803. func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes {
  804. code := newOpCode(ctx, c.typ, OpMarshalText)
  805. code.FieldQuery = c.fieldQuery
  806. if c.isAddrForMarshaler {
  807. code.Flags |= AddrForMarshalerFlags
  808. }
  809. if c.isNilableType {
  810. code.Flags |= IsNilableTypeFlags
  811. } else {
  812. code.Flags &= ^IsNilableTypeFlags
  813. }
  814. ctx.incIndex()
  815. return Opcodes{code}
  816. }
  817. func (c *MarshalTextCode) Filter(query *FieldQuery) Code {
  818. return &MarshalTextCode{
  819. typ: c.typ,
  820. fieldQuery: query,
  821. isAddrForMarshaler: c.isAddrForMarshaler,
  822. isNilableType: c.isNilableType,
  823. }
  824. }
  825. type PtrCode struct {
  826. typ *runtime.Type
  827. value Code
  828. ptrNum uint8
  829. }
  830. func (c *PtrCode) Kind() CodeKind {
  831. return CodeKindPtr
  832. }
  833. func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes {
  834. codes := c.value.ToOpcode(ctx)
  835. codes.First().Op = convertPtrOp(codes.First())
  836. codes.First().PtrNum = c.ptrNum
  837. return codes
  838. }
  839. func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
  840. var codes Opcodes
  841. anonymCode, ok := c.value.(AnonymousCode)
  842. if ok {
  843. codes = anonymCode.ToAnonymousOpcode(ctx)
  844. } else {
  845. codes = c.value.ToOpcode(ctx)
  846. }
  847. codes.First().Op = convertPtrOp(codes.First())
  848. codes.First().PtrNum = c.ptrNum
  849. return codes
  850. }
  851. func (c *PtrCode) Filter(query *FieldQuery) Code {
  852. return &PtrCode{
  853. typ: c.typ,
  854. value: c.value.Filter(query),
  855. ptrNum: c.ptrNum,
  856. }
  857. }
  858. func convertPtrOp(code *Opcode) OpType {
  859. ptrHeadOp := code.Op.HeadToPtrHead()
  860. if code.Op != ptrHeadOp {
  861. if code.PtrNum > 0 {
  862. // ptr field and ptr head
  863. code.PtrNum--
  864. }
  865. return ptrHeadOp
  866. }
  867. switch code.Op {
  868. case OpInt:
  869. return OpIntPtr
  870. case OpUint:
  871. return OpUintPtr
  872. case OpFloat32:
  873. return OpFloat32Ptr
  874. case OpFloat64:
  875. return OpFloat64Ptr
  876. case OpString:
  877. return OpStringPtr
  878. case OpBool:
  879. return OpBoolPtr
  880. case OpBytes:
  881. return OpBytesPtr
  882. case OpNumber:
  883. return OpNumberPtr
  884. case OpArray:
  885. return OpArrayPtr
  886. case OpSlice:
  887. return OpSlicePtr
  888. case OpMap:
  889. return OpMapPtr
  890. case OpMarshalJSON:
  891. return OpMarshalJSONPtr
  892. case OpMarshalText:
  893. return OpMarshalTextPtr
  894. case OpInterface:
  895. return OpInterfacePtr
  896. case OpRecursive:
  897. return OpRecursivePtr
  898. }
  899. return code.Op
  900. }