Ver Fonte

codec: Seperate BytesExt and InterfaceExt interfaces from Ext, and add impl methods to handles.

- Seperate BytesExt and InterfaceExt interfaces, and let Ext be a combo interface.
- Each Handle either exposes SetBytesExt or SetInterfaceExt (as appropriate for it).
- Create setExtWrapper for easy way to wrap either of these as an Ext.
- deprecated SetExt, along with previously deprecated AddExt.
Ugorji Nwoke há 10 anos atrás
pai
commit
6a9a8caa01
6 ficheiros alterados com 91 adições e 17 exclusões
  1. 5 0
      codec/binc.go
  2. 8 1
      codec/cbor.go
  3. 60 15
      codec/helper.go
  4. 5 0
      codec/json.go
  5. 5 0
      codec/msgpack.go
  6. 8 1
      codec/simple.go

+ 5 - 0
codec/binc.go

@@ -5,6 +5,7 @@ package codec
 
 import (
 	"math"
+	"reflect"
 	"time"
 )
 
@@ -905,5 +906,9 @@ func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
 	return &bincDecDriver{d: d, r: d.r, h: h, br: d.bytes}
 }
 
+func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
+	return h.SetExt(rt, tag, &setExtWrapper{b: ext})
+}
+
 var _ decDriver = (*bincDecDriver)(nil)
 var _ encDriver = (*bincEncDriver)(nil)

+ 8 - 1
codec/cbor.go

@@ -3,7 +3,10 @@
 
 package codec
 
-import "math"
+import (
+	"math"
+	"reflect"
+)
 
 const (
 	cborMajorUint byte = iota
@@ -566,5 +569,9 @@ func (h *CborHandle) newDecDriver(d *Decoder) decDriver {
 	return &cborDecDriver{d: d, r: d.r, h: h, br: d.bytes}
 }
 
+func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
+	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
+}
+
 var _ decDriver = (*cborDecDriver)(nil)
 var _ encDriver = (*cborEncDriver)(nil)

+ 60 - 15
codec/helper.go

@@ -309,32 +309,41 @@ type RawExt struct {
 	Value interface{}
 }
 
