blob: 8df6249f0237678921f8cb486de0066aec51c8c6 [file] [log] [blame]
Abhay Kumara61c5222025-11-10 07:32:50 +00001// 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
bseeniva0b9cbcb2026-02-12 19:11:11 +053028// Next moves the iterator to the next position.
29// Next reports whether there are more attributes.
Abhay Kumara61c5222025-11-10 07:32:50 +000030func (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
bseeniva0b9cbcb2026-02-12 19:11:11 +0530109// Next moves the iterator to the next position.
110// Next reports whether there is another attribute available.
Abhay Kumara61c5222025-11-10 07:32:50 +0000111func (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.
144func (m *MergeIterator) Label() KeyValue {
145 return m.current
146}
147
148// Attribute returns the current value after Next() returns true.
149func (m *MergeIterator) Attribute() KeyValue {
150 return m.current
151}