GoPLS Viewer

Home|gopls/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
5package label
6
7import (
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.
17type 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.Writerbuf []bytel Label)
28}
29
30// Label holds a key and value pair.
31// It is normally used when passing around lists of labels.
32type 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.
39type Map interface {
40    // Find returns the label that matches the supplied key.
41    Find(key KeyLabel
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.
47type 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 intbool
51    // Label returns the label at the given index.
52    Label(index intLabel
53}
54
55// list implements LabelList for a list of Labels.
56type list struct {
57    labels []Label
58}
59
60// filter wraps a LabelList filtering out specific labels.
61type filter struct {
62    keys       []Key
63    underlying List
64}
65
66// listMap implements LabelMap for a simple list of labels.
67type listMap struct {
68    labels []Label
69}
70
71// mapChain implements LabelMap for a list of underlying LabelMap.
72type 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.
79func OfValue(k Keyvalue interface{}) Label { return Label{keykuntypedvalue} }
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.
85func (t LabelUnpackValue() 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.
91func Of64(k Keyv uint64Label { return Label{keykpackedv} }
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.
97func (t LabelUnpack64() uint64 { return t.packed }
98
99type stringptr unsafe.Pointer
100
101// OfString creates a new label from a key and a string.
102// This method is for implementing new key types, label creation should
103// normally be done with the Of method of the key.
104func OfString(k Keyv stringLabel {
105    hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
106    return Label{
107        key:     k,
108        packed:  uint64(hdr.Len),
109        untypedstringptr(hdr.Data),
110    }
111}
112
113// UnpackString assumes the label was built using LabelOfString and returns the
114// value that was passed to that constructor.
115// This method is for implementing new key types, for type safety normal
116// access should be done with the From method of the key.
117func (t LabelUnpackString() string {
118    var v string
119    hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
120    hdr.Data = uintptr(t.untyped.(stringptr))
121    hdr.Len = int(t.packed)
122    return v
123}
124
125// Valid returns true if the Label is a valid one (it has a key).
126func (t LabelValid() bool { return t.key != nil }
127
128// Key returns the key of this Label.
129func (t LabelKey() Key { return t.key }
130
131// Format is used for debug printing of labels.
132func (t LabelFormat(f fmt.Stater rune) {
133    if !t.Valid() {
134        io.WriteString(f`nil`)
135        return
136    }
137    io.WriteString(ft.Key().Name())
138    io.WriteString(f"=")
139    var buf [128]byte
140    t.Key().Format(fbuf[:0], t)
141}
142
143func (l *listValid(index intbool {
144    return index >= 0 && index < len(l.labels)
145}
146
147func (l *listLabel(index intLabel {
148    return l.labels[index]
149}
150
151func (f *filterValid(index intbool {
152    return f.underlying.Valid(index)
153}
154
155func (f *filterLabel(index intLabel {
156    l := f.underlying.Label(index)
157    for _f := range f.keys {
158        if l.Key() == f {
159            return Label{}
160        }
161    }
162    return l
163}
164
165func (lm listMapFind(key KeyLabel {
166    for _l := range lm.labels {
167        if l.Key() == key {
168            return l
169        }
170    }
171    return Label{}
172}
173
174func (c mapChainFind(key KeyLabel {
175    for _src := range c.maps {
176        l := src.Find(key)
177        if l.Valid() {
178            return l
179        }
180    }
181    return Label{}
182}
183
184var emptyList = &list{}
185
186func NewList(labels ...LabelList {
187    if len(labels) == 0 {
188        return emptyList
189    }
190    return &list{labelslabels}
191}
192
193func Filter(l Listkeys ...KeyList {
194    if len(keys) == 0 {
195        return l
196    }
197    return &filter{keyskeysunderlyingl}
198}
199
200func NewMap(labels ...LabelMap {
201    return listMap{labelslabels}
202}
203
204func MergeMaps(srcs ...MapMap {
205    var nonNil []Map
206    for _src := range srcs {
207        if src != nil {
208            nonNil = append(nonNilsrc)
209        }
210    }
211    if len(nonNil) == 1 {
212        return nonNil[0]
213    }
214    return mapChain{mapsnonNil}
215}
216
MembersX
Label.untyped
Of64.k
Label.Format.f
list.Valid
NewList
Filter.keys
mapChain.Find.key
NewMap
fmt
io
Label.UnpackValue
stringptr
Label.Valid
Label.Key
filter.Valid.f
MergeMaps.nonNil
listMap.labels
filter.Label.RangeStmt_4792.f
Label.Format
filter.Label.f
mapChain.Find.c
Filter
reflect
listMap
Label.Format.r
filter.Valid
listMap.Find.lm
NewList.labels
MergeMaps.RangeStmt_5538.src
Label.packed
list
OfValue
Of64
list.Valid.l
MergeMaps
mapChain.Find.RangeStmt_5049.BlockStmt.l
Label.Unpack64.t
OfString
Label.Key.t
list.Valid.index
filter.Valid.index
filter.Label.l
listMap.Find.key
Label.key
filter.keys
mapChain.maps
Label.UnpackString.t
list.Label
list.Label.index
unsafe
Label
mapChain
Label.UnpackValue.t
OfString.hdr
mapChain.Find.RangeStmt_5049.src
Map
List
OfValue.k
OfString.k
Label.Format.buf
filter.Label.index
listMap.Find.RangeStmt_4918.l
list.labels
Of64.v
Label.Unpack64
Label.UnpackString
Label.UnpackString.v
Label.Valid.t
Filter.l
NewMap.labels
MergeMaps.srcs
filter.Label
mapChain.Find
Key
filter
OfValue.value
Label.UnpackString.hdr
Label.Format.t
list.Label.l
filter.underlying
OfString.v
listMap.Find
Members
X