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 / telemetry / event / tag.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 event
6
7 import (
8         "fmt"
9         "io"
10         "reflect"
11         "unsafe"
12 )
13
14 // Tag holds a key and value pair.
15 // It is normally used when passing around lists of tags.
16 type Tag struct {
17         key     Key
18         packed  uint64
19         untyped interface{}
20 }
21
22 // TagMap is the interface to a collection of Tags indexed by key.
23 type TagMap interface {
24         // Find returns the tag that matches the supplied key.
25         Find(key Key) Tag
26 }
27
28 // TagList is the interface to something that provides an iterable
29 // list of tags.
30 // Iteration should start from 0 and continue until Valid returns false.
31 type TagList interface {
32         // Valid returns true if the index is within range for the list.
33         // It does not imply the tag at that index will itself be valid.
34         Valid(index int) bool
35         // Tag returns the tag at the given index.
36         Tag(index int) Tag
37 }
38
39 // tagList implements TagList for a list of Tags.
40 type tagList struct {
41         tags []Tag
42 }
43
44 // tagFilter wraps a TagList filtering out specific tags.
45 type tagFilter struct {
46         keys       []Key
47         underlying TagList
48 }
49
50 // tagMap implements TagMap for a simple list of tags.
51 type tagMap struct {
52         tags []Tag
53 }
54
55 // tagMapChain implements TagMap for a list of underlying TagMap.
56 type tagMapChain struct {
57         maps []TagMap
58 }
59
60 // TagOfValue creates a new tag from the key and value.
61 // This method is for implementing new key types, tag creation should
62 // normally be done with the Of method of the key.
63 func TagOfValue(k Key, value interface{}) Tag { return Tag{key: k, untyped: value} }
64
65 // UnpackValue assumes the tag was built using TagOfValue and returns the value
66 // that was passed to that constructor.
67 // This method is for implementing new key types, for type safety normal
68 // access should be done with the From method of the key.
69 func (t Tag) UnpackValue() interface{} { return t.untyped }
70
71 // TagOf64 creates a new tag from a key and a uint64. This is often
72 // used for non uint64 values that can be packed into a uint64.
73 // This method is for implementing new key types, tag creation should
74 // normally be done with the Of method of the key.
75 func TagOf64(k Key, v uint64) Tag { return Tag{key: k, packed: v} }
76
77 // Unpack64 assumes the tag was built using TagOf64 and returns the value that
78 // was passed to that constructor.
79 // This method is for implementing new key types, for type safety normal
80 // access should be done with the From method of the key.
81 func (t Tag) Unpack64() uint64 { return t.packed }
82
83 // TagOfString creates a new tag from a key and a string.
84 // This method is for implementing new key types, tag creation should
85 // normally be done with the Of method of the key.
86 func TagOfString(k Key, v string) Tag {
87         hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
88         return Tag{
89                 key:     k,
90                 packed:  uint64(hdr.Len),
91                 untyped: unsafe.Pointer(hdr.Data),
92         }
93 }
94
95 // UnpackString assumes the tag was built using TagOfString and returns the
96 // value that was passed to that constructor.
97 // This method is for implementing new key types, for type safety normal
98 // access should be done with the From method of the key.
99 func (t Tag) UnpackString() string {
100         var v string
101         hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
102         hdr.Data = uintptr(t.untyped.(unsafe.Pointer))
103         hdr.Len = int(t.packed)
104         return *(*string)(unsafe.Pointer(hdr))
105 }
106
107 // Valid returns true if the Tag is a valid one (it has a key).
108 func (t Tag) Valid() bool { return t.key != nil }
109
110 // Key returns the key of this Tag.
111 func (t Tag) Key() Key { return t.key }
112
113 // Format is used for debug printing of tags.
114 func (t Tag) Format(f fmt.State, r rune) {
115         if !t.Valid() {
116                 io.WriteString(f, `nil`)
117                 return
118         }
119         io.WriteString(f, t.Key().Name())
120         io.WriteString(f, "=")
121         var buf [128]byte
122         t.Key().Format(f, buf[:0], t)
123 }
124
125 func (l *tagList) Valid(index int) bool {
126         return index >= 0 && index < len(l.tags)
127 }
128
129 func (l *tagList) Tag(index int) Tag {
130         return l.tags[index]
131 }
132
133 func (f *tagFilter) Valid(index int) bool {
134         return f.underlying.Valid(index)
135 }
136
137 func (f *tagFilter) Tag(index int) Tag {
138         tag := f.underlying.Tag(index)
139         for _, f := range f.keys {
140                 if tag.Key() == f {
141                         return Tag{}
142                 }
143         }
144         return tag
145 }
146
147 func (l tagMap) Find(key Key) Tag {
148         for _, tag := range l.tags {
149                 if tag.Key() == key {
150                         return tag
151                 }
152         }
153         return Tag{}
154 }
155
156 func (c tagMapChain) Find(key Key) Tag {
157         for _, src := range c.maps {
158                 tag := src.Find(key)
159                 if tag.Valid() {
160                         return tag
161                 }
162         }
163         return Tag{}
164 }
165
166 var emptyList = &tagList{}
167
168 func NewTagList(tags ...Tag) TagList {
169         if len(tags) == 0 {
170                 return emptyList
171         }
172         return &tagList{tags: tags}
173 }
174
175 func Filter(l TagList, keys ...Key) TagList {
176         if len(keys) == 0 {
177                 return l
178         }
179         return &tagFilter{keys: keys, underlying: l}
180 }
181
182 func NewTagMap(tags ...Tag) TagMap {
183         return tagMap{tags: tags}
184 }
185
186 func MergeTagMaps(srcs ...TagMap) TagMap {
187         var nonNil []TagMap
188         for _, src := range srcs {
189                 if src != nil {
190                         nonNil = append(nonNil, src)
191                 }
192         }
193         if len(nonNil) == 1 {
194                 return nonNil[0]
195         }
196         return tagMapChain{maps: nonNil}
197 }