Skip to content

Commit c2bf2ba

Browse files
committed
Header, Body, Trailer FieldMap types (#138)
1 parent 82ce45c commit c2bf2ba

File tree

10 files changed

+103
-82
lines changed

10 files changed

+103
-82
lines changed

field_map.go

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package quickfix
22

33
import (
44
"bytes"
5-
"math"
65
"sort"
76
)
87

@@ -24,50 +23,14 @@ func (t tagSort) Len() int { return len(t.tags) }
2423
func (t tagSort) Swap(i, j int) { t.tags[i], t.tags[j] = t.tags[j], t.tags[i] }
2524
func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) }
2625

27-
//in the message header, the first 3 tags in the message header must be 8,9,35
28-
func headerFieldOrder(i, j Tag) bool {
29-
var ordering = func(t Tag) uint32 {
30-
switch t {
31-
case tagBeginString:
32-
return 1
33-
case tagBodyLength:
34-
return 2
35-
case tagMsgType:
36-
return 3
37-
}
38-
39-
return math.MaxUint32
40-
}
41-
42-
orderi := ordering(i)
43-
orderj := ordering(j)
44-
45-
switch {
46-
case orderi < orderj:
47-
return true
48-
case orderi > orderj:
49-
return false
50-
}
51-
52-
return i < j
53-
}
54-
55-
// In the body, ascending tags
26+
// ascending tags
5627
func normalFieldOrder(i, j Tag) bool { return i < j }
5728

