selfext.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
  2. // Use of this source code is governed by a MIT license found in the LICENSE file.
  3. package codec
  4. import "sync"
  5. // This extension expects that types registered with it implement SelfExt interface.
  6. //
  7. // This is used by libraries that support BytesExt e.g. cbor, json.
  8. var GlobalSelfInterfaceExt InterfaceExt = selfInterfaceExt{}
  9. // var selfExtEncPool = sync.Pool{
  10. // New: func() interface{} { return new(Encoder) },
  11. // }
  12. // var selfExtDecPool = sync.Pool{
  13. // New: func() interface{} { return new(Decoder) },
  14. // }
  15. // SelfExt is the interface that users implement so that their types
  16. // can, with minimal effort, be able to be an extension while allowing the
  17. // library handling the encoding/decoding needs easily.
  18. //
  19. // We now support the ability for an extension to define a tag,
  20. // but allow itself to be encoded in a default way.
  21. //
  22. // Because we use the type to determine how to encode or decode a value,
  23. // we cannot tell a value to just encode itself, as that will lead to an
  24. // infinite recursion.
  25. //
  26. // Instead, a value can define how it is to be encoded using a delegate value.
  27. //
  28. // If your types implement SelfExt, you can use this to define an extension.
  29. //
  30. // At encode time, the interface will call CodecConvertExt, and encode that value.
  31. // At decode time, the library will call CodecConvertExt, decode into that value, and
  32. // call the primary object's CodecUpdateExt with that value.
  33. //
  34. // The easiest way to do this is via struct embedding:
  35. //
  36. // type T struct {
  37. // tHelper
  38. // }
  39. // func (t *T) CodecConvertExt() { return &t.tHelper }
  40. // func (t *T) CodecUpdateExt(interface{}) { } // no-op (as our delegate is interior pointer)
  41. // type tHelper struct {
  42. // // ... all t fields
  43. // }
  44. //
  45. // Usage model:
  46. //
  47. // cborHandle.SetInterfaceExt(reflect.TypeOf(T), 122, codec.GlobalSelfInterfaceExt)
  48. //
  49. // msgpackHandle.SetBytesExt(reflect.TypeOf(T), 122, codec.NewSelfBytesExt(msgpackHandle, 1024))
  50. //
  51. type SelfExt interface {
  52. CodecConvertExt() interface{}
  53. CodecUpdateExt(interface{})
  54. }
  55. type selfBytesExt struct {
  56. // For performance and memory utilization, use sync.Pools
  57. // They all have to be local to the Ext, as the Ext is bound to a Handle.
  58. p sync.Pool // pool of byte buffers
  59. e sync.Pool
  60. d sync.Pool
  61. h Handle
  62. // bufcap int // cap for each byte buffer created
  63. }
  64. type selfInterfaceExt struct{}
  65. // NewSelfBytesExt will return a BytesExt implementation,
  66. // that will call an encoder to encode the value to a stream
  67. // so it can be placed into the encoder stream, and use a decoder
  68. // to do the same on the other end.
  69. //
  70. // Users can specify a buffer size, and we will initialize that
  71. // buffer for encoding the type. This allows users manage
  72. // how big the buffer is based on their knowledge of the type being
  73. // registered.
  74. //
  75. // This extension expects that types registered with it implement SelfExt interface.
  76. //
  77. // This is used by libraries that support BytesExt e.g. msgpack, binc.
  78. func NewSelfBytesExt(h Handle, bufcap int) *selfBytesExt {
  79. var v = selfBytesExt{h: h}
  80. v.p.New = func() interface{} {
  81. return make([]byte, 0, bufcap)
  82. }
  83. v.e.New = func() interface{} { return NewEncoderBytes(nil, v.h) }
  84. v.d.New = func() interface{} { return NewDecoderBytes(nil, v.h) }
  85. return &v
  86. }
  87. func (x *selfBytesExt) WriteExt(v interface{}) (s []byte) {
  88. ei := x.e.Get()
  89. bi := x.p.Get()
  90. defer func() {
  91. x.e.Put(ei)
  92. x.p.Put(bi)
  93. }()
  94. b := (bi.([]byte))[:0]
  95. e := ei.(*Encoder)
  96. e.ResetBytes(&b)
  97. e.MustEncode(v.(SelfExt).CodecConvertExt())
  98. if len(b) > 0 {
  99. s = make([]byte, len(b))
  100. copy(s, b)
  101. }
  102. return
  103. }
  104. func (x *selfBytesExt) ReadExt(dst interface{}, src []byte) {
  105. di := x.d.Get()
  106. d := di.(*Decoder)
  107. defer func() {
  108. d.Release()
  109. x.d.Put(di)
  110. }()
  111. d.ResetBytes(src)
  112. v := dst.(SelfExt).CodecConvertExt()
  113. d.MustDecode(v)
  114. dst.(SelfExt).CodecUpdateExt(v)
  115. return
  116. }
  117. func (x selfInterfaceExt) ConvertExt(v interface{}) interface{} {
  118. return v.(SelfExt).CodecConvertExt()
  119. }
  120. func (x selfInterfaceExt) UpdateExt(dst interface{}, src interface{}) {
  121. dst.(SelfExt).CodecUpdateExt(src)
  122. }