Skip to content

Commit

Permalink
code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mfdeveloper508 committed Oct 5, 2023
1 parent 5e2af56 commit 71af4bf
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 90 deletions.
16 changes: 1 addition & 15 deletions field/composite.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import (
"fmt"
"math"
"reflect"
"regexp"
"strconv"
"sync"

"github.com/moov-io/iso8583/encoding"
"github.com/moov-io/iso8583/prefix"
"github.com/moov-io/iso8583/sort"

"github.com/moov-io/iso8583/utils"
)

Expand Down Expand Up @@ -676,21 +674,9 @@ func orderedKeys(kvs map[string]Field, sorter sort.StringSlice) []string {
return keys
}

var fieldNameTagRe = regexp.MustCompile(`^F.+$`)

// getFieldIndexOrTag returns index or tag of the field. First, it checks the
// field name. If it does not match F.+ pattern, it checks value of `index`
// tag. If empty string, then index/tag was not found for the field.
func getFieldIndexOrTag(field reflect.StructField) (string, error) {
dataFieldName := field.Name

if fieldIndex := field.Tag.Get("index"); fieldIndex != "" {
return fieldIndex, nil
}

if len(dataFieldName) > 0 && fieldNameTagRe.MatchString(dataFieldName) {
return dataFieldName[1:], nil
}

return "", nil
return NewIndexTag(field).Tag, nil
}
5 changes: 4 additions & 1 deletion index_tag.go → field/index_tag.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package iso8583
package field

import (
"reflect"
"regexp"
"strconv"
"strings"
)

var fieldNameIndexRe = regexp.MustCompile(`^F.+$`)

type IndexTag struct {
Id int // is -1 if index is not a number

Expand Down
57 changes: 11 additions & 46 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"reflect"
"regexp"
"sort"
"strconv"
"sync"
Expand Down Expand Up @@ -427,7 +426,7 @@ func (m *Message) Marshal(v interface{}) error {

// iterate over struct fields
for i := 0; i < dataStruct.NumField(); i++ {
indexTag := NewIndexTag(dataStruct.Type().Field(i))
indexTag := field.NewIndexTag(dataStruct.Type().Field(i))

// skip field without index or if index in tag is not defined
if indexTag.Id < 0 {
Expand Down Expand Up @@ -486,23 +485,19 @@ func (m *Message) Unmarshal(v interface{}) error {

// iterate over struct fields
for i := 0; i < dataStruct.NumField(); i++ {
fieldIndex, err := getFieldIndex(dataStruct.Type().Field(i))
if err != nil {
return fmt.Errorf("getting field %d index: %w", i, err)
}

// skip field without index
if fieldIndex < 0 {
continue
indexTag := field.NewIndexTag(dataStruct.Type().Field(i))
// skip field without index or if index in tag is not defined
if indexTag.Id < 0 {
return fmt.Errorf("getting field %d index error", i)
}

// we can get data only if field value is set
messageField := m.GetField(fieldIndex)
messageField := m.GetField(indexTag.Id)
if messageField == nil {
continue
}

if _, set := m.fieldsMap[fieldIndex]; !set {
if _, set := m.fieldsMap[indexTag.Id]; !set {
continue
}

Expand All @@ -512,47 +507,17 @@ func (m *Message) Unmarshal(v interface{}) error {
if dataField.IsNil() || dataField.IsZero() {
dataField.Set(reflect.New(dataField.Type().Elem()))
}
err = messageField.Unmarshal(dataField.Interface())
err := messageField.Unmarshal(dataField.Interface())
if err != nil {
return fmt.Errorf("failed to get value from field %d: %w", fieldIndex, err)
return fmt.Errorf("failed to get value from field %d: %w", indexTag.Id, err)
}
default: // Native types
err = messageField.Unmarshal(dataField)
err := messageField.Unmarshal(dataField)
if err != nil {
return fmt.Errorf("failed to get value from field %d: %w", fieldIndex, err)
return fmt.Errorf("failed to get value from field %d: %w", indexTag.Id, err)
}
}
}

return nil
}

var fieldNameIndexRe = regexp.MustCompile(`^F\d+$`)

// fieldIndex returns index of the field. First, it checks field name. If it
// does not match FNN (when NN is digits), it checks value of `index` tag. If
// negative value returned (-1) then index was not found for the field.
func getFieldIndex(field reflect.StructField) (int, error) {
dataFieldName := field.Name

if indexStr := field.Tag.Get("index"); indexStr != "" {
fieldIndex, err := strconv.Atoi(indexStr)
if err != nil {
return -1, fmt.Errorf("converting field index into int: %w", err)
}

return fieldIndex, nil
}

if len(dataFieldName) > 0 && fieldNameIndexRe.MatchString(dataFieldName) {
indexStr := dataFieldName[1:]
fieldIndex, err := strconv.Atoi(indexStr)
if err != nil {
return -1, fmt.Errorf("converting field index into int: %w", err)
}

return fieldIndex, nil
}

return -1, nil
}
42 changes: 14 additions & 28 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1415,21 +1415,17 @@ func Test_getFieldIndex(t *testing.T) {
F1 string
}{}).Elem()

index, err := getFieldIndex(st.Type().Field(0))

require.NoError(t, err)
require.Equal(t, 1, index)
indexTag := field.NewIndexTag(st.Type().Field(0))
require.Equal(t, 1, indexTag.Id)
})

t.Run("returns index from field tag instead of field name when both match", func(t *testing.T) {
st := reflect.ValueOf(&struct {
F1 string `index:"2"`
}{}).Elem()

index, err := getFieldIndex(st.Type().Field(0))

require.NoError(t, err)
require.Equal(t, 2, index)
indexTag := field.NewIndexTag(st.Type().Field(0))
require.Equal(t, 2, indexTag.Id)
})

t.Run("returns index from field tag", func(t *testing.T) {
Expand All @@ -1440,43 +1436,33 @@ func Test_getFieldIndex(t *testing.T) {
}{}).Elem()

// get index from field Name
_, err := getFieldIndex(st.Type().Field(0))

require.Error(t, err)
require.EqualError(t, err, "converting field index into int: strconv.Atoi: parsing \"abcd\": invalid syntax")
indexTag := field.NewIndexTag(st.Type().Field(0))
require.Equal(t, -1, indexTag.Id)

// get index from field F
index, err := getFieldIndex(st.Type().Field(1))

require.NoError(t, err)
require.Equal(t, 2, index)
indexTag = field.NewIndexTag(st.Type().Field(1))
require.Equal(t, 2, indexTag.Id)

// get index from field Amount
index, err = getFieldIndex(st.Type().Field(2))

require.NoError(t, err)
require.Equal(t, 3, index)
indexTag = field.NewIndexTag(st.Type().Field(2))
require.Equal(t, 3, indexTag.Id)
})

t.Run("returns empty string when no tag and field name does not match the pattern", func(t *testing.T) {
st := reflect.ValueOf(&struct {
Name string
}{}).Elem()

index, err := getFieldIndex(st.Type().Field(0))

require.NoError(t, err)
require.Equal(t, -1, index)
indexTag := field.NewIndexTag(st.Type().Field(0))
require.Equal(t, -1, indexTag.Id)

// single letter field without tag is ignored
st = reflect.ValueOf(&struct {
F string
}{}).Elem()

index, err = getFieldIndex(st.Type().Field(0))

require.NoError(t, err)
require.Equal(t, -1, index)
indexTag = field.NewIndexTag(st.Type().Field(0))
require.Equal(t, -1, indexTag.Id)
})
}

Expand Down

0 comments on commit 71af4bf

Please sign in to comment.