1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3 4 package attribute // import "go.opentelemetry.io/otel/attribute"
5 6 // Iterator allows iterating over the set of attributes in order, sorted by
7 // key.
8 type Iterator struct {
9 storage *Set
10 idx int
11 }
12 13 // MergeIterator supports iterating over two sets of attributes while
14 // eliminating duplicate values from the combined set. The first iterator
15 // value takes precedence.
16 type MergeIterator struct {
17 one oneIterator
18 two oneIterator
19 current KeyValue
20 }
21 22 type oneIterator struct {
23 iter Iterator
24 done bool
25 attr KeyValue
26 }
27 28 // Next moves the iterator to the next position.
29 // Next reports whether there are more attributes.
30 func (i *Iterator) Next() bool {
31 i.idx++
32 return i.idx < i.Len()
33 }
34 35 // Label returns current KeyValue. Must be called only after Next returns
36 // true.
37 //
38 // Deprecated: Use Attribute instead.
39 func (i *Iterator) Label() KeyValue {
40 return i.Attribute()
41 }
42 43 // Attribute returns the current KeyValue of the Iterator. It must be called
44 // only after Next returns true.
45 func (i *Iterator) Attribute() KeyValue {
46 kv, _ := i.storage.Get(i.idx)
47 return kv
48 }
49 50 // IndexedLabel returns current index and attribute. Must be called only
51 // after Next returns true.
52 //
53 // Deprecated: Use IndexedAttribute instead.
54 func (i *Iterator) IndexedLabel() (int, KeyValue) {
55 return i.idx, i.Attribute()
56 }
57 58 // IndexedAttribute returns current index and attribute. Must be called only
59 // after Next returns true.
60 func (i *Iterator) IndexedAttribute() (int, KeyValue) {
61 return i.idx, i.Attribute()
62 }
63 64 // Len returns a number of attributes in the iterated set.
65 func (i *Iterator) Len() int {
66 return i.storage.Len()
67 }
68 69 // ToSlice is a convenience function that creates a slice of attributes from
70 // the passed iterator. The iterator is set up to start from the beginning
71 // before creating the slice.
72 func (i *Iterator) ToSlice() []KeyValue {
73 l := i.Len()
74 if l == 0 {
75 return nil
76 }
77 i.idx = -1
78 slice := make([]KeyValue, 0, l)
79 for i.Next() {
80 slice = append(slice, i.Attribute())
81 }
82 return slice
83 }
84 85 // NewMergeIterator returns a MergeIterator for merging two attribute sets.
86 // Duplicates are resolved by taking the value from the first set.
87 func NewMergeIterator(s1, s2 *Set) MergeIterator {
88 mi := MergeIterator{
89 one: makeOne(s1.Iter()),
90 two: makeOne(s2.Iter()),
91 }
92 return mi
93 }
94 95 func makeOne(iter Iterator) oneIterator {
96 oi := oneIterator{
97 iter: iter,
98 }
99 oi.advance()
100 return oi
101 }
102 103 func (oi *oneIterator) advance() {
104 if oi.done = !oi.iter.Next(); !oi.done {
105 oi.attr = oi.iter.Attribute()
106 }
107 }
108 109 // Next moves the iterator to the next position.
110 // Next reports whether there is another attribute available.
111 func (m *MergeIterator) Next() bool {
112 if m.one.done && m.two.done {
113 return false
114 }
115 if m.one.done {
116 m.current = m.two.attr
117 m.two.advance()
118 return true
119 }
120 if m.two.done {
121 m.current = m.one.attr
122 m.one.advance()
123 return true
124 }
125 if m.one.attr.Key == m.two.attr.Key {
126 m.current = m.one.attr // first iterator attribute value wins
127 m.one.advance()
128 m.two.advance()
129 return true
130 }
131 if m.one.attr.Key < m.two.attr.Key {
132 m.current = m.one.attr
133 m.one.advance()
134 return true
135 }
136 m.current = m.two.attr
137 m.two.advance()
138 return true
139 }
140 141 // Label returns the current value after Next() returns true.
142 //
143 // Deprecated: Use Attribute instead.
144 func (m *MergeIterator) Label() KeyValue {
145 return m.current
146 }
147 148 // Attribute returns the current value after Next() returns true.
149 func (m *MergeIterator) Attribute() KeyValue {
150 return m.current
151 }
152