Skip to content

Commit

Permalink
deprecate setdata method for fields, update unmarshal/marshal functions
Browse files Browse the repository at this point in the history
  • Loading branch information
mfdeveloper508 committed Sep 27, 2023
1 parent b05481c commit d8c9fe2
Show file tree
Hide file tree
Showing 18 changed files with 778 additions and 238 deletions.
106 changes: 76 additions & 30 deletions field/binary.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package field

import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"reflect"

"github.com/moov-io/iso8583/encoding"
"github.com/moov-io/iso8583/utils"
Expand All @@ -16,7 +17,6 @@ var _ json.Unmarshaler = (*Binary)(nil)
type Binary struct {
value []byte
spec *Spec
data *Binary
}

func NewBinary(spec *Spec) *Binary {
Expand All @@ -41,9 +41,6 @@ func (f *Binary) SetSpec(spec *Spec) {

func (f *Binary) SetBytes(b []byte) error {
f.value = b
if f.data != nil {
*(f.data) = *f
}
return nil
}

Expand Down Expand Up @@ -114,42 +111,91 @@ func (f *Binary) Unpack(data []byte) (int, error) {
return read + prefBytes, nil
}

func (f *Binary) Unmarshal(v interface{}) error {
if v == nil {
return nil
}
// Deprecated. Use Marshal intead.
func (f *Binary) SetData(data interface{}) error {
return f.Marshal(data)
}

bin, ok := v.(*Binary)
if !ok {
return errors.New("data does not match required *Binary type")
func (f *Binary) Unmarshal(v interface{}) error {
switch val := v.(type) {
case reflect.Value:
switch val.Kind() {
case reflect.String:
if !val.CanSet() {
return fmt.Errorf("reflect.Value of the data can not be change")
}

str := hex.EncodeToString(f.value)
val.SetString(str)
case reflect.Slice:
if !val.CanSet() {
return fmt.Errorf("reflect.Value of the data can not be change")
}

val.SetBytes(f.value)
default:
return fmt.Errorf("data does not match required reflect.Value type")
}
case *string:
str := hex.EncodeToString(f.value)
*val = str
case *[]byte:
*val = f.value
case *Binary:
val.value = f.value
default:
return fmt.Errorf("data does not match required *Binary or (*string, *[]byte) type")
}

bin.value = f.value

return nil
}

func (f *Binary) SetData(data interface{}) error {
if data == nil {
return nil
}

bin, ok := data.(*Binary)
if !ok {
return errors.New("data does not match required *Binary type")
func (f *Binary) Marshal(v interface{}) error {
switch v := v.(type) {
case *Binary:
if v == nil {
return nil
}
f.value = v.value
case string:
if v == "" {
f.value = nil
return nil
}

buf, err := hex.DecodeString(v)
if err != nil {
return fmt.Errorf("failed to convert string to byte: %w", err)
}

f.value = buf
case *string:
if v == nil {
f.value = nil
return nil
}

buf, err := hex.DecodeString(*v)
if err != nil {
return fmt.Errorf("failed to convert string to byte: %w", err)
}

f.value = buf
case []byte:
f.SetBytes(v)
case *[]byte:
if v == nil {
f.value = nil
return nil
}
f.SetBytes(*v)
default:
return fmt.Errorf("data does not match required *Binary or (string, *string, []byte, *[]byte) type")
}

f.data = bin
if bin.value != nil {
f.value = bin.value
}
return nil
}

func (f *Binary) Marshal(data interface{}) error {
return f.SetData(data)
}

func (f *Binary) MarshalJSON() ([]byte, error) {
str, err := f.String()
if err != nil {
Expand Down
81 changes: 76 additions & 5 deletions field/binary_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package field

import (
"reflect"
"testing"

"github.com/moov-io/iso8583/encoding"
Expand Down Expand Up @@ -50,7 +51,7 @@ func TestBinaryField(t *testing.T) {

t.Run("SetData sets data to the field", func(t *testing.T) {
bin := NewBinary(spec)
bin.SetData(NewBinaryValue(in))
bin.Marshal(NewBinaryValue(in))

packed, err := bin.Pack()

Expand All @@ -71,12 +72,12 @@ func TestBinaryField(t *testing.T) {
t.Run("SetBytes sets data to the data field", func(t *testing.T) {
bin := NewBinary(spec)
data := &Binary{}
bin.SetData(data)
bin.Marshal(data)

err := bin.SetBytes(in)
require.NoError(t, err)

require.Equal(t, in, data.value)
require.Equal(t, in, bin.value)
})

// SetValue sets data to the data field
Expand All @@ -90,13 +91,13 @@ func TestBinaryField(t *testing.T) {
t.Run("Unpack sets data to data value", func(t *testing.T) {
bin := NewBinary(spec)
data := NewBinaryValue([]byte{})
bin.SetData(data)
bin.Marshal(data)

n, err := bin.Unpack(in)

require.NoError(t, err)
require.Equal(t, len(in), n)
require.Equal(t, in, data.value)
require.Equal(t, in, bin.value)
})

t.Run("UnmarshalJSON unquotes input before handling it", func(t *testing.T) {
Expand Down Expand Up @@ -140,3 +141,73 @@ func TestBinaryNil(t *testing.T) {
bs = str.Value()
require.Nil(t, bs)
}

func TestBinaryFieldUnmarshal(t *testing.T) {
testValue := []byte{0x12, 0x34, 0x56}
str := NewBinaryValue(testValue)

val1 := &Binary{}
err := str.Unmarshal(val1)
require.NoError(t, err)
require.Equal(t, testValue, val1.Value())

var val2 string
err = str.Unmarshal(&val2)
require.NoError(t, err)
require.Equal(t, "123456", val2)

var val3 []byte
err = str.Unmarshal(&val3)
require.NoError(t, err)
require.Equal(t, testValue, val3)

val4 := reflect.ValueOf(&val2).Elem()
err = str.Unmarshal(val4)
require.NoError(t, err)
require.Equal(t, "123456", val4.String())

val5 := reflect.ValueOf(&val3).Elem()
err = str.Unmarshal(val5)
require.NoError(t, err)
require.Equal(t, testValue, val5.Bytes())

val6 := reflect.ValueOf(val2)
err = str.Unmarshal(val6)
require.Error(t, err)
require.Equal(t, "reflect.Value of the data can not be change", err.Error())

val7 := reflect.ValueOf(&val2)
err = str.Unmarshal(val7)
require.Error(t, err)
require.Equal(t, "data does not match required reflect.Value type", err.Error())

err = str.Unmarshal(nil)
require.Error(t, err)
require.Equal(t, "data does not match required *Binary or (*string, *[]byte) type", err.Error())
}

func TestBinaryFieldMarshal(t *testing.T) {
testValue := []byte{0x12, 0x34, 0x56}
str := NewBinaryValue(nil)

vstring := "123456"
err := str.Marshal(vstring)
require.NoError(t, err)
require.Equal(t, testValue, str.Value())

err = str.Marshal(&vstring)
require.NoError(t, err)
require.Equal(t, testValue, str.Value())

err = str.Marshal(testValue)
require.NoError(t, err)
require.Equal(t, testValue, str.Value())

err = str.Marshal(&testValue)
require.NoError(t, err)
require.Equal(t, testValue, str.Value())

err = str.Marshal(nil)
require.Error(t, err)
require.Equal(t, "data does not match required *Binary or (string, *string, []byte, *[]byte) type", err.Error())
}
11 changes: 6 additions & 5 deletions field/bitmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ func (f *Bitmap) Unpack(data []byte) (int, error) {
return read, nil
}

// Deprecated. Use Marshal intead.
func (f *Bitmap) SetData(data interface{}) error {
return f.Marshal(data)
}

func (f *Bitmap) Unmarshal(v interface{}) error {
if v == nil {
return nil
Expand All @@ -129,7 +134,7 @@ func (f *Bitmap) Unmarshal(v interface{}) error {
return nil
}

func (f *Bitmap) SetData(data interface{}) error {
func (f *Bitmap) Marshal(data interface{}) error {
if data == nil {
return nil
}
Expand All @@ -143,10 +148,6 @@ func (f *Bitmap) SetData(data interface{}) error {
return nil
}

func (f *Bitmap) Marshal(data interface{}) error {
return f.SetData(data)
}

// Reset resets the bitmap to its initial state because of how message works,
// Message need a way to initialize bitmap. That's why we set parameters to
// their default values here like we do in constructor.
Expand Down
4 changes: 2 additions & 2 deletions field/bitmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func TestBitmap_SetData(t *testing.T) {

t.Run("Nil data causes no side effects", func(t *testing.T) {
bitmap := NewBitmap(spec)
err := bitmap.SetData(nil)
err := bitmap.Marshal(nil)
require.NoError(t, err)
require.Equal(t, NewBitmap(spec), bitmap)
})
Expand All @@ -339,7 +339,7 @@ func TestBitmap_SetData(t *testing.T) {
a string
}{"left"}

err := bitmap.SetData(str)
err := bitmap.Marshal(str)
require.Error(t, err)
})

Expand Down
24 changes: 17 additions & 7 deletions field/composite.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,23 @@ func (f *Composite) Unmarshal(v interface{}) error {
}

dataField := dataStruct.Field(i)
if dataField.IsNil() {
dataField.Set(reflect.New(dataField.Type().Elem()))
}
switch dataField.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
if dataField.IsNil() {
dataField.Set(reflect.New(dataField.Type().Elem()))
}

err = messageField.Unmarshal(dataField.Interface())
if err != nil {
return fmt.Errorf("failed to get data from field %s: %w", indexOrTag, err)
err = messageField.Unmarshal(dataField.Interface())
if err != nil {
return fmt.Errorf("failed to get data from field %s: %w", indexOrTag, err)
}
default: // Native types
vv := reflect.New(dataField.Type()).Elem()
err = messageField.Unmarshal(vv)
if err != nil {
return fmt.Errorf("failed to get data from field %s: %w", indexOrTag, err)
}
dataField.Set(vv)
}
}

Expand Down Expand Up @@ -259,7 +269,7 @@ func (f *Composite) Marshal(v interface{}) error {
}

dataField := dataStruct.Field(i)
if dataField.IsNil() {
if dataField.IsZero() {
continue
}

Expand Down
Loading

0 comments on commit d8c9fe2

Please sign in to comment.