-
Notifications
You must be signed in to change notification settings - Fork 57
/
value_mapping.go
143 lines (118 loc) · 3.46 KB
/
value_mapping.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
139
140
141
142
143
package data
import (
"encoding/json"
"fmt"
"strings"
jsoniter "github.com/json-iterator/go"
)
// MappingType see https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/types/valueMapping.ts
type mappingType string
const (
valueToText mappingType = "value"
rangeToText mappingType = "range"
specialValue mappingType = "special"
)
type SpecialValueMatch string
const (
SpecialValueTrue SpecialValueMatch = "true"
SpecialValueFalse SpecialValueMatch = "false"
SpecialValueNull SpecialValueMatch = "null"
SpecialValueNaN SpecialValueMatch = "nan"
SpecialValueNullAndNaN SpecialValueMatch = "null+nan"
SpecialValueEmpty SpecialValueMatch = "empty"
)
// ValueMappingResult is the results from mapping a value
type ValueMappingResult struct {
Text string `json:"text,omitempty"`
Color string `json:"color,omitempty"`
Index int `json:"index,omitempty"` // just used ofr ui ordering
}
// ValueMapping allows mapping input values to text and color
type ValueMapping interface {
getType() mappingType
}
type ValueMappings []ValueMapping
// MarshalJSON writes the results as json
func (m ValueMappings) MarshalJSON() ([]byte, error) {
cfg := jsoniter.ConfigCompatibleWithStandardLibrary
stream := cfg.BorrowStream(nil)
defer cfg.ReturnStream(stream)
stream.WriteArrayStart()
for idx, v := range m {
if idx > 0 {
stream.WriteMore()
}
stream.WriteObjectStart()
stream.WriteObjectField("type")
stream.WriteString(string(v.getType()))
stream.WriteMore()
stream.WriteObjectField("options")
stream.WriteVal(v)
stream.WriteObjectEnd()
}
stream.WriteArrayEnd()
return append([]byte(nil), stream.Buffer()...), stream.Error
}
// UnmarshalJSON will read JSON into the appropriate go types
func (m *ValueMappings) UnmarshalJSON(b []byte) error {
iter := jsoniter.ParseBytes(jsoniter.ConfigDefault, b)
var mappings ValueMappings
for iter.ReadArray() {
var objMap map[string]json.RawMessage
iter.ReadVal(&objMap)
mt := mappingType(strings.Trim(string(objMap["type"]), `"`))
switch mt {
case valueToText:
var mapper ValueMapper
err := json.Unmarshal(objMap["options"], &mapper)
if err != nil {
return err
}
mappings = append(mappings, mapper)
case rangeToText:
var mapper RangeValueMapper
err := json.Unmarshal(objMap["options"], &mapper)
if err != nil {
return err
}
mappings = append(mappings, mapper)
case specialValue:
var mapper SpecialValueMapper
err := json.Unmarshal(objMap["options"], &mapper)
if err != nil {
return err
}
mappings = append(mappings, mapper)
default:
return fmt.Errorf("unknown mapping type: %s", mt)
}
}
*m = mappings
return iter.Error
}
// ValueMapper converts one set of strings to another
type ValueMapper map[string]ValueMappingResult
func (m ValueMapper) getType() mappingType {
return valueToText
}
type SpecialValueMapper struct {
Match SpecialValueMatch `json:"match"`
Result ValueMappingResult `json:"result"`
}
func (m SpecialValueMapper) getType() mappingType {
return specialValue
}
type RangeValueMapper struct {
From *ConfFloat64 `json:"from,omitempty"`
To *ConfFloat64 `json:"to,omitempty"`
Result ValueMappingResult `json:"result"`
}
func (m RangeValueMapper) getType() mappingType {
return rangeToText
}
// Make sure each type implements all required interfaces
var (
_ ValueMapping = (*ValueMapper)(nil)
_ ValueMapping = (*RangeValueMapper)(nil)
_ ValueMapping = (*SpecialValueMapper)(nil)
)