-
Notifications
You must be signed in to change notification settings - Fork 7
/
Instance.go
138 lines (115 loc) · 3.49 KB
/
Instance.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package interpreters
import (
"bytes"
"sort"
)
// Instance is one instantiated interpreter for a data block,
// based on a predetermined description.
type Instance struct {
desc *Description
data []byte
}
// Raw returns the raw array.
func (inst *Instance) Raw() []byte {
return inst.data
}
// Undefined returns a byte array that specifies which bits were not
// specified. The array has the same length as the underlying buffer and
// has all bits set to 1 where no field or active refinement is present.
func (inst *Instance) Undefined() []byte {
mask := bytes.Repeat([]byte{0xFF}, len(inst.data))
for _, e := range inst.desc.fields {
if inst.isValidRange(e) {
copy(mask[e.start:e.start+e.count], bytes.Repeat([]byte{0x00}, e.count))
}
}
for key, r := range inst.desc.refinements {
if r.predicate(inst) {
refined := inst.Refined(key)
subMask := refined.Undefined()
for index, m := range subMask {
mask[r.start+index] &= m
}
}
}
return mask
}
// Keys returns an array of all registered keys, sorted by start index
func (inst *Instance) Keys() []string {
return sortKeys(inst.desc.fields)
}
// ActiveRefinements returns an array of all keys where the corresponding refinement
// is active (The corresponding predicate returns true).
func (inst *Instance) ActiveRefinements() (keys []string) {
entries := make(map[string]*entry)
for key, r := range inst.desc.refinements {
entries[key] = &r.entry
}
sortedKeys := sortKeys(entries)
for _, key := range sortedKeys {
if inst.desc.refinements[key].predicate(inst) {
keys = append(keys, key)
}
}
return
}
// Get returns the value associated with the given key. Should there be no
// value for the requested key, the function returns 0.
func (inst *Instance) Get(key string) uint32 {
e := inst.desc.fields[key]
value := uint32(0)
if e != nil && inst.isValidRange(e) {
for i := 0; i < e.count; i++ {
value = (value << 8) | uint32(inst.data[e.start+e.count-1-i])
}
}
return value
}
// Describe returns the description of a value key.
func (inst *Instance) Describe(key string, simplifier *Simplifier) {
e := inst.desc.fields[key]
if e != nil && inst.isValidRange(e) {
e.describe(simplifier)
}
}
// Set stores the provided value with the given key. Should there be no
// registration for the key, the function does nothing.
func (inst *Instance) Set(key string, value uint32) {
e := inst.desc.fields[key]
if e != nil && inst.isValidRange(e) {
for i := 0; i < e.count; i++ {
inst.data[e.start+i] = byte(value >> uint32(i*8))
}
}
}
// Refined returns an instance that was nested according to the description.
// This method returns an instance for registered refinements even if their predicate
// would not specify them being active.
// Should the refinement not exist, an instance without any fields will be returned.
func (inst *Instance) Refined(key string) (refined *Instance) {
r := inst.desc.refinements[key]
if r != nil && inst.isValidRange(&r.entry) {
refined = &Instance{
desc: r.desc,
data: inst.data[r.start : r.start+r.count]}
} else {
refined = New().For(nil)
}
return
}
func (inst *Instance) isValidRange(e *entry) bool {
available := len(inst.data)
return (e.start + e.count) <= available
}
func sortKeys(entries map[string]*entry) []string {
keys := make([]string, 0, len(entries))
for key := range entries {
keys = append(keys, key)
}
sort.Slice(keys, func(a, b int) bool {
entryA := entries[keys[a]]
entryB := entries[keys[b]]
return entryA.start < entryB.start
})
return keys
}