label.go 5.6 KB

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