From a4b1be2ea69aac2c6e2972080116786eb2911ca2 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 2 Oct 2023 10:06:14 -0500 Subject: [PATCH 1/4] Deprecate SetData method --- field/binary.go | 15 +++++----- field/binary_test.go | 8 ++--- field/bitmap.go | 15 +++++----- field/bitmap_test.go | 10 +++---- field/composite_test.go | 66 ++++++++++++++++++++--------------------- field/hex.go | 15 +++++----- field/numeric.go | 15 +++++----- field/numeric_test.go | 6 ++-- field/string.go | 15 +++++----- field/string_test.go | 6 ++-- field/track1.go | 15 +++++----- field/track2.go | 15 +++++----- field/track3.go | 15 +++++----- field/track_test.go | 30 +++++++++---------- message_test.go | 10 +++---- 15 files changed, 132 insertions(+), 124 deletions(-) diff --git a/field/binary.go b/field/binary.go index 64d00a8c..d1813c51 100644 --- a/field/binary.go +++ b/field/binary.go @@ -114,6 +114,11 @@ func (f *Binary) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *Binary) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Binary) Unmarshal(v interface{}) error { if v == nil { return nil @@ -129,12 +134,12 @@ func (f *Binary) Unmarshal(v interface{}) error { return nil } -func (f *Binary) SetData(data interface{}) error { - if data == nil { +func (f *Binary) Marshal(v interface{}) error { + if v == nil { return nil } - bin, ok := data.(*Binary) + bin, ok := v.(*Binary) if !ok { return errors.New("data does not match required *Binary type") } @@ -146,10 +151,6 @@ func (f *Binary) SetData(data interface{}) error { 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 { diff --git a/field/binary_test.go b/field/binary_test.go index 903bfef5..e3670ed3 100644 --- a/field/binary_test.go +++ b/field/binary_test.go @@ -48,9 +48,9 @@ func TestBinaryField(t *testing.T) { require.Equal(t, in, bin.value) }) - t.Run("SetData sets data to the field", func(t *testing.T) { + t.Run("Marshal sets data to the field", func(t *testing.T) { bin := NewBinary(spec) - bin.SetData(NewBinaryValue(in)) + bin.Marshal(NewBinaryValue(in)) packed, err := bin.Pack() @@ -71,7 +71,7 @@ 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) @@ -90,7 +90,7 @@ 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) diff --git a/field/bitmap.go b/field/bitmap.go index db1b1ea6..a8f0e170 100644 --- a/field/bitmap.go +++ b/field/bitmap.go @@ -114,6 +114,11 @@ func (f *Bitmap) Unpack(data []byte) (int, error) { return read, nil } +// Deprecated. Use Marshal instead +func (f *Bitmap) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Bitmap) Unmarshal(v interface{}) error { if v == nil { return nil @@ -129,12 +134,12 @@ func (f *Bitmap) Unmarshal(v interface{}) error { return nil } -func (f *Bitmap) SetData(data interface{}) error { - if data == nil { +func (f *Bitmap) Marshal(v interface{}) error { + if v == nil { return nil } - bmap, ok := data.(*Bitmap) + bmap, ok := v.(*Bitmap) if !ok { return fmt.Errorf("data does not match required *Bitmap type") } @@ -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. diff --git a/field/bitmap_test.go b/field/bitmap_test.go index f203d43d..c8aa6d09 100644 --- a/field/bitmap_test.go +++ b/field/bitmap_test.go @@ -317,7 +317,7 @@ func TestBitmap_Unmarshal(t *testing.T) { }) } -func TestBitmap_SetData(t *testing.T) { +func TestBitmap_Marshal(t *testing.T) { spec := &Spec{ Description: "Bitmap", Enc: encoding.BytesToASCIIHex, @@ -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) }) @@ -339,11 +339,11 @@ func TestBitmap_SetData(t *testing.T) { a string }{"left"} - err := bitmap.SetData(str) + err := bitmap.Marshal(str) require.Error(t, err) }) - t.Run("Unpack sets the data field with the correct bitmap provided using SetData", func(t *testing.T) { + t.Run("Unpack sets the data field with the correct bitmap provided using Marshal", func(t *testing.T) { bitmap := NewBitmap(spec) // set bit: 10 @@ -361,7 +361,7 @@ func TestBitmap_SetData(t *testing.T) { require.Equal(t, bitmapBytes, dataBytes) }) - t.Run("Pack returns bytes using the bitmap provided using SetData", func(t *testing.T) { + t.Run("Pack returns bytes using the bitmap provided using Marshal", func(t *testing.T) { bitmap := NewBitmap(spec) data := NewBitmap(&Spec{}) diff --git a/field/composite_test.go b/field/composite_test.go index 78d7fe08..79939278 100644 --- a/field/composite_test.go +++ b/field/composite_test.go @@ -349,10 +349,10 @@ type SubConstructedTLVTestData struct { F9F45 *Hex } -func TestComposite_SetData(t *testing.T) { - t.Run("SetData returns an error on provision of primitive type data", func(t *testing.T) { +func TestComposite_Marshal(t *testing.T) { + t.Run("Marshal returns an error on provision of primitive type data", func(t *testing.T) { composite := NewComposite(compositeTestSpec) - err := composite.SetData("primitive str") + err := composite.Marshal("primitive str") require.EqualError(t, err, "data is not a pointer or nil") }) } @@ -362,7 +362,7 @@ func TestCompositeFieldUnmarshal(t *testing.T) { // first, we need to populate fields of composite field // we will do it by packing the field composite := NewComposite(tlvTestSpec) - err := composite.SetData(&TLVTestData{ + err := composite.Marshal(&TLVTestData{ F9A: NewHexValue("210720"), F9F02: NewHexValue("000000000501"), }) @@ -381,7 +381,7 @@ func TestCompositeFieldUnmarshal(t *testing.T) { t.Run("Unmarshal gets data for composite field (constructed)", func(t *testing.T) { composite := NewComposite(constructedBERTLVTestSpec) - err := composite.SetData(&ConstructedTLVTestData{ + err := composite.Marshal(&ConstructedTLVTestData{ F82: NewHexValue("017F"), F9F36: NewHexValue("027F"), F9F3B: &SubConstructedTLVTestData{ @@ -410,7 +410,7 @@ func TestCompositeFieldUnmarshal(t *testing.T) { // first, we need to populate fields of composite field // we will do it by packing the field composite := NewComposite(tlvTestSpec) - err := composite.SetData(&TLVTestData{ + err := composite.Marshal(&TLVTestData{ F9A: NewHexValue("210720"), F9F02: NewHexValue("000000000501"), }) @@ -436,7 +436,7 @@ func TestTLVPacking(t *testing.T) { } composite := NewComposite(tlvTestSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -502,7 +502,7 @@ func TestTLVPacking(t *testing.T) { } composite := NewComposite(constructedBERTLVTestSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -592,7 +592,7 @@ func TestCompositePacking(t *testing.T) { F1 *Numeric } composite := NewComposite(compositeTestSpec) - err := composite.SetData(&TestDataIncorrectType{ + err := composite.Marshal(&TestDataIncorrectType{ F1: NewNumericValue(1), }) @@ -610,7 +610,7 @@ func TestCompositePacking(t *testing.T) { } composite := NewComposite(compositeTestSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) _, err = composite.Pack() @@ -666,7 +666,7 @@ func TestCompositePacking(t *testing.T) { } composite := NewComposite(compositeTestSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -754,7 +754,7 @@ func TestCompositePacking(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // Last two characters must be an integer type. F3 fails to unpack. @@ -793,7 +793,7 @@ func TestCompositePacking(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(spec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // Length of denoted by prefix is too long, causing failure to decode length. @@ -831,7 +831,7 @@ func TestCompositePacking(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(spec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // There is data only for first subfield @@ -947,7 +947,7 @@ func TestCompositePackingWithTags(t *testing.T) { } composite := NewComposite(invalidSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) b, err := composite.Pack() @@ -1010,7 +1010,7 @@ func TestCompositePackingWithTags(t *testing.T) { } composite := NewComposite(compositeTestSpecWithTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1026,7 +1026,7 @@ func TestCompositePackingWithTags(t *testing.T) { } composite := NewComposite(compositeTestSpecWithTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1043,7 +1043,7 @@ func TestCompositePackingWithTags(t *testing.T) { } composite := NewComposite(compositeTestSpecWithoutTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1056,7 +1056,7 @@ func TestCompositePackingWithTags(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // F3 fails to unpack - it requires len to be defined instead of AB. @@ -1070,7 +1070,7 @@ func TestCompositePackingWithTags(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // Index 2-3 should have '01' rather than '12'. @@ -1083,7 +1083,7 @@ func TestCompositePackingWithTags(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // Index 0, 1 should have '01' rather than 'ID'. @@ -1199,7 +1199,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { } composite := NewComposite(invalidSpec) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) b, err := composite.Pack() @@ -1262,7 +1262,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { } composite := NewComposite(compositeTestSpecWithDefaultBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1278,7 +1278,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { } composite := NewComposite(compositeTestSpecWithDefaultBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1299,7 +1299,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { } composite := NewComposite(compositeTestSpecWithSizedBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1315,7 +1315,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { } composite := NewComposite(compositeTestSpecWithSizedBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) packed, err := composite.Pack() @@ -1329,7 +1329,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithDefaultBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // F1 fails to unpack - it requires length to be defined instead of AB. @@ -1343,7 +1343,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithDefaultBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // Index 2-3 = 70 indicates the presence of field 4. This field is not defined on spec. @@ -1408,7 +1408,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithSizedBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // F1 fails to unpack - it requires length to be defined instead of AB. @@ -1422,7 +1422,7 @@ func TestCompositePackingWithBitmap(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithSizedBitmap) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) // Index 2-3 = 70 indicates the presence of field 4. This field is not defined on spec. @@ -1722,7 +1722,7 @@ func TestCompositeJSONConversion(t *testing.T) { } composite := NewComposite(compositeTestSpecWithTagPadding) - require.NoError(t, composite.SetData(data)) + require.NoError(t, composite.Marshal(data)) actual, err := composite.MarshalJSON() require.NoError(t, err) @@ -1734,7 +1734,7 @@ func TestCompositeJSONConversion(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithTagPadding) - err := composite.SetData(data) + err := composite.Marshal(data) require.NoError(t, err) require.NoError(t, composite.UnmarshalJSON([]byte(json))) @@ -1761,7 +1761,7 @@ func TestCompositeJSONConversion(t *testing.T) { data := &CompositeTestData{} composite := NewComposite(compositeTestSpecWithTagPadding) - require.NoError(t, composite.SetData(data)) + require.NoError(t, composite.Marshal(data)) require.NoError(t, composite.UnmarshalJSON([]byte(json))) diff --git a/field/hex.go b/field/hex.go index d11f38e3..36d8b0f5 100644 --- a/field/hex.go +++ b/field/hex.go @@ -126,6 +126,11 @@ func (f *Hex) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *Hex) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Hex) Unmarshal(v interface{}) error { if v == nil { return nil @@ -141,12 +146,12 @@ func (f *Hex) Unmarshal(v interface{}) error { return nil } -func (f *Hex) SetData(data interface{}) error { - if data == nil { +func (f *Hex) Marshal(v interface{}) error { + if v == nil { return nil } - str, ok := data.(*Hex) + str, ok := v.(*Hex) if !ok { return fmt.Errorf("data does not match required *Hex type") } @@ -158,10 +163,6 @@ func (f *Hex) SetData(data interface{}) error { return nil } -func (f *Hex) Marshal(data interface{}) error { - return f.SetData(data) -} - func (f *Hex) MarshalJSON() ([]byte, error) { data, err := f.String() if err != nil { diff --git a/field/numeric.go b/field/numeric.go index 18e41936..7c17f1b1 100644 --- a/field/numeric.go +++ b/field/numeric.go @@ -128,6 +128,11 @@ func (f *Numeric) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *Numeric) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Numeric) Unmarshal(v interface{}) error { if v == nil { return nil @@ -142,12 +147,12 @@ func (f *Numeric) Unmarshal(v interface{}) error { return nil } -func (f *Numeric) SetData(data interface{}) error { - if data == nil { +func (f *Numeric) Marshal(v interface{}) error { + if v == nil { return nil } - num, ok := data.(*Numeric) + num, ok := v.(*Numeric) if !ok { return fmt.Errorf("data does not match required *Numeric type") } @@ -159,10 +164,6 @@ func (f *Numeric) SetData(data interface{}) error { return nil } -func (f *Numeric) Marshal(data interface{}) error { - return f.SetData(data) -} - func (f *Numeric) MarshalJSON() ([]byte, error) { bytes, err := json.Marshal(f.value) if err != nil { diff --git a/field/numeric_test.go b/field/numeric_test.go index c2ac8f87..1da167ea 100644 --- a/field/numeric_test.go +++ b/field/numeric_test.go @@ -37,14 +37,14 @@ func TestNumericField(t *testing.T) { require.Equal(t, 9876, numeric.Value()) numeric = NewNumeric(spec) - numeric.SetData(NewNumericValue(9876)) + numeric.Marshal(NewNumericValue(9876)) packed, err = numeric.Pack() require.NoError(t, err) require.Equal(t, " 9876", string(packed)) numeric = NewNumeric(spec) data := NewNumericValue(0) - numeric.SetData(data) + numeric.Marshal(data) length, err = numeric.Unpack([]byte(" 9876")) require.NoError(t, err) require.Equal(t, 10, length) @@ -159,7 +159,7 @@ func TestNumericSetBytesSetsDataOntoDataStruct(t *testing.T) { }) data := &Numeric{} - err := numeric.SetData(data) + err := numeric.Marshal(data) require.NoError(t, err) err = numeric.SetBytes([]byte("9")) diff --git a/field/string.go b/field/string.go index 94a1a8a4..11421e25 100644 --- a/field/string.go +++ b/field/string.go @@ -113,6 +113,11 @@ func (f *String) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *String) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *String) Unmarshal(v interface{}) error { if v == nil { return nil @@ -128,12 +133,12 @@ func (f *String) Unmarshal(v interface{}) error { return nil } -func (f *String) SetData(data interface{}) error { - if data == nil { +func (f *String) Marshal(v interface{}) error { + if v == nil { return nil } - str, ok := data.(*String) + str, ok := v.(*String) if !ok { return fmt.Errorf("data does not match required *String type") } @@ -145,10 +150,6 @@ func (f *String) SetData(data interface{}) error { return nil } -func (f *String) Marshal(data interface{}) error { - return f.SetData(data) -} - func (f *String) MarshalJSON() ([]byte, error) { bytes, err := json.Marshal(f.value) if err != nil { diff --git a/field/string_test.go b/field/string_test.go index f2537d32..2158d3ff 100644 --- a/field/string_test.go +++ b/field/string_test.go @@ -37,14 +37,14 @@ func TestStringField(t *testing.T) { require.Equal(t, "olleh", str.Value()) str = NewString(spec) - str.SetData(NewStringValue("hello")) + str.Marshal(NewStringValue("hello")) packed, err = str.Pack() require.NoError(t, err) require.Equal(t, " hello", string(packed)) str = NewString(spec) data := NewStringValue("") - str.SetData(data) + str.Marshal(data) length, err = str.Unpack([]byte(" olleh")) require.NoError(t, err) require.Equal(t, 10, length) @@ -52,7 +52,7 @@ func TestStringField(t *testing.T) { str = NewString(spec) data = &String{} - str.SetData(data) + str.Marshal(data) err = str.SetBytes([]byte("hello")) require.NoError(t, err) require.Equal(t, "hello", data.Value()) diff --git a/field/track1.go b/field/track1.go index f96aae9c..519bd914 100644 --- a/field/track1.go +++ b/field/track1.go @@ -111,6 +111,11 @@ func (f *Track1) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *Track1) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Track1) Unmarshal(v interface{}) error { if v == nil { return nil @@ -132,12 +137,12 @@ func (f *Track1) Unmarshal(v interface{}) error { return nil } -func (f *Track1) SetData(data interface{}) error { - if data == nil { +func (f *Track1) Marshal(v interface{}) error { + if v == nil { return nil } - track, ok := data.(*Track1) + track, ok := v.(*Track1) if !ok { return fmt.Errorf("data does not match required *Track type") } @@ -155,10 +160,6 @@ func (f *Track1) SetData(data interface{}) error { return nil } -func (f *Track1) Marshal(data interface{}) error { - return f.SetData(data) -} - func (f *Track1) unpack(raw []byte) error { if raw == nil || !track1Regex.Match(raw) { return errors.New("invalid track data") diff --git a/field/track2.go b/field/track2.go index 8d05383a..e94d6d26 100644 --- a/field/track2.go +++ b/field/track2.go @@ -109,6 +109,11 @@ func (f *Track2) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *Track2) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Track2) Unmarshal(v interface{}) error { if v == nil { return nil @@ -128,12 +133,12 @@ func (f *Track2) Unmarshal(v interface{}) error { return nil } -func (f *Track2) SetData(data interface{}) error { - if data == nil { +func (f *Track2) Marshal(v interface{}) error { + if v == nil { return nil } - track, ok := data.(*Track2) + track, ok := v.(*Track2) if !ok { return fmt.Errorf("data does not match required *Track type") } @@ -149,10 +154,6 @@ func (f *Track2) SetData(data interface{}) error { return nil } -func (f *Track2) Marshal(data interface{}) error { - return f.SetData(data) -} - func (f *Track2) unpack(raw []byte) error { if raw == nil || !track2Regex.Match(raw) { return errors.New("invalid track data") diff --git a/field/track3.go b/field/track3.go index 9e180b4a..86ac72b5 100644 --- a/field/track3.go +++ b/field/track3.go @@ -108,6 +108,11 @@ func (f *Track3) Unpack(data []byte) (int, error) { return read + prefBytes, nil } +// Deprecated. Use Marshal instead +func (f *Track3) SetData(data interface{}) error { + return f.Marshal(data) +} + func (f *Track3) Unmarshal(v interface{}) error { if v == nil { return nil @@ -125,12 +130,12 @@ func (f *Track3) Unmarshal(v interface{}) error { return nil } -func (f *Track3) SetData(data interface{}) error { - if data == nil { +func (f *Track3) Marshal(v interface{}) error { + if v == nil { return nil } - track, ok := data.(*Track3) + track, ok := v.(*Track3) if !ok { return fmt.Errorf("data does not match required *Track type") } @@ -144,10 +149,6 @@ func (f *Track3) SetData(data interface{}) error { return nil } -func (f *Track3) Marshal(data interface{}) error { - return f.SetData(data) -} - func (f *Track3) unpack(raw []byte) error { if raw == nil || !track3Regex.Match(raw) { return errors.New("invalid track data") diff --git a/field/track_test.go b/field/track_test.go index 7a71a4d2..f52e2ab7 100644 --- a/field/track_test.go +++ b/field/track_test.go @@ -137,7 +137,7 @@ func TestTrack1(t *testing.T) { t.Run("Returns an error on mismatch of track type", func(t *testing.T) { track := NewTrack1(track1Spec) - err := track.SetData(NewStringValue("hello")) + err := track.Marshal(NewStringValue("hello")) require.EqualError(t, err, "data does not match required *Track type") }) @@ -146,7 +146,7 @@ func TestTrack1(t *testing.T) { require.NoError(t, err) track := NewTrack1(track1Spec) - err = track.SetData(&Track1{ + err = track.Marshal(&Track1{ FixedLength: true, FormatCode: "B", PrimaryAccountNumber: "1234567890123445", @@ -185,7 +185,7 @@ func TestTrack1(t *testing.T) { } track := NewTrack1(track1Spec) - err = track.SetData(data) + err = track.Marshal(data) require.NoError(t, err) // test assigned fields @@ -208,7 +208,7 @@ func TestTrack1(t *testing.T) { data := &Track1{} track := NewTrack1(track1Spec) - err = track.SetData(data) + err = track.Marshal(data) require.NoError(t, err) _, err = track.Unpack(rawWithPrefix) @@ -230,7 +230,7 @@ func TestTrack1(t *testing.T) { data := &Track1{} track := NewTrack1(track1Spec) - err = track.SetData(data) + err = track.Marshal(data) require.NoError(t, err) err = track.SetBytes(raw) @@ -304,7 +304,7 @@ func TestTrack2TypedAPI(t *testing.T) { t.Run("Track 2 typed", func(t *testing.T) { t.Run("Returns an error on mismatch of track type", func(t *testing.T) { track := NewTrack2(track2Spec) - err := track.SetData(NewStringValue("hello")) + err := track.Marshal(NewStringValue("hello")) require.EqualError(t, err, "data does not match required *Track type") }) @@ -313,7 +313,7 @@ func TestTrack2TypedAPI(t *testing.T) { require.NoError(t, err) track := NewTrack2(track2Spec) - err = track.SetData(&Track2{ + err = track.Marshal(&Track2{ PrimaryAccountNumber: "4000340000000506", Separator: "D", ServiceCode: "111", @@ -366,7 +366,7 @@ func TestTrack2TypedAPI(t *testing.T) { } track := NewTrack2(track2Spec) - err = track.SetData(data) + err = track.Marshal(data) require.NoError(t, err) // test assigned fields @@ -404,7 +404,7 @@ func TestTrack2TypedAPI(t *testing.T) { data := &Track2{} track := NewTrack2(track2Spec) - err = track.SetData(data) + err = track.Marshal(data) require.NoError(t, err) _, err = track.Unpack(tc.Bytes) @@ -441,7 +441,7 @@ func TestTrack2TypedAPI(t *testing.T) { data := &Track2{} track := NewTrack2(track2Spec) - err = track.SetData(data) + err = track.Marshal(data) require.NoError(t, err) err = track.SetBytes(tc.TrackData) @@ -515,13 +515,13 @@ func TestTrack3TypedAPI(t *testing.T) { ) t.Run("Returns an error on mismatch of track type", func(t *testing.T) { track := NewTrack3(track3Spec) - err := track.SetData(NewStringValue("hello")) + err := track.Marshal(NewStringValue("hello")) require.EqualError(t, err, "data does not match required *Track type") }) t.Run("Unmarshal gets track values into data parameter", func(t *testing.T) { track := NewTrack3(track3Spec) - err := track.SetData(&Track3{ + err := track.Marshal(&Track3{ FormatCode: `01`, PrimaryAccountNumber: `1234567890123445`, DiscretionaryData: `724724000000000****00300XXXX020200099010=********************==1=100000000000000000**`, @@ -546,7 +546,7 @@ func TestTrack3TypedAPI(t *testing.T) { } track := NewTrack3(track3Spec) - err := track.SetData(data) + err := track.Marshal(data) require.NoError(t, err) // test assigned fields @@ -563,7 +563,7 @@ func TestTrack3TypedAPI(t *testing.T) { data := &Track3{} track := NewTrack3(track3Spec) - err := track.SetData(data) + err := track.Marshal(data) require.NoError(t, err) _, err = track.Unpack(rawWithPrefix) @@ -579,7 +579,7 @@ func TestTrack3TypedAPI(t *testing.T) { data := &Track3{} track := NewTrack3(track3Spec) - err := track.SetData(data) + err := track.Marshal(data) require.NoError(t, err) err = track.SetBytes(raw) diff --git a/message_test.go b/message_test.go index 7968340e..95f06348 100644 --- a/message_test.go +++ b/message_test.go @@ -265,7 +265,7 @@ func TestMessage(t *testing.T) { } message := NewMessage(spec) - err := message.SetData(&ISO87Data{ + err := message.Marshal(&ISO87Data{ F0: field.NewStringValue("0100"), F2: field.NewStringValue("4242424242424242"), F3: &TestISOF3Data{ @@ -535,7 +535,7 @@ func TestPackUnpack(t *testing.T) { t.Run("Pack data", func(t *testing.T) { message := NewMessage(spec) - err := message.SetData(&TestISOData{ + err := message.Marshal(&TestISOData{ F2: field.NewStringValue("4276555555555555"), F3: &TestISOF3Data{ F1: field.NewStringValue("00"), @@ -815,7 +815,7 @@ func TestMessageJSON(t *testing.T) { require.NoError(t, err) message := NewMessage(spec) - err = message.SetData(&TestISOData{ + err = message.Marshal(&TestISOData{ F0: field.NewStringValue("0100"), F2: field.NewStringValue("4242424242424242"), F3: &TestISOF3Data{ @@ -873,7 +873,7 @@ func TestMessageJSON(t *testing.T) { want := `{"0":"0100","1":"7000000000000000","2":"4242424242424242","3":{"1":"12","2":"34","3":"56"},"4":"100"}` message := NewMessage(spec) - message.SetData(&ISO87Data{}) + message.Marshal(&ISO87Data{}) rawMsg := []byte("01007000000000000000164242424242424242123456000000000100") require.NoError(t, message.Unpack([]byte(rawMsg))) @@ -1228,7 +1228,7 @@ func TestMessageClone(t *testing.T) { }, F120: field.NewStringValue("Another test text"), } - require.NoError(t, message.SetData(data2)) + require.NoError(t, message.Marshal(data2)) message.MTI("0100") From be33dcedce29cd48bf1a62f3c090f07f8b869821 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 2 Oct 2023 10:11:29 -0500 Subject: [PATCH 2/4] fix wrong spelling --- field/field.go | 2 +- message.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/field/field.go b/field/field.go index 306153fd..234cee6e 100644 --- a/field/field.go +++ b/field/field.go @@ -23,7 +23,7 @@ type Field interface { // Bytes returns binary representation of the field Value Bytes() ([]byte, error) - // Deprecated. Use Marshal intead. + // Deprecated. Use Marshal instead. SetData(data interface{}) error // Unmarshal sets field Value into provided v. If v is nil or not diff --git a/message.go b/message.go index 01538508..54f01aae 100644 --- a/message.go +++ b/message.go @@ -51,7 +51,7 @@ func NewMessage(spec *MessageSpec) *Message { } } -// Deprecated. Use Marshal intead. +// Deprecated. Use Marshal instead. func (m *Message) SetData(data interface{}) error { return m.Marshal(data) } From dc7902ca8390c647226639187ad5a0ab9a25f546 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 2 Oct 2023 10:24:20 -0500 Subject: [PATCH 3/4] Unpdate Unmarshal/Marshal method for the message and the rest of the fields --- field/binary.go | 95 +++++++++++++++++++++++++++++++------------ field/binary_test.go | 75 +++++++++++++++++++++++++++++++++- field/hex.go | 85 ++++++++++++++++++++++++++------------ field/hex_test.go | 81 ++++++++++++++++++++++++++++++++++++ field/numeric.go | 91 ++++++++++++++++++++++++++++++----------- field/numeric_test.go | 73 ++++++++++++++++++++++++++++++--- field/string.go | 87 +++++++++++++++++++++++++++------------ field/string_test.go | 80 ++++++++++++++++++++++++++++++------ 8 files changed, 548 insertions(+), 119 deletions(-) diff --git a/field/binary.go b/field/binary.go index d1813c51..7c9c3dfb 100644 --- a/field/binary.go +++ b/field/binary.go @@ -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" @@ -16,7 +17,6 @@ var _ json.Unmarshaler = (*Binary)(nil) type Binary struct { value []byte spec *Spec - data *Binary } func NewBinary(spec *Spec) *Binary { @@ -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 } @@ -120,34 +117,82 @@ func (f *Binary) SetData(data interface{}) error { } func (f *Binary) Unmarshal(v interface{}) error { - if v == nil { - return nil + switch val := v.(type) { + case reflect.Value: + switch val.Kind() { //nolint:exhaustive + 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, ok := v.(*Binary) - if !ok { - return errors.New("data does not match required *Binary type") - } - - bin.value = f.value - return nil } func (f *Binary) Marshal(v interface{}) error { - if v == nil { - return nil - } - - bin, ok := v.(*Binary) - if !ok { - return errors.New("data does not match required *Binary type") + 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 } diff --git a/field/binary_test.go b/field/binary_test.go index e3670ed3..6d300ba2 100644 --- a/field/binary_test.go +++ b/field/binary_test.go @@ -1,6 +1,7 @@ package field import ( + "reflect" "testing" "github.com/moov-io/iso8583/encoding" @@ -76,7 +77,7 @@ func TestBinaryField(t *testing.T) { 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 @@ -96,7 +97,7 @@ func TestBinaryField(t *testing.T) { 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) { @@ -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()) +} diff --git a/field/hex.go b/field/hex.go index 36d8b0f5..8912be17 100644 --- a/field/hex.go +++ b/field/hex.go @@ -3,8 +3,8 @@ package field import ( "encoding/hex" "encoding/json" - "errors" "fmt" + "reflect" "strings" "github.com/moov-io/iso8583/utils" @@ -22,7 +22,6 @@ var _ json.Unmarshaler = (*Hex)(nil) type Hex struct { value string spec *Spec - data *Hex } func NewHex(spec *Spec) *Hex { @@ -50,9 +49,6 @@ func (f *Hex) SetSpec(spec *Spec) { func (f *Hex) SetBytes(b []byte) error { f.value = strings.ToUpper(hex.EncodeToString(b)) - if f.data != nil { - *(f.data) = *f - } return nil } @@ -132,34 +128,73 @@ func (f *Hex) SetData(data interface{}) error { } func (f *Hex) Unmarshal(v interface{}) error { - if v == nil { - return nil - } - - str, ok := v.(*Hex) - if !ok { - return errors.New("data does not match required *Hex type") + switch val := v.(type) { + case reflect.Value: + switch val.Kind() { //nolint:exhaustive + case reflect.String: + if !val.CanSet() { + return fmt.Errorf("reflect.Value of the data can not be change") + } + + str, _ := f.String() + val.SetString(str) + case reflect.Slice: + if !val.CanSet() { + return fmt.Errorf("reflect.Value of the data can not be change") + } + + buf, _ := f.Bytes() + val.SetBytes(buf) + default: + return fmt.Errorf("data does not match required reflect.Value type") + } + case *string: + *val, _ = f.String() + case *[]byte: + *val, _ = f.Bytes() + case *Hex: + val.value = f.value + default: + return fmt.Errorf("data does not match required *Hex or (*string, *[]byte) type") } - str.value = f.value - return nil } func (f *Hex) Marshal(v interface{}) error { - if v == nil { - return nil + switch v := v.(type) { + case *Hex: + if v == nil { + return nil + } + f.value = v.value + case string: + if v == "" { + f.value = "" + return nil + } + + f.value = v + hex.EncodeToString([]byte(v)) + case *string: + if v == nil { + f.value = "" + return nil + } + + f.value = *v + case []byte: + f.SetBytes(v) + case *[]byte: + if v == nil { + f.value = "" + return nil + } + f.SetBytes(*v) + default: + return fmt.Errorf("data does not match required *Hex or (string, *string, []byte, *[]byte) type") } - str, ok := v.(*Hex) - if !ok { - return fmt.Errorf("data does not match required *Hex type") - } - - f.data = str - if str.value != "" { - f.value = str.value - } return nil } diff --git a/field/hex_test.go b/field/hex_test.go index 25c4a96b..43f131c8 100644 --- a/field/hex_test.go +++ b/field/hex_test.go @@ -2,6 +2,7 @@ package field import ( "errors" + "reflect" "testing" "github.com/moov-io/iso8583/encoding" @@ -142,3 +143,83 @@ func TestHexPack(t *testing.T) { require.EqualError(t, err, "failed to encode length: field length: 0 should be fixed: 10") }) } + +func TestHexFieldUnmarshal(t *testing.T) { + testValue := []byte{0x12, 0x34, 0x56} + str := NewHexValue("123456") + + val1 := &Hex{} + err := str.Unmarshal(val1) + require.NoError(t, err) + require.Equal(t, "123456", val1.Value()) + buf, _ := val1.Bytes() + require.Equal(t, testValue, buf) + + 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 *Hex or (*string, *[]byte) type", err.Error()) +} + +func TestHexFieldMarshal(t *testing.T) { + testValue := []byte{0x12, 0x34, 0x56} + str := NewHexValue("") + + vstring := "123456" + err := str.Marshal(vstring) + require.NoError(t, err) + require.Equal(t, "123456", str.Value()) + buf, _ := str.Bytes() + require.Equal(t, testValue, buf) + + err = str.Marshal(&vstring) + require.NoError(t, err) + require.Equal(t, "123456", str.Value()) + buf, _ = str.Bytes() + require.Equal(t, testValue, buf) + + err = str.Marshal(testValue) + require.NoError(t, err) + require.Equal(t, "123456", str.Value()) + buf, _ = str.Bytes() + require.Equal(t, testValue, buf) + + err = str.Marshal(&testValue) + require.NoError(t, err) + require.Equal(t, "123456", str.Value()) + buf, _ = str.Bytes() + require.Equal(t, testValue, buf) + + err = str.Marshal(nil) + require.Error(t, err) + require.Equal(t, "data does not match required *Hex or (string, *string, []byte, *[]byte) type", err.Error()) +} diff --git a/field/numeric.go b/field/numeric.go index 7c17f1b1..21cc7ded 100644 --- a/field/numeric.go +++ b/field/numeric.go @@ -2,8 +2,8 @@ package field import ( "encoding/json" - "errors" "fmt" + "reflect" "strconv" "github.com/moov-io/iso8583/utils" @@ -16,7 +16,6 @@ var _ json.Unmarshaler = (*Numeric)(nil) type Numeric struct { value int spec *Spec - data *Numeric } func NewNumeric(spec *Spec) *Numeric { @@ -54,9 +53,6 @@ func (f *Numeric) SetBytes(b []byte) error { f.value = val } - if f.data != nil { - *(f.data) = *f - } return nil } @@ -134,33 +130,80 @@ func (f *Numeric) SetData(data interface{}) error { } func (f *Numeric) Unmarshal(v interface{}) error { - if v == nil { - return nil - } - num, ok := v.(*Numeric) - if !ok { - return errors.New("data does not match required *Numeric type") + switch val := v.(type) { + case reflect.Value: + switch val.Kind() { //nolint:exhaustive + case reflect.String: + if !val.CanSet() { + return fmt.Errorf("reflect.Value of the data can not be change") + } + + str := strconv.Itoa(f.value) + val.SetString(str) + case reflect.Int: + if !val.CanSet() { + return fmt.Errorf("reflect.Value of the data can not be change") + } + + val.SetInt(int64(f.value)) + default: + return fmt.Errorf("data does not match required reflect.Value type") + } + case *string: + str := strconv.Itoa(f.value) + *val = str + case *int: + *val = f.value + case *Numeric: + val.value = f.value + default: + return fmt.Errorf("data does not match required *Numeric or *int type") } - num.value = f.value - return nil } -func (f *Numeric) Marshal(v interface{}) error { - if v == nil { - return nil - } +func (f *Numeric) Marshal(data interface{}) error { + switch v := data.(type) { + case *Numeric: + if v == nil { + f.value = 0 + return nil + } + f.value = v.value + case int: + f.value = v + case *int: + if v == nil { + f.value = 0 + return nil + } + f.value = *v + case string: + if v == "" { + f.value = 0 + return nil + } + val, err := strconv.Atoi(v) + if err != nil { + return utils.NewSafeError(err, "failed to convert sting value into number") + } + f.value = val + case *string: + if v == nil { + f.value = 0 + return nil + } - num, ok := v.(*Numeric) - if !ok { - return fmt.Errorf("data does not match required *Numeric type") + val, err := strconv.Atoi(*v) + if err != nil { + return utils.NewSafeError(err, "failed to convert sting value into number") + } + f.value = val + default: + return fmt.Errorf("data does not match require *Numeric or (int, *int, string, *string) type") } - f.data = num - if num.value != 0 { - f.value = num.value - } return nil } diff --git a/field/numeric_test.go b/field/numeric_test.go index 1da167ea..8665652a 100644 --- a/field/numeric_test.go +++ b/field/numeric_test.go @@ -1,6 +1,7 @@ package field import ( + "reflect" "testing" "github.com/moov-io/iso8583/encoding" @@ -48,7 +49,7 @@ func TestNumericField(t *testing.T) { length, err = numeric.Unpack([]byte(" 9876")) require.NoError(t, err) require.Equal(t, 10, length) - require.Equal(t, 9876, data.Value()) + require.Equal(t, 9876, numeric.Value()) numeric = NewNumeric(spec) numeric.SetValue(9876) @@ -88,14 +89,74 @@ func TestNumericPack(t *testing.T) { } func TestNumericFieldUnmarshal(t *testing.T) { - str := NewNumericValue(9876) + str := NewNumericValue(123456) + + val1 := &Numeric{} + err := str.Unmarshal(val1) + require.NoError(t, err) + require.Equal(t, 123456, val1.Value()) - val := &Numeric{} + var val2 string + err = str.Unmarshal(&val2) + require.NoError(t, err) + require.Equal(t, "123456", val2) - err := str.Unmarshal(val) + var val3 int + err = str.Unmarshal(&val3) + require.NoError(t, err) + require.Equal(t, 123456, val3) + val4 := reflect.ValueOf(&val2).Elem() + err = str.Unmarshal(val4) require.NoError(t, err) - require.Equal(t, 9876, val.Value()) + require.Equal(t, "123456", val4.String()) + + val5 := reflect.ValueOf(&val3).Elem() + err = str.Unmarshal(val5) + require.NoError(t, err) + require.Equal(t, 123456, int(val5.Int())) + + 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 *Numeric or *int type", err.Error()) +} + +func TestNumericFieldMarshal(t *testing.T) { + str := NewNumericValue(0) + vNumeric := NewNumericValue(123456) + str.Marshal(vNumeric) + require.Equal(t, 123456, vNumeric.Value()) + + str.Marshal(&vNumeric) + require.Equal(t, 123456, vNumeric.Value()) + + vstring := "123456" + str.Marshal(vstring) + require.Equal(t, 123456, vNumeric.Value()) + + str.Marshal(&vstring) + require.Equal(t, 123456, vNumeric.Value()) + + vint := 123456 + str.Marshal(vint) + require.Equal(t, 123456, vNumeric.Value()) + + str.Marshal(&vint) + require.Equal(t, 123456, vNumeric.Value()) + + err := str.Marshal(nil) + require.Error(t, err) + require.Equal(t, "data does not match require *Numeric or (int, *int, string, *string) type", err.Error()) } func TestNumericFieldWithNotANumber(t *testing.T) { @@ -165,7 +226,7 @@ func TestNumericSetBytesSetsDataOntoDataStruct(t *testing.T) { err = numeric.SetBytes([]byte("9")) require.NoError(t, err) - require.Equal(t, 9, data.Value()) + require.Equal(t, 9, numeric.Value()) } func TestNumericJSONMarshal(t *testing.T) { diff --git a/field/string.go b/field/string.go index 11421e25..f20e564b 100644 --- a/field/string.go +++ b/field/string.go @@ -2,8 +2,9 @@ package field import ( "encoding/json" - "errors" "fmt" + "reflect" + "strconv" "github.com/moov-io/iso8583/utils" ) @@ -15,7 +16,6 @@ var _ json.Unmarshaler = (*String)(nil) type String struct { value string spec *Spec - data *String } func NewString(spec *Spec) *String { @@ -40,9 +40,6 @@ func (f *String) SetSpec(spec *Spec) { func (f *String) SetBytes(b []byte) error { f.value = string(b) - if f.data != nil { - *(f.data) = *f - } return nil } @@ -119,34 +116,74 @@ func (f *String) SetData(data interface{}) 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() { //nolint:exhaustive + case reflect.String: + if !val.CanSet() { + return fmt.Errorf("reflect.Value of the data can not be change") + } + + val.SetString(f.value) + case reflect.Int: + if !val.CanSet() { + return fmt.Errorf("reflect.Value of the data can not be change") + } + + 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 } func (f *String) Marshal(v interface{}) error { - if v == nil { - return nil + switch v := v.(type) { + case *String: + if v == nil { + f.value = "" + return nil + } + f.value = v.value + case string: + if v == "" { + f.value = "" + return nil + } + f.value = v + case *string: + if v == nil { + f.value = "" + return nil + } + f.value = *v + case int: + f.value = strconv.FormatInt(int64(v), 10) + case *int: + f.value = strconv.FormatInt(int64(*v), 10) + default: + return fmt.Errorf("data does not match required *String or (string, *string, int, *int) type") } - str, ok := v.(*String) - if !ok { - return fmt.Errorf("data does not match required *String type") - } - - f.data = str - if str.value != "" { - f.value = str.value - } return nil } diff --git a/field/string_test.go b/field/string_test.go index 2158d3ff..c8a11f38 100644 --- a/field/string_test.go +++ b/field/string_test.go @@ -1,6 +1,7 @@ package field import ( + "reflect" "testing" "github.com/moov-io/iso8583/encoding" @@ -43,24 +44,19 @@ func TestStringField(t *testing.T) { require.Equal(t, " hello", string(packed)) str = NewString(spec) - data := NewStringValue("") - str.Marshal(data) length, err = str.Unpack([]byte(" olleh")) require.NoError(t, err) require.Equal(t, 10, length) - require.Equal(t, "olleh", data.Value()) + require.Equal(t, "olleh", str.Value()) str = NewString(spec) - data = &String{} - str.Marshal(data) err = str.SetBytes([]byte("hello")) require.NoError(t, err) - require.Equal(t, "hello", data.Value()) + require.Equal(t, "hello", str.Value()) str = NewString(spec) - str.SetValue("hello") - require.Equal(t, "hello", data.Value()) + require.Equal(t, "hello", str.Value()) } func TestStringNil(t *testing.T) { @@ -94,14 +90,74 @@ func TestStringPack(t *testing.T) { } func TestStringFieldUnmarshal(t *testing.T) { - str := NewStringValue("hello") + str := NewStringValue("123456") - val := &String{} + val1 := &String{} + err := str.Unmarshal(val1) + require.NoError(t, err) + require.Equal(t, "123456", val1.Value()) - err := str.Unmarshal(val) + var val2 string + err = str.Unmarshal(&val2) + require.NoError(t, err) + require.Equal(t, "123456", val2) + var val3 int + err = str.Unmarshal(&val3) require.NoError(t, err) - require.Equal(t, "hello", val.Value()) + require.Equal(t, 123456, 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, 123456, int(val5.Int())) + + 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 *String or *string type", err.Error()) +} + +func TestStringFieldMarshal(t *testing.T) { + str := NewStringValue("") + vString := NewStringValue("123456") + str.Marshal(vString) + require.Equal(t, "123456", str.Value()) + + str.Marshal(&vString) + require.Equal(t, "123456", str.Value()) + + vstring := "123456" + str.Marshal(vstring) + require.Equal(t, "123456", str.Value()) + + str.Marshal(&vstring) + require.Equal(t, "123456", str.Value()) + + vint := 123456 + str.Marshal(vint) + require.Equal(t, "123456", str.Value()) + + str.Marshal(&vint) + require.Equal(t, "123456", str.Value()) + + err := str.Marshal(nil) + require.Error(t, err) + require.Equal(t, "data does not match required *String or (string, *string, int, *int) type", err.Error()) } func TestStringJSONUnmarshal(t *testing.T) { From 48a45beb316cf9b6cba2807ec44fe825121dec65 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 2 Oct 2023 10:30:34 -0500 Subject: [PATCH 4/4] Update message.Marshal message to accept structs with Go's native types --- field/composite.go | 24 ++++++++---- field/composite_test.go | 4 +- message.go | 24 ++++++++---- message_test.go | 82 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 16 deletions(-) diff --git a/field/composite.go b/field/composite.go index 6612c89f..212975cb 100644 --- a/field/composite.go +++ b/field/composite.go @@ -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() { //nolint:exhaustive + 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) } } @@ -259,7 +269,7 @@ func (f *Composite) Marshal(v interface{}) error { } dataField := dataStruct.Field(i) - if dataField.IsNil() { + if dataField.IsZero() { continue } diff --git a/field/composite_test.go b/field/composite_test.go index 79939278..e32f79a6 100644 --- a/field/composite_test.go +++ b/field/composite_test.go @@ -597,7 +597,7 @@ func TestCompositePacking(t *testing.T) { }) require.Error(t, err) - require.EqualError(t, err, "failed to set data from field 1: data does not match required *String type") + require.EqualError(t, err, "failed to set data from field 1: data does not match required *String or (string, *string, int, *int) type") }) t.Run("Pack returns error on failure of subfield packing", func(t *testing.T) { @@ -747,7 +747,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.EqualError(t, err, "failed to get data from field 1: data does not match required *String or *string type") }) t.Run("Unpack returns an error on failure of subfield to unpack bytes", func(t *testing.T) { diff --git a/message.go b/message.go index 54f01aae..e07b4723 100644 --- a/message.go +++ b/message.go @@ -445,7 +445,7 @@ func (m *Message) Marshal(v interface{}) error { } dataField := dataStruct.Field(i) - if dataField.IsNil() { + if dataField.IsZero() { continue } @@ -502,13 +502,23 @@ func (m *Message) Unmarshal(v interface{}) error { } dataField := dataStruct.Field(i) - if dataField.IsNil() { - dataField.Set(reflect.New(dataField.Type().Elem())) - } + switch dataField.Kind() { //nolint:exhaustive + 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 value from field %d: %w", fieldIndex, err) + err = messageField.Unmarshal(dataField.Interface()) + if err != nil { + return fmt.Errorf("failed to get value from field %d: %w", fieldIndex, err) + } + default: // Native types + vv := reflect.New(dataField.Type()).Elem() + err = messageField.Unmarshal(vv) + if err != nil { + return fmt.Errorf("failed to get value from field %d: %w", fieldIndex, err) + } + dataField.Set(vv) } } diff --git a/message_test.go b/message_test.go index 95f06348..5056580e 100644 --- a/message_test.go +++ b/message_test.go @@ -250,6 +250,53 @@ func TestMessage(t *testing.T) { require.Equal(t, "100", data.F4.Value()) }) + t.Run("Test unpacking with untyped fields", func(t *testing.T) { + type TestISOF3Data struct { + F1 *string + F2 string + F3 string + } + + type ISO87Data struct { + F0 *string + F2 string + F3 *TestISOF3Data + F4 string + } + + message := NewMessage(spec) + + rawMsg := []byte("01007000000000000000164242424242424242123456000000000100") + err := message.Unpack([]byte(rawMsg)) + + require.NoError(t, err) + + s, err := message.GetString(2) + require.NoError(t, err) + require.Equal(t, "4242424242424242", s) + + s, err = message.GetString(3) + require.NoError(t, err) + require.Equal(t, "123456", s) + + s, err = message.GetString(4) + require.NoError(t, err) + require.Equal(t, "100", s) + + data := &ISO87Data{} + + require.NoError(t, message.Unmarshal(data)) + + require.NotNil(t, data.F0) + require.Equal(t, "0100", *data.F0) + require.Equal(t, "4242424242424242", data.F2) + require.NotNil(t, data.F3.F1) + require.Equal(t, "12", *data.F3.F1) + require.Equal(t, "34", data.F3.F2) + require.Equal(t, "56", data.F3.F3) + require.Equal(t, "100", data.F4) + }) + t.Run("Test packing with typed fields", func(t *testing.T) { type TestISOF3Data struct { F1 *field.String @@ -283,6 +330,41 @@ func TestMessage(t *testing.T) { wantMsg := []byte("01007000000000000000164242424242424242123456000000000100") require.Equal(t, wantMsg, rawMsg) }) + + t.Run("Test packing with untyped fields", func(t *testing.T) { + type TestISOF3Data struct { + F1 string + F2 string + F3 string + } + + type ISO87Data struct { + F0 *string + F2 string + F3 *TestISOF3Data + F4 string + } + + messageCode := "0100" + message := NewMessage(spec) + err := message.Marshal(&ISO87Data{ + F0: &messageCode, + F2: "4242424242424242", + F3: &TestISOF3Data{ + F1: "12", + F2: "34", + F3: "56", + }, + F4: "100", + }) + require.NoError(t, err) + + rawMsg, err := message.Pack() + require.NoError(t, err) + + wantMsg := []byte("01007000000000000000164242424242424242123456000000000100") + require.Equal(t, wantMsg, rawMsg) + }) } func TestPackUnpack(t *testing.T) {