You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2017/01/18 00:52:00 UTC

[3/3] qpid-proton git commit: NO-JIRA: Clean up marshal/unmarshal error handling

NO-JIRA: Clean up marshal/unmarshal error handling


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/eafd0810
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/eafd0810
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/eafd0810

Branch: refs/heads/master
Commit: eafd08104e232c911686b05f419a3c970706a554
Parents: 0f156d7
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Jan 17 16:16:23 2017 -0500
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Jan 17 19:43:58 2017 -0500

----------------------------------------------------------------------
 .../go/src/qpid.apache.org/amqp/marshal.go      | 41 ++++++++++++-----
 .../go/src/qpid.apache.org/amqp/unmarshal.go    | 46 ++++++++++++--------
 2 files changed, 59 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eafd0810/proton-c/bindings/go/src/qpid.apache.org/amqp/marshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/marshal.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/marshal.go
index e3d4e10..b6adf90 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/marshal.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/marshal.go
@@ -29,12 +29,25 @@ import (
 	"unsafe"
 )
 
-func dataError(prefix string, data *C.pn_data_t) error {
-	err := PnError(C.pn_data_error(data))
-	if err != nil {
-		err = fmt.Errorf("%s: %s", prefix, err.Error())
+// Error returned if Go data cannot be marshaled as an AMQP type.
+type MarshalError struct {
+	// The Go type.
+	GoType reflect.Type
+	s      string
+}
+
+func (e MarshalError) Error() string { return e.s }
+
+func newMarshalError(v interface{}, s string) *MarshalError {
+	t := reflect.TypeOf(v)
+	return &MarshalError{GoType: t, s: fmt.Sprintf("cannot marshal %s: %s", t, s)}
+}
+
+func dataMarshalError(v interface{}, data *C.pn_data_t) error {
+	if pe := PnError(C.pn_data_error(data)); pe != nil {
+		return newMarshalError(v, pe.Error())
 	}
-	return err
+	return nil
 }
 
 /*
@@ -87,7 +100,16 @@ Described types.
 
 */
 func Marshal(v interface{}, buffer []byte) (outbuf []byte, err error) {
-	defer doRecover(&err)
+	defer func() {
+		if r := recover(); r != nil {
+			if merr, ok := r.(*MarshalError); ok {
+				err = merr
+			} else {
+				panic(r)
+			}
+		}
+	}()
+
 	data := C.pn_data(0)
 	defer C.pn_data_free(data)
 	marshal(v, data)
@@ -97,7 +119,7 @@ func Marshal(v interface{}, buffer []byte) (outbuf []byte, err error) {
 		case n == int(C.PN_OVERFLOW):
 			return buf, overflow
 		case n < 0:
-			return buf, dataError("marshal error", data)
+			return buf, dataMarshalError(v, data)
 		default:
 			return buf[:n], nil
 		}
@@ -189,11 +211,10 @@ func marshal(v interface{}, data *C.pn_data_t) {
 		case reflect.Slice:
 			putList(data, v)
 		default:
-			panic(fmt.Errorf("cannot marshal %s to AMQP", reflect.TypeOf(v)))
+			panic(newMarshalError(v, "no conversion"))
 		}
 	}
-	err := dataError("marshal", data)
-	if err != nil {
+	if err := dataMarshalError(v, data); err != nil {
 		panic(err)
 	}
 	return

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eafd0810/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
index 9b9cfd3..d56cbd2 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
@@ -38,28 +38,39 @@ type UnmarshalError struct {
 	AMQPType string
 	// The Go type.
 	GoType reflect.Type
-}
 
-func newUnmarshalError(pnType C.pn_type_t, v interface{}) *UnmarshalError {
-	return &UnmarshalError{C.pn_type_t(pnType).String(), reflect.TypeOf(v)}
+	s string
 }
 
-func (e UnmarshalError) Error() string {
+func (e UnmarshalError) Error() string { return e.s }
+
+func newUnmarshalError(pnType C.pn_type_t, v interface{}) *UnmarshalError {
+	e := &UnmarshalError{AMQPType: C.pn_type_t(pnType).String(), GoType: reflect.TypeOf(v)}
 	if e.GoType.Kind() != reflect.Ptr {
-		return fmt.Sprintf("cannot unmarshal to type %s, not a pointer", e.GoType)
+		e.s = fmt.Sprintf("cannot unmarshal to type %s, not a pointer", e.GoType)
 	} else {
-		return fmt.Sprintf("cannot unmarshal AMQP %s to %s", e.AMQPType, e.GoType)
+		e.s = fmt.Sprintf("cannot unmarshal AMQP %s to %s", e.AMQPType, e.GoType)
 	}
+	return e
 }
 
-func doRecover(err *error) {
-	r := recover()
-	switch r := r.(type) {
-	case nil:
-	case *UnmarshalError:
-		*err = r
-	default:
-		panic(r)
+func newUnmarshalErrorData(data *C.pn_data_t, v interface{}) *UnmarshalError {
+	err := PnError(C.pn_data_error(data))
+	if err == nil {
+		return nil
+	}
+	e := newUnmarshalError(C.pn_data_type(data), v)
+	e.s = e.s + ": " + err.Error()
+	return e
+}
+
+func recoverUnmarshal(err *error) {
+	if r := recover(); r != nil {
+		if uerr, ok := r.(*UnmarshalError); ok {
+			*err = uerr
+		} else {
+			panic(r)
+		}
 	}
 }
 
@@ -99,7 +110,7 @@ func (d *Decoder) Buffered() io.Reader {
 // See the documentation for Unmarshal for details about the conversion of AMQP into a Go value.
 //
 func (d *Decoder) Decode(v interface{}) (err error) {
-	defer doRecover(&err)
+	defer recoverUnmarshal(&err)
 	data := C.pn_data(0)
 	defer C.pn_data_free(data)
 	var n int
@@ -181,7 +192,7 @@ AMQP maps with mixed/unhashable key types need an alternate representation.
 Described types.
 */
 func Unmarshal(bytes []byte, v interface{}) (n int, err error) {
-	defer doRecover(&err)
+	defer recoverUnmarshal(&err)
 
 	data := C.pn_data(0)
 	defer C.pn_data_free(data)
@@ -433,8 +444,7 @@ func unmarshal(v interface{}, data *C.pn_data_t) {
 			panic(newUnmarshalError(pnType, v))
 		}
 	}
-	err := dataError("unmarshaling", data)
-	if err != nil {
+	if err := newUnmarshalErrorData(data, v); err != nil {
 		panic(err)
 	}
 	return


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org