-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathkind.go
160 lines (121 loc) · 2.85 KB
/
kind.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package servers
import (
"encoding/json"
"errors"
"fmt"
"strings"
)
var ErrKindINETAndUNIX = errors.New("got both INET and UNIX kind")
type Kind uint8
const (
KindEmpty Kind = 0
KindINET = 1 << (iota - 1)
KindUNIX
KindHTTP
KindGRPC
)
var kindText = map[Kind]string{
KindEmpty: "unknown",
KindINET: "inet", // AF_INET
KindUNIX: "unix", // AF_UNIX
KindHTTP: "http",
KindGRPC: "gRPC",
}
// IsSingle is power of two algorithm.
func (knd Kind) IsSingle() bool {
return !knd.IsEmpty() && (knd&(knd-1) == 0)
}
func (knd Kind) IsEmpty() bool { return knd == KindEmpty }
func (knd Kind) Has(v Kind) bool { return (knd & v) != 0 }
func (knd *Kind) Set(v Kind) { *knd |= v }
func (knd *Kind) UnSet(v Kind) { *knd &= ^v }
func (knd Kind) String() string {
if knd.IsEmpty() {
return "~"
}
s, _ := knd.MarshalJSON()
return string(s)
}
func (knd Kind) StringTrySingle() string {
if knd.IsSingle() {
return kindText[knd]
}
return knd.String()
}
func (knd Kind) validate() error {
if knd.Has(KindINET) && knd.Has(KindUNIX) {
return ErrKindINETAndUNIX
}
return nil
}
func (knd *Kind) unmarshal(fn func(interface{}) error) error {
var (
raw string
rawSs []string
)
if err1 := fn(&raw); err1 != nil {
if err2 := fn(&rawSs); err2 != nil {
return fmt.Errorf("error unmarshal kind (%s): %w", err1, err2)
}
*knd = NewKindFromStringSlice(rawSs)
} else {
*knd = NewKindFromString(raw)
}
return knd.validate()
}
func (knd Kind) MarshalJSON() ([]byte, error) { return json.Marshal(knd.ToStringSlice()) }
func (knd Kind) MarshalYAML() (interface{}, error) { return knd.ToStringSlice(), nil }
func (knd *Kind) UnmarshalJSON(data []byte) error {
return knd.unmarshal(func(knd interface{}) error { return json.Unmarshal(data, knd) })
}
func (knd *Kind) UnmarshalYAML(unmarshal func(interface{}) error) error {
return knd.unmarshal(unmarshal)
}
func (knd Kind) ToStringSlice() (vv []string) {
if knd.Has(KindINET) {
vv = append(vv, kindText[KindINET])
}
if knd.Has(KindUNIX) {
vv = append(vv, kindText[KindUNIX])
}
if knd.Has(KindHTTP) {
vv = append(vv, kindText[KindHTTP])
}
if knd.Has(KindGRPC) {
vv = append(vv, kindText[KindGRPC])
}
return
}
func (knd Kind) NewServer() Server {
if knd.Has(KindUNIX) {
return new(ServerUNIX)
}
return new(ServerINET)
}
func NewKindFromStringSlice(vv []string) Kind {
knd := KindEmpty
for _, v := range vv {
knd.Set(NewKindFromString(v))
}
return knd
}
func NewKindFromString(v string) Kind {
v = strings.TrimSpace(v)
v = strings.ReplaceAll(v, "/", "")
v = strings.ReplaceAll(v, "\"", "")
v = strings.ReplaceAll(v, "'", "")
v = strings.ReplaceAll(v, "_", "-")
v = strings.ReplaceAll(v, " ", "-")
v = strings.ToLower(v)
switch v {
case "inet":
return KindINET
case "unix":
return KindUNIX
case "http":
return KindHTTP
case "grpc":
return KindGRPC
}
return KindEmpty
}