forked from pingcap/tidb
/
capability.go
133 lines (112 loc) · 3.19 KB
/
capability.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
package mysql
import (
"fmt"
)
// Capabilities are indexed by name and can be one of 7 protobuf types (including nesting...).
// - see: mysqlx_datatypes.proto 'Type'
// So rather complex and messy even if in reality most combinations won't be used.
// - currently handled combinations are:
// - scalar string
// - scalar bool
// - array of string
type capabilityType uint8
const (
// CapabilityString is a string
CapabilityString capabilityType = iota
// CapabilityBool is a boolean
CapabilityBool
)
// ugly!
type capability struct {
capabilityType capabilityType
capabilityBool bool
capabilityString string
}
func (c *capability) Type() string {
var t string
if c != nil {
switch c.capabilityType {
case CapabilityBool:
t = "bool"
case CapabilityString:
t = "string"
}
}
return t
}
func (c *capability) String() string {
if c != nil && c.capabilityType == CapabilityString {
return c.capabilityString
}
return ""
}
func (c *capability) Bool() bool {
if c != nil && c.capabilityType == CapabilityBool {
return c.capabilityBool
}
return false
}
// Values contains an array of capabilities
type Values []capability
// ServerCapabilities is a named map of capability values
type ServerCapabilities map[string]Values
// NewServerCapabilities returns a structure containing the named capabilities of the server
func NewServerCapabilities() ServerCapabilities {
return make(map[string]Values)
}
// Exists returns true if the named capability exists
func (sc ServerCapabilities) Exists(name string) bool {
if sc == nil {
return false
}
_, found := sc[name]
return found
}
// Values returns the named Values
func (sc ServerCapabilities) Values(name string) Values {
if sc == nil {
return nil
}
// get the values
values, found := sc[name]
// not necessary to do this explicitly?
if !found {
return nil
}
return values
}
// AddScalarString adds the given string value to the named capability
func (sc ServerCapabilities) AddScalarString(name string, value string) error {
// debug.Msg("ServerCapabilities.AddScalarString(%q,%q)", name, value)
if sc == nil {
return fmt.Errorf("ServerCapabilities.AddScalarString() on nil value")
}
values := sc.Values(name)
values = append(values, capability{capabilityType: CapabilityString, capabilityString: value})
sc[name] = values
return nil
}
// AddScalarBool adds the given boolean value to the named capability
func (sc ServerCapabilities) AddScalarBool(name string, value bool) error {
// debug.Msg("ServerCapabilities.AddScalar(%q,%+v)", name, value)
if sc == nil {
return fmt.Errorf("ServerCapabilities.AddScalarBool() on nil value")
}
values := sc.Values(name)
values = append(values, capability{capabilityType: CapabilityBool, capabilityBool: value})
sc[name] = values
return nil
}
// AddArrayString adds the given array of strings to the named capability
func (sc ServerCapabilities) AddArrayString(name string, values []string) error {
// debug.Msg("ServerCapabilities.AddArrayString(%q,%+v)", name, values)
if sc == nil {
return fmt.Errorf("ServerCapabilities.AddArrayString() on nil value")
}
for i := range values {
if err := sc.AddScalarString(name, values[i]); err != nil {
return err
}
}
return nil
}