encode_map.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright (c) Faye Amacker. All rights reserved.
  2. // Licensed under the MIT License. See LICENSE in the project root for license information.
  3. package cbor
  4. import (
  5. "bytes"
  6. "reflect"
  7. "sync"
  8. )
  9. type mapKeyValueEncodeFunc struct {
  10. kf, ef encodeFunc
  11. kpool, vpool sync.Pool
  12. }
  13. func (me *mapKeyValueEncodeFunc) encodeKeyValues(e *bytes.Buffer, em *encMode, v reflect.Value, kvs []keyValue) error {
  14. iterk := me.kpool.Get().(*reflect.Value)
  15. defer func() {
  16. iterk.SetZero()
  17. me.kpool.Put(iterk)
  18. }()
  19. iterv := me.vpool.Get().(*reflect.Value)
  20. defer func() {
  21. iterv.SetZero()
  22. me.vpool.Put(iterv)
  23. }()
  24. if kvs == nil {
  25. for i, iter := 0, v.MapRange(); iter.Next(); i++ {
  26. iterk.SetIterKey(iter)
  27. iterv.SetIterValue(iter)
  28. if err := me.kf(e, em, *iterk); err != nil {
  29. return err
  30. }
  31. if err := me.ef(e, em, *iterv); err != nil {
  32. return err
  33. }
  34. }
  35. return nil
  36. }
  37. initial := e.Len()
  38. for i, iter := 0, v.MapRange(); iter.Next(); i++ {
  39. iterk.SetIterKey(iter)
  40. iterv.SetIterValue(iter)
  41. offset := e.Len()
  42. if err := me.kf(e, em, *iterk); err != nil {
  43. return err
  44. }
  45. valueOffset := e.Len()
  46. if err := me.ef(e, em, *iterv); err != nil {
  47. return err
  48. }
  49. kvs[i] = keyValue{
  50. offset: offset - initial,
  51. valueOffset: valueOffset - initial,
  52. nextOffset: e.Len() - initial,
  53. }
  54. }
  55. return nil
  56. }
  57. func getEncodeMapFunc(t reflect.Type) encodeFunc {
  58. kf, _, _ := getEncodeFunc(t.Key())
  59. ef, _, _ := getEncodeFunc(t.Elem())
  60. if kf == nil || ef == nil {
  61. return nil
  62. }
  63. mkv := &mapKeyValueEncodeFunc{
  64. kf: kf,
  65. ef: ef,
  66. kpool: sync.Pool{
  67. New: func() any {
  68. rk := reflect.New(t.Key()).Elem()
  69. return &rk
  70. },
  71. },
  72. vpool: sync.Pool{
  73. New: func() any {
  74. rv := reflect.New(t.Elem()).Elem()
  75. return &rv
  76. },
  77. },
  78. }
  79. return mapEncodeFunc{
  80. e: mkv.encodeKeyValues,
  81. }.encode
  82. }