58-
// In the trailer, CheckSum (tag 10) must be last
59-
func trailerFieldOrder(i, j Tag) bool {
60-
switch {
61-
case i == tagCheckSum:
62-
return false
63-
case j == tagCheckSum:
64-
return true
65-
}
66-
67-
return i < j
29+
func (m *FieldMap) init() {
30+
m.initWithOrdering(normalFieldOrder)
6831
}
6932

70-
func (m *FieldMap) init(ordering tagOrder) {
33+
func (m *FieldMap) initWithOrdering(ordering tagOrder) {
7134
m.tagLookup = make(map[Tag]TagValues)
7235
m.tagOrder = ordering
7336
}

field_map_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55
)
66

77
func TestFieldMap_Clear(t *testing.T) {
8-
fMap := FieldMap{}
9-
fMap.init(normalFieldOrder)
8+
var fMap FieldMap
9+
fMap.init()
1010

1111
fMap.SetField(1, FIXString("hello"))
1212
fMap.SetField(2, FIXString("world"))
@@ -19,8 +19,8 @@ func TestFieldMap_Clear(t *testing.T) {
1919
}
2020

2121
func TestFieldMap_SetAndGet(t *testing.T) {
22-
fMap := FieldMap{}
23-
fMap.init(normalFieldOrder)
22+
var fMap FieldMap
23+
fMap.init()
2424

2525
fMap.SetField(1, FIXString("hello"))
2626
fMap.SetField(2, FIXString("world"))
@@ -57,8 +57,8 @@ func TestFieldMap_SetAndGet(t *testing.T) {
5757
}
5858

5959
func TestFieldMap_Length(t *testing.T) {
60-
fMap := FieldMap{}
61-
fMap.init(normalFieldOrder)
60+
var fMap FieldMap
61+
fMap.init()
6262
fMap.SetField(1, FIXString("hello"))
6363
fMap.SetField(2, FIXString("world"))
6464
fMap.SetField(8, FIXString("FIX.4.4"))
@@ -72,8 +72,8 @@ func TestFieldMap_Length(t *testing.T) {
7272

7373
func TestFieldMap_Total(t *testing.T) {
7474

75-
fMap := FieldMap{}
76-
fMap.init(normalFieldOrder)
75+
var fMap FieldMap
76+
fMap.init()
7777
fMap.SetField(1, FIXString("hello"))
7878
fMap.SetField(2, FIXString("world"))
7979
fMap.SetField(8, FIXString("FIX.4.4"))

marshal.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ func Marshal(v interface{}) Message {
105105
}
106106
continue
107107
case "Header":
108-
e.FieldMap = m.Header
108+
e.FieldMap = m.Header.FieldMap
109109
case "Trailer":
110-
e.FieldMap = m.Trailer
110+
e.FieldMap = m.Trailer.FieldMap
111111
default:
112-
e.FieldMap = m.Body
112+
e.FieldMap = m.Body.FieldMap
113113
}
114114

115115
e.encodeField(sf, sf.Type, reflectValue.Field(i))

marshal_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,10 @@ func TestMarshal_HeaderTrailer(t *testing.T) {
351351
fixMsgPart quickfix.FieldMap
352352
expected []byte
353353
}{
354-
{quickfix.Tag(35), new(quickfix.FIXString), fixMsg.Header, []byte("0")},
355-
{quickfix.Tag(49), new(quickfix.FIXString), fixMsg.Header, []byte("hello")},
356-
{quickfix.Tag(112), new(quickfix.FIXString), fixMsg.Body, []byte("world")},
357-
{quickfix.Tag(89), new(quickfix.FIXInt), fixMsg.Trailer, []byte("3")},
354+
{quickfix.Tag(35), new(quickfix.FIXString), fixMsg.Header.FieldMap, []byte("0")},
355+
{quickfix.Tag(49), new(quickfix.FIXString), fixMsg.Header.FieldMap, []byte("hello")},
356+
{quickfix.Tag(112), new(quickfix.FIXString), fixMsg.Body.FieldMap, []byte("world")},
357+
{quickfix.Tag(89), new(quickfix.FIXInt), fixMsg.Trailer.FieldMap, []byte("3")},
358358
}
359359

360360
for _, test := range tests {

message.go

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,77 @@ package quickfix
33
import (
44
"bytes"
55
"fmt"
6+
"math"
67
"time"
78

89
"github.com/quickfixgo/quickfix/enum"
910
)
1011

12+
//Header is first section of a FIX Message
13+
type Header struct{ FieldMap }
14+
15+
//Init initializes the Header instance
16+
func (h *Header) Init() {
17+
//in the message header, the first 3 tags in the message header must be 8,9,35
18+
h.initWithOrdering(func(i, j Tag) bool {
19+
var ordering = func(t Tag) uint32 {
20+
switch t {
21+
case tagBeginString:
22+
return 1
23+
case tagBodyLength:
24+
return 2
25+
case tagMsgType:
26+
return 3
27+
}
28+
29+
return math.MaxUint32
30+
}
31+
32+
orderi := ordering(i)
33+
orderj := ordering(j)
34+
35+
switch {
36+
case orderi < orderj:
37+
return true
38+
case orderi > orderj:
39+
return false
40+
}
41+
42+
return i < j
43+
})
44+
}
45+
46+
//Body is the primary application section of a FIX message
47+
type Body struct{ FieldMap }
48+
49+
//Init initializes the FIX message
50+
func (b *Body) Init() {
51+
b.init()
52+
}
53+
54+
//Trailer is the last section of a FIX message
55+
type Trailer struct{ FieldMap }
56+
57+
//Init initializes the FIX message
58+
func (t *Trailer) Init() {
59+
// In the trailer, CheckSum (tag 10) must be last
60+
t.initWithOrdering(func(i, j Tag) bool {
61+
switch {
62+
case i == tagCheckSum:
63+
return false
64+
case j == tagCheckSum:
65+
return true
66+
}
67+
68+
return i < j
69+
})
70+
}
71+
1172
//Message is a FIX Message abstraction.
1273
type Message struct {
13-
Header FieldMap
14-
Trailer FieldMap
15-
Body FieldMap
74+
Header Header
75+
Trailer Trailer
76+
Body Body
1677

1778
//ReceiveTime is the time that this message was read from the socket connection
1879
ReceiveTime time.Time
@@ -38,15 +99,11 @@ func (e parseError) Error() string { return fmt.Sprintf("error parsing message:
3899

39100
//NewMessage returns a newly initialized Message instance
40101
func NewMessage() (m Message) {
41-
m.Init()
42-
return
43-
}
102+
m.Header.Init()
103+
m.Body.Init()
104+
m.Trailer.Init()
44105

45-
//Init initializes the Message instance
46-
func (m *Message) Init() {
47-
m.Header.init(headerFieldOrder)
48-
m.Body.init(normalFieldOrder)
49-
m.Trailer.init(trailerFieldOrder)
106+
return
50107
}
51108

52109
//ParseMessage constructs a Message from a byte slice wrapping a FIX message.

repeating_group.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (f RepeatingGroup) Get(i int) Group {
7777
//Add appends a new group to the RepeatingGroup and returns the new Group
7878
func (f *RepeatingGroup) Add() Group {
7979
var g Group
80-
g.init(f.groupTagOrder())
80+
g.initWithOrdering(f.groupTagOrder())
8181

8282
f.groups = append(f.groups, g)
8383
return g
@@ -157,7 +157,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
157157
tv = tv[1:cap(tv)]
158158
tagOrdering := f.groupTagOrder()
159159
var group Group
160-
group.init(tagOrdering)
160+
group.initWithOrdering(tagOrdering)
161161
for len(tv) > 0 {
162162
field, ok := f.findItemInGroupTemplate(tv[0].tag)
163163
if !ok {
@@ -171,7 +171,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
171171

172172
if f.isDelimiter(field.Tag()) {
173173
group = Group{}
174-
group.init(tagOrdering)
174+
group.initWithOrdering(tagOrdering)
175175

176176
f.groups = append(f.groups, group)
177177
}

session.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package quickfix
22

33
import (
44
"fmt"
5+
"sync"
6+
"time"
7+
58
"github.com/quickfixgo/quickfix/config"
69
"github.com/quickfixgo/quickfix/datadictionary"
710
"github.com/quickfixgo/quickfix/enum"
8-
"sync"
9-
"time"
1011
)
1112

1213
//The Session is the primary FIX abstraction for message communication
@@ -152,7 +153,7 @@ func (s *session) onDisconnect() {
152153
s.log.OnEvent("Disconnected")
153154
}
154155

155-
func (s *session) insertSendingTime(header FieldMap) {
156+
func (s *session) insertSendingTime(header Header) {
156157
sendingTime := time.Now().UTC()
157158

158159
if s.sessionID.BeginString >= enum.BeginStringFIX42 {

session_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package quickfix
22

33
import (
4-
"github.com/quickfixgo/quickfix/enum"
54
"testing"
65
"time"
6+
7+
"github.com/quickfixgo/quickfix/enum"
78
)
89

910
func buildMessage() Message {
10-
builder := Message{}
11-
builder.Init()
11+
builder := NewMessage()
1212
builder.Header.SetField(tagBeginString, FIXString(enum.BeginStringFIX40))
1313
builder.Header.SetField(tagMsgType, FIXString("D"))
1414
return builder

unmarshal.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ func Unmarshal(m Message, v interface{}) MessageRejectError {
124124
case "FIXMsgType":
125125
continue
126126
case "Header":
127-
d.FieldMap = m.Header
127+
d.FieldMap = m.Header.FieldMap
128128
case "Trailer":
129-
d.FieldMap = m.Trailer
129+
d.FieldMap = m.Trailer.FieldMap
130130
default:
131-
d.FieldMap = m.Body
131+
d.FieldMap = m.Body.FieldMap
132132
}
133133

134134
if err := d.decodeField(sf, sf.Type, sv); err != nil {

validation.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,15 @@ func validateOrder(msg Message) MessageRejectError {
242242
}
243243

244244
func validateRequired(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message Message) MessageRejectError {
245-
if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header); err != nil {
245+
if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header.FieldMap); err != nil {
246246
return err
247247
}
248248

249-
if err := validateRequiredFieldMap(message, appDD.Messages[msgType].RequiredTags, message.Body); err != nil {
249+
if err := validateRequiredFieldMap(message, appDD.Messages[msgType].RequiredTags, message.Body.FieldMap); err != nil {
250250
return err
251251
}
252252

253-
if err := validateRequiredFieldMap(message, transportDD.Trailer.RequiredTags, message.Trailer); err != nil {
253+
if err := validateRequiredFieldMap(message, transportDD.Trailer.RequiredTags, message.Trailer.FieldMap); err != nil {
254254
return err
255255
}
256256

0 commit comments

Comments
 (0)