1// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4package attribute // import "go.opentelemetry.io/otel/attribute"
5
6// Iterator allows iterating over the set of attributes in order, sorted by
7// key.
8type 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.
16type MergeIterator struct {
17 one oneIterator
18 two oneIterator
19 current KeyValue
20}
21
22type oneIterator struct {
23 iter Iterator
24 done bool
25 attr KeyValue
26}
27
28// Next moves the iterator to the next position. Returns false if there are no
29// more attributes.
30func (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.
39func (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.
45func (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.
54func (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.
60func (i *Iterator) IndexedAttribute() (int, KeyValue) {
61 return i.idx, i.Attribute()
62}
63
64// Len returns a number of attributes in the iterated set.
65func (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.
72func (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.
87func NewMergeIterator(s1, s2 *Set) MergeIterator {
88 mi := MergeIterator{
89 one: makeOne(s1.Iter()),
90 two: makeOne(s2.Iter()),
91 }
92 return mi
93}
94
95func makeOne(iter Iterator) oneIterator {
96 oi := oneIterator{
97 iter: iter,
98 }
99 oi.advance()
100 return oi
101}
102
103func (oi *oneIterator) advance() {
104 if oi.done = !oi.iter.Next(); !oi.done {
105 oi.attr = oi.iter.Attribute()
106 }
107}
108
109// Next returns true if there is another attribute available.
110func (m *MergeIterator) Next() bool {
111 if m.one.done && m.two.done {
112 return false
113 }
114 if m.one.done {
115 m.current = m.two.attr
116 m.two.advance()
117 return true
118 }
119 if m.two.done {
120 m.current = m.one.attr
121 m.one.advance()
122 return true
123 }
124 if m.one.attr.Key == m.two.attr.Key {
125 m.current = m.one.attr // first iterator attribute value wins
126 m.one.advance()
127 m.two.advance()
128 return true
129 }
130 if m.one.attr.Key < m.two.attr.Key {
131 m.current = m.one.attr
132 m.one.advance()
133 return true
134 }
135 m.current = m.two.attr
136 m.two.advance()
137 return true
138}
139
140// Label returns the current value after Next() returns true.
141//
142// Deprecated: Use Attribute instead.
143func (m *MergeIterator) Label() KeyValue {
144 return m.current
145}
146
147// Attribute returns the current value after Next() returns true.
148func (m *MergeIterator) Attribute() KeyValue {
149 return m.current
150}