From 2f44c9f5c9bf72927313d35e4dfaa478711943fb Mon Sep 17 00:00:00 2001 From: Pavel Gabriel Date: Mon, 11 Sep 2023 16:05:48 +0200 Subject: [PATCH] implement unmarshal --- exp_test.go | 39 +++++++++++++++++++++++++++++++++++++++ field/composite_test.go | 2 +- field/string.go | 37 +++++++++++++++++++++++++++---------- message.go | 16 ++++++++++++---- 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/exp_test.go b/exp_test.go index 970358c..4e88c61 100644 --- a/exp_test.go +++ b/exp_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/moov-io/iso8583" + "github.com/moov-io/iso8583/field" "github.com/moov-io/iso8583/specs" "github.com/stretchr/testify/require" ) @@ -164,4 +165,42 @@ func TestStructWithTypes(t *testing.T) { }) } }) + + t.Run("unpack", func(t *testing.T) { + type authRequest struct { + MTI string `index:"0"` + PrimaryAccountNumber string `index:"2"` + } + + packed := []byte("011040000000000000000000000000000000164242424242424242") + + message := iso8583.NewMessage(specs.Spec87ASCII) + err := message.Unpack(packed) + require.NoError(t, err) + + data := authRequest{} + err = message.Unmarshal(&data) + require.NoError(t, err) + require.Equal(t, "0110", data.MTI) + require.Equal(t, "4242424242424242", data.PrimaryAccountNumber) + }) + + t.Run("unpack2", func(t *testing.T) { + type authRequest struct { + MTI *string `index:"0"` + PrimaryAccountNumber *field.String `index:"2"` + } + + packed := []byte("011040000000000000000000000000000000164242424242424242") + + message := iso8583.NewMessage(specs.Spec87ASCII) + err := message.Unpack(packed) + require.NoError(t, err) + + data := authRequest{} + err = message.Unmarshal(&data) + require.NoError(t, err) + require.Equal(t, "0110", *data.MTI) + require.Equal(t, "4242424242424242", data.PrimaryAccountNumber.Value()) + }) } diff --git a/field/composite_test.go b/field/composite_test.go index 83e0ea7..f789adb 100644 --- a/field/composite_test.go +++ b/field/composite_test.go @@ -745,7 +745,7 @@ func TestCompositePacking(t *testing.T) { err = composite.Unmarshal(data) require.Error(t, err) - require.EqualError(t, err, "failed to get data from field 1: data does not match required *String type") + require.Contains(t, err.Error(), "failed to get data from field 1: data does not match required *String") }) t.Run("Unpack returns an error on failure of subfield to unpack bytes", func(t *testing.T) { diff --git a/field/string.go b/field/string.go index 0640390..598712d 100644 --- a/field/string.go +++ b/field/string.go @@ -2,8 +2,8 @@ package field import ( "encoding/json" - "errors" "fmt" + "reflect" "strconv" "github.com/moov-io/iso8583/utils" @@ -111,17 +111,34 @@ func (f *String) Unpack(data []byte) (int, error) { } func (f *String) Unmarshal(v interface{}) error { - if v == nil { - return nil - } - - str, ok := v.(*String) - if !ok { - return errors.New("data does not match required *String type") + switch val := v.(type) { + case reflect.Value: + switch val.Kind() { + case reflect.String: + val.SetString(f.value) + case reflect.Int: + i, err := strconv.Atoi(f.value) + if err != nil { + return fmt.Errorf("failed to convert string to int: %w", err) + } + val.SetInt(int64(i)) + default: + return fmt.Errorf("data does not match required reflect.Value type") + } + case *string: + *val = f.value + case *int: + i, err := strconv.Atoi(f.value) + if err != nil { + return fmt.Errorf("failed to convert string to int: %w", err) + } + *val = i + case *String: + val.value = f.value + default: + return fmt.Errorf("data does not match required *String or *string type") } - str.value = f.value - return nil } diff --git a/message.go b/message.go index 7cd406c..59bb884 100644 --- a/message.go +++ b/message.go @@ -433,11 +433,19 @@ func (m *Message) Unmarshal(v interface{}) error { } dataField := dataStruct.Field(i) - if dataField.IsNil() { - dataField.Set(reflect.New(dataField.Type().Elem())) - } - err = messageField.Unmarshal(dataField.Interface()) + // if field is pointer we will pass pointer to the field + if dataField.Kind() == reflect.Ptr { + if dataField.IsZero() { + fmt.Println("is zero") + dataField.Set(reflect.New(dataField.Type().Elem())) + } + + err = messageField.Unmarshal(dataField.Interface()) + } else { + // if field is not pointer we will pass the field as reflect.Value + err = messageField.Unmarshal(dataField) + } if err != nil { return fmt.Errorf("failed to get value from field %d: %w", fieldIndex, err) }