From b2fb4e8be99b1bcc027214e74d516dad8ad26788 Mon Sep 17 00:00:00 2001 From: Chris Busbey Date: Tue, 19 Apr 2016 14:07:03 -0500 Subject: [PATCH] fixes bug in unmarshalling group components --- marshal.go | 35 +---------------------------------- reflection.go | 30 ++++++++++++++++++++++++++++++ unmarshal.go | 9 ++------- unmarshal_test.go | 26 +++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/marshal.go b/marshal.go index e8a780ce5..d51af0865 100644 --- a/marshal.go +++ b/marshal.go @@ -2,8 +2,6 @@ package quickfix import ( "reflect" - "strconv" - "strings" "time" ) @@ -66,38 +64,7 @@ func (e encoder) encodeValue(fixTag Tag, v reflect.Value, omitEmpty bool, defaul panic("repeating group must be a slice of type struct") } - template := make(GroupTemplate, 0) - - var walkFunc func(t reflect.Type) - - walkFunc = func(t reflect.Type) { - for i := 0; i < t.NumField(); i++ { - sf := t.Field(i) - - //recurse if item is a component, optional or not - elementType := sf.Type - if elementType.Kind() == reflect.Ptr { - elementType = elementType.Elem() - } - - if elementType.Kind() == reflect.Struct { - walkFunc(elementType) - continue - } - - afixTag, err := strconv.Atoi(strings.Split(sf.Tag.Get("fix"), ",")[0]) - - if err != nil { - panic(err) - } - - template = append(template, GroupElement(Tag(afixTag))) - } - } - - walkFunc(elem) - - repeatingGroup := RepeatingGroup{Tag: fixTag, GroupTemplate: template} + repeatingGroup := RepeatingGroup{Tag: fixTag, GroupTemplate: buildGroupTemplate(elem)} for i := 0; i < v.Len(); i++ { group := repeatingGroup.Add() diff --git a/reflection.go b/reflection.go index caa7ebde0..162161d17 100644 --- a/reflection.go +++ b/reflection.go @@ -1,6 +1,7 @@ package quickfix import ( + "reflect" "strconv" "strings" ) @@ -28,3 +29,32 @@ func parseStructTag(goTag string) (tag Tag, omitEmpty bool, defaultVal *string) return } + +func buildGroupTemplate(elem reflect.Type) GroupTemplate { + template := make(GroupTemplate, 0) + + var walkFunc func(t reflect.Type) + + walkFunc = func(t reflect.Type) { + for i := 0; i < t.NumField(); i++ { + sf := t.Field(i) + + //recurse if item is a component, optional or not + elementType := sf.Type + if elementType.Kind() == reflect.Ptr { + elementType = elementType.Elem() + } + + if elementType.Kind() == reflect.Struct { + walkFunc(elementType) + continue + } + + afixTag, _, _ := parseStructTag(sf.Tag.Get("fix")) + template = append(template, GroupElement(Tag(afixTag))) + } + } + + walkFunc(elem) + return template +} diff --git a/unmarshal.go b/unmarshal.go index 245a1df2c..9d0352ab8 100644 --- a/unmarshal.go +++ b/unmarshal.go @@ -53,13 +53,8 @@ func (d decoder) decodeValue(fixTag Tag, t reflect.Type, v reflect.Value) Messag if elem.Kind() != reflect.Struct { panic("repeating group must be a slice of type struct") } - template := make(GroupTemplate, elem.NumField()) - for i := 0; i < elem.NumField(); i++ { - sf := elem.Field(i) - fixTag, _, _ := parseStructTag(sf.Tag.Get("fix")) - template[i] = GroupElement(fixTag) - } - repeatingGroup := RepeatingGroup{Tag: fixTag, GroupTemplate: template} + + repeatingGroup := RepeatingGroup{Tag: fixTag, GroupTemplate: buildGroupTemplate(elem)} if err := d.FieldMap.GetGroup(&repeatingGroup); err != nil { return err } diff --git a/unmarshal_test.go b/unmarshal_test.go index 1237e51b9..9f1064ba2 100644 --- a/unmarshal_test.go +++ b/unmarshal_test.go @@ -1,9 +1,10 @@ package quickfix_test import ( - "github.com/quickfixgo/quickfix" "testing" "time" + + "github.com/quickfixgo/quickfix" ) func TestUnmarshal_Literals(t *testing.T) { @@ -140,9 +141,22 @@ func TestUnmarshal_RepeatingGroups(t *testing.T) { StringField2 *string `fix:"9"` } + type AnonymousGroup struct { + IntField3 int `fix:"3"` + } + + type GroupComponent1 struct { + } + + type GroupComponent2 struct { + } + type Group2 struct { IntField1 int `fix:"1"` IntField2 int `fix:"2"` + AnonymousGroup + GroupComponent1 + OptionalComponent *GroupComponent2 } type Message struct { @@ -160,12 +174,22 @@ func TestUnmarshal_RepeatingGroups(t *testing.T) { quickfix.GroupElement(quickfix.Tag(9)), } + group2Template := quickfix.GroupTemplate{ + quickfix.GroupElement(quickfix.Tag(1)), + quickfix.GroupElement(quickfix.Tag(2)), + quickfix.GroupElement(quickfix.Tag(3)), + } + group1 := quickfix.RepeatingGroup{Tag: quickfix.Tag(100), GroupTemplate: group1Template} group1.Add().SetField(quickfix.Tag(8), quickfix.FIXString("hello")).SetField(quickfix.Tag(9), quickfix.FIXString("world")) group1.Add().SetField(quickfix.Tag(8), quickfix.FIXString("goodbye")) group1.Add().SetField(quickfix.Tag(8), quickfix.FIXString("OHHAI")).SetField(quickfix.Tag(9), quickfix.FIXString("world")) fixMsg.Body.SetGroup(group1) + group2 := quickfix.RepeatingGroup{Tag: quickfix.Tag(101), GroupTemplate: group2Template} + group2.Add().SetField(quickfix.Tag(1), quickfix.FIXInt(1)).SetField(quickfix.Tag(2), quickfix.FIXInt(2)) + fixMsg.Body.SetGroup(group2) + var msgOut Message quickfix.Unmarshal(fixMsg, &msgOut)