-
Notifications
You must be signed in to change notification settings - Fork 16
/
array.go
106 lines (89 loc) · 2.24 KB
/
array.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package xml
import (
"encoding/xml"
"github.com/jexia/semaphore/v2/pkg/references"
"github.com/jexia/semaphore/v2/pkg/specs"
)
// Array represents an array of values/references.
type Array struct {
name, path string
template specs.Template
repeated specs.Template
store references.Store
tracker references.Tracker
}
// NewArray constructs a new XML array encoder/decoder.
func NewArray(name, path string, template specs.Template, store references.Store, tracker references.Tracker) *Array {
// TODO: find a better implementation/name
combi, err := template.Repeated.Template()
if err != nil {
panic(err)
}
return &Array{
name: name,
path: path,
template: combi,
repeated: template,
store: store,
tracker: tracker,
}
}
// MarshalXML encodes the given specs object into the provided XML encoder.
func (array *Array) MarshalXML(encoder *xml.Encoder, _ xml.StartElement) error {
if array.repeated.Reference == nil {
ptrack := array.tracker.Resolve(array.path)
array.tracker.Track(ptrack, 0)
for _, item := range array.repeated.Repeated {
if err := encodeElement(
encoder,
array.name,
array.path,
item,
array.store,
array.tracker,
); err != nil {
return err
}
array.tracker.Next(ptrack)
}
return nil
}
length := array.store.Length(array.tracker.Resolve(array.repeated.Reference.String()))
if length == 0 {
return nil
}
ptrack := array.tracker.Resolve(array.path)
array.tracker.Track(ptrack, 0)
for index := 0; index < length; index++ {
if err := encodeElement(
encoder,
array.name,
specs.JoinPath(array.path, array.name),
array.template,
array.store,
array.tracker,
); err != nil {
return err
}
array.tracker.Next(ptrack)
}
return nil
}
// UnmarshalXML decodes XML input into the receiver of type specs.Repeated.
func (array *Array) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
var (
path = specs.JoinPath(array.path, array.name)
index = array.store.Length(array.tracker.Resolve(path))
)
array.tracker.Track(path, index)
array.store.Define(array.tracker.Resolve(path), index+1)
return decodeElement(
decoder,
start,
array.name,
array.path,
array.template,
array.store,
array.tracker,
)
}