Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / mvdan.cc / gofumpt@v0.0.0-20200802201014-ab5a8192947d / gofumports / internal / event / label / label.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package label
6
7 import (
8         "fmt"
9         "io"
10         "reflect"
11         "unsafe"
12 )
13
14 // Key is used as the identity of a Label.
15 // Keys are intended to be compared by pointer only, the name should be unique
16 // for communicating with external systems, but it is not required or enforced.
17 type Key interface {
18         // Name returns the key name.
19         Name() string
20         // Description returns a string that can be used to describe the value.
21         Description() string
22
23         // Format is used in formatting to append the value of the label to the
24         // supplied buffer.
25         // The formatter may use the supplied buf as a scratch area to avoid
26         // allocations.
27         Format(w io.Writer, buf []byte, l Label)
28 }
29
30 // Label holds a key and value pair.
31 // It is normally used when passing around lists of labels.
32 type Label struct {
33         key     Key
34         packed  uint64
35         untyped interface{}
36 }
37
38 // Map is the interface to a collection of Labels indexed by key.
39 type Map interface {
40         // Find returns the label that matches the supplied key.
41         Find(key Key) Label
42 }
43
44 // List is the interface to something that provides an iterable
45 // list of labels.
46 // Iteration should start from 0 and continue until Valid returns false.
47 type List interface {
48         // Valid returns true if the index is within range for the list.
49         // It does not imply the label at that index will itself be valid.
50         Valid(index int) bool
51         // Label returns the label at the given index.
52         Label(index int) Label
53 }
54
55 // list implements LabelList for a list of Labels.
56 type list struct {
57         labels []Label
58 }
59
60 // filter wraps a LabelList filtering out specific labels.
61 type filter struct {
62         keys       []Key
63         underlying List
64 }
65
66 // listMap implements LabelMap for a simple list of labels.
67 type listMap struct {
68         labels []Label
69 }
70
71 // mapChain implements LabelMap for a list of underlying LabelMap.
72 type mapChain struct {
73         maps []Map
74 }
75
76 // OfValue creates a new label from the key and value.
77 // This method is for implementing new key types, label creation should
78 // normally be done with the Of method of the key.
79 func OfValue(k Key, value interface{}) Label { return Label{key: k, untyped: value} }
80
81 // UnpackValue assumes the label was built using LabelOfValue and returns the value
82 // that was passed to that constructor.
83 // This method is for implementing new key types, for type safety normal
84 // access should be done with the From method of the key.
85 func (t Label) UnpackValue() interface{} { return t.untyped }
86
87 // Of64 creates a new label from a key and a uint64. This is often
88 // used for non uint64 values that can be packed into a uint64.
89 // This method is for implementing new key types, label creation should
90 // normally be done with the Of method of the key.
91 func Of64(k Key, v uint64) Label { return Label{key: k, packed: v} }
92
93 // Unpack64 assumes the label was built using LabelOf64 and returns the value that
94 // was passed to that constructor.
95 // This method is for implementing new key types, for type safety normal
96 // access should be done with the From method of the key.
97 func (t Label) Unpack64() uint64 { return t.packed }
98
99 // OfString creates a new label from a key and a string.
100 // This method is for implementing new key types, label creation should
101 // normally be done with the Of method of the key.
102 func OfString(k Key, v string) Label {
103         hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
104         return Label{
105                 key:     k,
106                 packed:  uint64(hdr.Len),
107                 untyped: unsafe.Pointer(hdr.Data),
108         }
109 }
110
111 // UnpackString assumes the label was built using LabelOfString and returns the
112 // value that was passed to that constructor.
113 // This method is for implementing new key types, for type safety normal
114 // access should be done with the From method of the key.
115 func (t Label) UnpackString() string {
116         var v string
117         hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
118         hdr.Data = uintptr(t.untyped.(unsafe.Pointer))
119         hdr.Len = int(t.packed)
120         return *(*string)(unsafe.Pointer(hdr))
121 }
122
123 // Valid returns true if the Label is a valid one (it has a key).
124 func (t Label) Valid() bool { return t.key != nil }
125
126 // Key returns the key of this Label.
127 func (t Label) Key() Key { return t.key }
128
129 // Format is used for debug printing of labels.
130 func (t Label) Format(f fmt.State, r rune) {
131         if !t.Valid() {
132                 io.WriteString(f, `nil`)
133                 return
134         }
135         io.WriteString(f, t.Key().Name())
136         io.WriteString(f, "=")
137         var buf [128]byte
138         t.Key().Format(f, buf[:0], t)
139 }
140
141 func (l *list) Valid(index int) bool {
142         return index >= 0 && index < len(l.labels)
143 }
144
145 func (l *list) Label(index int) Label {
146         return l.labels[index]
147 }
148
149 func (f *filter) Valid(index int) bool {
150         return f.underlying.Valid(index)
151 }
152
153 func (f *filter) Label(index int) Label {
154         l := f.underlying.Label(index)
155         for _, f := range f.keys {
156                 if l.Key() == f {
157                         return Label{}
158                 }
159         }
160         return l
161 }
162
163 func (lm listMap) Find(key Key) Label {
164         for _, l := range lm.labels {
165                 if l.Key() == key {
166                         return l
167                 }
168         }
169         return Label{}
170 }
171
172 func (c mapChain) Find(key Key) Label {
173         for _, src := range c.maps {
174                 l := src.Find(key)
175                 if l.Valid() {
176                         return l
177                 }
178         }
179         return Label{}
180 }
181
182 var emptyList = &list{}
183
184 func NewList(labels ...Label) List {
185         if len(labels) == 0 {
186                 return emptyList
187         }
188         return &list{labels: labels}
189 }
190
191 func Filter(l List, keys ...Key) List {
192         if len(keys) == 0 {
193                 return l
194         }
195         return &filter{keys: keys, underlying: l}
196 }
197
198 func NewMap(labels ...Label) Map {
199         return listMap{labels: labels}
200 }
201
202 func MergeMaps(srcs ...Map) Map {
203         var nonNil []Map
204         for _, src := range srcs {
205                 if src != nil {
206                         nonNil = append(nonNil, src)
207                 }
208         }
209         if len(nonNil) == 1 {
210                 return nonNil[0]
211         }
212         return mapChain{maps: nonNil}
213 }