-// Ext handles custom (de)serialization of custom types / extensions.
-type Ext interface {
+// BytesExt handles custom (de)serialization of types to/from []byte.
+// It is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types.
+type BytesExt interface {
 	// WriteExt converts a value to a []byte.
-	// It is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types.
 	WriteExt(v interface{}) []byte
 
 	// ReadExt updates a value from a []byte.
-	// It is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types.
 	ReadExt(dst interface{}, src []byte)
+}
 
+// InterfaceExt handles custom (de)serialization of types to/from another interface{} value.
+// The Encoder or Decoder will then handle the further (de)serialization of that known type.
+//
+// It is used by codecs (e.g. cbor, json) which use the format to do custom serialization of the types.
+type InterfaceExt interface {
 	// ConvertExt converts a value into a simpler interface for easy encoding e.g. convert time.Time to int64.
-	// It is used by codecs (e.g. cbor) which use the format to do custom serialization of the types.
 	ConvertExt(v interface{}) interface{}
 
 	// UpdateExt updates a value from a simpler interface for easy decoding e.g. convert int64 to time.Time.
-	// It is used by codecs (e.g. cbor) which use the format to do custom serialization of the types.
 	UpdateExt(dst interface{}, src interface{})
 }
 
-// bytesExt is a wrapper implementation to support former AddExt exported method.
-type bytesExt struct {
+// Ext handles custom (de)serialization of custom types / extensions.
+type Ext interface {
+	BytesExt
+	InterfaceExt
+}
+
+// addExtWrapper is a wrapper implementation to support former AddExt exported method.
+type addExtWrapper struct {
 	encFn func(reflect.Value) ([]byte, error)
 	decFn func(reflect.Value, []byte) error
 }
 
-func (x bytesExt) WriteExt(v interface{}) []byte {
+func (x addExtWrapper) WriteExt(v interface{}) []byte {
 	// fmt.Printf(">>>>>>>>>> WriteExt: %T, %v\n", v, v)
 	bs, err := x.encFn(reflect.ValueOf(v))
 	if err != nil {
@@ -343,21 +352,57 @@ func (x bytesExt) WriteExt(v interface{}) []byte {
 	return bs
 }
 
-func (x bytesExt) ReadExt(v interface{}, bs []byte) {
+func (x addExtWrapper) ReadExt(v interface{}, bs []byte) {
 	// fmt.Printf(">>>>>>>>>> ReadExt: %T, %v\n", v, v)
 	if err := x.decFn(reflect.ValueOf(v), bs); err != nil {
 		panic(err)
 	}
 }
 
-func (x bytesExt) ConvertExt(v interface{}) interface{} {
+func (x addExtWrapper) ConvertExt(v interface{}) interface{} {
 	return x.WriteExt(v)
 }
 
-func (x bytesExt) UpdateExt(dest interface{}, v interface{}) {
+func (x addExtWrapper) UpdateExt(dest interface{}, v interface{}) {
 	x.ReadExt(dest, v.([]byte))
 }
 
+type setExtWrapper struct {
+	b BytesExt
+	i InterfaceExt
+}
+
+func (x *setExtWrapper) WriteExt(v interface{}) []byte {
+	if x.b == nil {
+		panic("BytesExt.WriteExt is not supported")
+	}
+	return x.b.WriteExt(v)
+}
+
+func (x *setExtWrapper) ReadExt(v interface{}, bs []byte) {
+	if x.b == nil {
+		panic("BytesExt.WriteExt is not supported")
+
+	}
+	x.b.ReadExt(v, bs)
+}
+
+func (x *setExtWrapper) ConvertExt(v interface{}) interface{} {
+	if x.i == nil {
+		panic("InterfaceExt.ConvertExt is not supported")
+
+	}
+	return x.i.ConvertExt(v)
+}
+
+func (x *setExtWrapper) UpdateExt(dest interface{}, v interface{}) {
+	if x.i == nil {
+		panic("InterfaceExxt.UpdateExt is not supported")
+
+	}
+	x.i.UpdateExt(dest, v)
+}
+
 // type errorString string
 // func (x errorString) Error() string { return string(x) }
 
@@ -412,7 +457,7 @@ type extTypeTagFn struct {
 
 type extHandle []*extTypeTagFn
 
-// DEPRECATED: AddExt is deprecated in favor of SetExt. It exists for compatibility only.
+// DEPRECATED: Use SetBytesExt or SetInterfaceExt on the Handle instead.
 //
 // AddExt registes an encode and decode function for a reflect.Type.
 // AddExt internally calls SetExt.
@@ -424,10 +469,10 @@ func (o *extHandle) AddExt(
 	if encfn == nil || decfn == nil {
 		return o.SetExt(rt, uint64(tag), nil)
 	}
-	return o.SetExt(rt, uint64(tag), bytesExt{encfn, decfn})
+	return o.SetExt(rt, uint64(tag), addExtWrapper{encfn, decfn})
 }
 
-// SetExt registers a tag and Ext for a reflect.Type.
+// DEPRECATED: Use SetBytesExt or SetInterfaceExt on the Handle instead.
 //
 // Note that the type must be a named type, and specifically not
 // a pointer or Interface. An error is returned if that is not honored.

+ 5 - 0
codec/json.go

@@ -36,6 +36,7 @@ import (
 	"bytes"
 	"encoding/base64"
 	"fmt"
+	"reflect"
 	"strconv"
 	"unicode/utf16"
 	"unicode/utf8"
@@ -1080,6 +1081,10 @@ func (h *JsonHandle) newDecDriver(d *Decoder) decDriver {
 	return &hd
 }
 
+func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
+	return h.SetExt(rt, tag, &setExtWrapper{i: ext})
+}
+
 var jsonEncodeTerminate = []byte{' '}
 
 func (h *JsonHandle) rpcEncodeTerminate() []byte {

+ 5 - 0
codec/msgpack.go

@@ -24,6 +24,7 @@ import (
 	"io"
 	"math"
 	"net/rpc"
+	"reflect"
 )
 
 const (
@@ -726,6 +727,10 @@ func (h *MsgpackHandle) newDecDriver(d *Decoder) decDriver {
 	return &msgpackDecDriver{d: d, r: d.r, h: h, br: d.bytes}
 }
 
+func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
+	return h.SetExt(rt, tag, &setExtWrapper{b: ext})
+}
+
 //--------------------------------------------------
 
 type msgpackSpecRpcCodec struct {

+ 8 - 1
codec/simple.go

@@ -3,7 +3,10 @@
 
 package codec
 
-import "math"
+import (
+	"math"
+	"reflect"
+)
 
 const (
 	_               uint8 = iota
@@ -501,5 +504,9 @@ func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
 	return &simpleDecDriver{d: d, r: d.r, h: h, br: d.bytes}
 }
 
+func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
+	return h.SetExt(rt, tag, &setExtWrapper{b: ext})
+}
+
 var _ decDriver = (*simpleDecDriver)(nil)
 var _ encDriver = (*simpleEncDriver)(nil)