Skip to content

Commit

Permalink
Update message.Marshal message to accept structs with Go's native types
Browse files Browse the repository at this point in the history
  • Loading branch information
mfdeveloper508 committed Oct 2, 2023
1 parent dc7902c commit 48a45be
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 16 deletions.
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() { //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)
}
}

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
4 changes: 2 additions & 2 deletions field/composite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
24 changes: 17 additions & 7 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ func (m *Message) Marshal(v interface{}) error {
}

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

Expand Down Expand Up @@ -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)
}
}

Expand Down
82 changes: 82 additions & 0 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 48a45be

Please sign in to comment.