diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..3a63def --- /dev/null +++ b/errors.go @@ -0,0 +1,28 @@ +package iso8583 + +// UnpackError returns error with possibility to access RawMessage when +// connection failed to unpack message +type UnpackError struct { + Err error + RawMessage []byte +} + +func (e *UnpackError) Error() string { + return e.Err.Error() +} + +func (e *UnpackError) Unwrap() error { + return e.Err +} + +type PackError struct { + Err error +} + +func (e *PackError) Error() string { + return e.Err.Error() +} + +func (e *PackError) Unwrap() error { + return e.Err +} diff --git a/message.go b/message.go index 87a192d..87e07a4 100644 --- a/message.go +++ b/message.go @@ -126,7 +126,18 @@ func (m *Message) GetFields() map[int]field.Field { return fields } +// Pack returns the packed message or an error if the message is invalid +// error is of type *PackError func (m *Message) Pack() ([]byte, error) { + data, err := m.pack() + if err != nil { + return nil, &PackError{Err: err} + } + + return data, nil +} + +func (m *Message) pack() ([]byte, error) { packed := []byte{} m.Bitmap().Reset() @@ -160,7 +171,19 @@ func (m *Message) Pack() ([]byte, error) { return packed, nil } +// Unpack unpacks the message from the given byte slice or returns an error +// error is of type *UnpackError and contains the raw message func (m *Message) Unpack(src []byte) error { + if err := m.unpack(src); err != nil { + return &UnpackError{ + Err: err, + RawMessage: src, + } + } + return nil +} + +func (m *Message) unpack(src []byte) error { var off int // reset fields that were set diff --git a/message_test.go b/message_test.go index 05c8476..f764e57 100644 --- a/message_test.go +++ b/message_test.go @@ -535,12 +535,26 @@ func TestPackUnpack(t *testing.T) { assert.Equal(t, "Another test text", data.F120.Value()) }) + t.Run("Pack invalid message returns error of *PackError type", func(t *testing.T) { + message := NewMessage(spec) + message.MTI("1") + + _, err := message.Pack() + require.Error(t, err) + + var packErr *PackError + require.ErrorAs(t, err, &packErr) + }) + t.Run("Unpack nil", func(t *testing.T) { message := NewMessage(spec) err := message.Unpack(nil) require.Error(t, err) + + var unpackError *UnpackError + require.ErrorAs(t, err, &unpackError) }) t.Run("Unpack short mti", func(t *testing.T) { @@ -551,6 +565,10 @@ func TestPackUnpack(t *testing.T) { err := message.Unpack([]byte(rawMsg)) require.Error(t, err) + + var unpackError *UnpackError + require.ErrorAs(t, err, &unpackError) + require.Equal(t, rawMsg, unpackError.RawMessage) }) // this test should check that BCD fields are packed and