1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2026-06-03 18:35:08 +02:00
Files
opentelemetry-go/trace/tracestate.go
T
renovate[bot] a18614cbc2 chore(deps): update module github.com/securego/gosec/v2 to v2.24.7 (#7988)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[github.com/securego/gosec/v2](https://redirect.github.com/securego/gosec)
| `v2.23.0` → `v2.24.7` |
![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fsecurego%2fgosec%2fv2/v2.24.7?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fsecurego%2fgosec%2fv2/v2.23.0/v2.24.7?slim=true)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/5322) for more information.

---

### Release Notes

<details>
<summary>securego/gosec (github.com/securego/gosec/v2)</summary>

###
[`v2.24.7`](https://redirect.github.com/securego/gosec/releases/tag/v2.24.7)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.6...v2.24.7)

#### Changelog

-
[`bb17e42`](https://redirect.github.com/securego/gosec/commit/bb17e422fc34bf4c0a2e5cab9d07dc45a68c040c)
Ignore nosec comments in action integration workflow to generate some
warnings
([#&#8203;1573](https://redirect.github.com/securego/gosec/issues/1573))
-
[`e1502ad`](https://redirect.github.com/securego/gosec/commit/e1502ad21653d1c6717e33f1221c3ce2d5c8581f)
Add a workflow for action integration test
([#&#8203;1571](https://redirect.github.com/securego/gosec/issues/1571))
-
[`f8691bd`](https://redirect.github.com/securego/gosec/commit/f8691bd77bab5430ccb538e6f253275e82577afc)
fix(sarif): avoid invalid null relationships in SARIF output
([#&#8203;1569](https://redirect.github.com/securego/gosec/issues/1569))
-
[`ade1d0e`](https://redirect.github.com/securego/gosec/commit/ade1d0e0a04ec8ae98da98614d42524621d40df2)
chore: migrate gosec container image references to GHCR
([#&#8203;1567](https://redirect.github.com/securego/gosec/issues/1567))

###
[`v2.24.6`](https://redirect.github.com/securego/gosec/releases/tag/v2.24.6)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.5...v2.24.6)

#### Changelog

-
[`88835e8`](https://redirect.github.com/securego/gosec/commit/88835e86bba381290c2f60a1c73610995b1502eb)
Update gorelease to use the latest cosign bundle argument
([#&#8203;1565](https://redirect.github.com/securego/gosec/issues/1565))

###
[`v2.24.5`](https://redirect.github.com/securego/gosec/compare/v2.24.4...v2.24.5)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.4...v2.24.5)

###
[`v2.24.4`](https://redirect.github.com/securego/gosec/compare/v2.24.3...v2.24.4)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.3...v2.24.4)

###
[`v2.24.3`](https://redirect.github.com/securego/gosec/compare/v2.24.2...v2.24.3)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.2...v2.24.3)

###
[`v2.24.2`](https://redirect.github.com/securego/gosec/compare/v2.24.1...v2.24.2)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.1...v2.24.2)

###
[`v2.24.1`](https://redirect.github.com/securego/gosec/compare/v2.24.0...v2.24.1)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.24.0...v2.24.1)

###
[`v2.24.0`](https://redirect.github.com/securego/gosec/releases/tag/v2.24.0)

[Compare
Source](https://redirect.github.com/securego/gosec/compare/v2.23.0...v2.24.0)

#### Changelog

-
[`271492b`](https://redirect.github.com/securego/gosec/commit/271492bcd930ef72dfb9d00e5bb9544b3b407fb5)
fix: G704 false positive on const URL
([#&#8203;1551](https://redirect.github.com/securego/gosec/issues/1551))
-
[`1341aea`](https://redirect.github.com/securego/gosec/commit/1341aeadb4c334014c4834c745344edb9dcf85b0)
fix(G705): eliminate false positive for non-HTTP io.Writer
([#&#8203;1550](https://redirect.github.com/securego/gosec/issues/1550))
-
[`f2262c8`](https://redirect.github.com/securego/gosec/commit/f2262c88ffdfc9eb7be8444db19caa17cc71810f)
G120: avoid false positive when MaxBytesReader is applied in middleware
([#&#8203;1547](https://redirect.github.com/securego/gosec/issues/1547))
-
[`5b580c7`](https://redirect.github.com/securego/gosec/commit/5b580c76e4714fa553b2ceb8169a071e45bf6428)
Fix G602 regression coverage for issue
[#&#8203;1545](https://redirect.github.com/securego/gosec/issues/1545)
and stabilize G117 TOML test dependency
([#&#8203;1546](https://redirect.github.com/securego/gosec/issues/1546))
-
[`eba2d15`](https://redirect.github.com/securego/gosec/commit/eba2d1582b13e37d5b6c991b643827bc60e58156)
taint: skip `context.Context` arguments during taint propagation to fix
false positives
([#&#8203;1543](https://redirect.github.com/securego/gosec/issues/1543))
-
[`a6381c1`](https://redirect.github.com/securego/gosec/commit/a6381c1e2fe9a9a33ef105c76bea3191402ea4b3)
test: add missing rules to formatter report tests
([#&#8203;1540](https://redirect.github.com/securego/gosec/issues/1540))
-
[`fea9725`](https://redirect.github.com/securego/gosec/commit/fea9725934065d3dd5c96352f89f75d117ac12f6)
chore(deps): update all dependencies
([#&#8203;1541](https://redirect.github.com/securego/gosec/issues/1541))
-
[`f3e2fac`](https://redirect.github.com/securego/gosec/commit/f3e2fac4d58b7eca54307cd40ce2a836a12e4d95)
Regenrate the TLS config rule
([#&#8203;1539](https://redirect.github.com/securego/gosec/issues/1539))
-
[`200461f`](https://redirect.github.com/securego/gosec/commit/200461fcf74ed836305bf95f72568c20925730c5)
Improve documentation
([#&#8203;1538](https://redirect.github.com/securego/gosec/issues/1538))
-
[`078a62a`](https://redirect.github.com/securego/gosec/commit/078a62afc3331206fec1cd9a03637983ec4f9fc8)
Expand analyzer-core test coverage for orchestration, go/analysis
adapter logic, and taint integration
([#&#8203;1537](https://redirect.github.com/securego/gosec/issues/1537))
-
[`ffdc620`](https://redirect.github.com/securego/gosec/commit/ffdc6205c82278cee0b62923814141923794219e)
Add unit tests for CLI orchestration, TLS config generation, and SSA
cache behavior
([#&#8203;1536](https://redirect.github.com/securego/gosec/issues/1536))
-
[`c13a486`](https://redirect.github.com/securego/gosec/commit/c13a48626bc160ef1caa293679044b5667d4d8ef)
Add G707 taint analyzer for SMTP command/header injection
([#&#8203;1535](https://redirect.github.com/securego/gosec/issues/1535))
-
[`f61ed31`](https://redirect.github.com/securego/gosec/commit/f61ed314c2467116ec3a5126150cb2b29a623406)
Add G123 analyzer for tls.VerifyPeerCertificate resumption bypass risk
([#&#8203;1534](https://redirect.github.com/securego/gosec/issues/1534))
-
[`b568aa1`](https://redirect.github.com/securego/gosec/commit/b568aa1445e110ed12abe5c2433b3cfbcd0a5935)
Add G122 SSA analyzer for filepath.Walk/WalkDir symlink TOCTOU race
risks
([#&#8203;1532](https://redirect.github.com/securego/gosec/issues/1532))
-
[`1735e5a`](https://redirect.github.com/securego/gosec/commit/1735e5a9acd155702b8c6137d323df886c0252b5)
fix(G602): avoid false positives for range-over-array indexing
([#&#8203;1531](https://redirect.github.com/securego/gosec/issues/1531))
-
[`caf93d0`](https://redirect.github.com/securego/gosec/commit/caf93d07f10ef7d07006011b17f1d9bd218b5a9d)
Improve taint analyzer performance with shared SSA cache, parallel
analyzer execution, and CI regression guard
([#&#8203;1530](https://redirect.github.com/securego/gosec/issues/1530))
-
[`bd11fbe`](https://redirect.github.com/securego/gosec/commit/bd11fbe2bacb0abf1e541df8b6ec6b040bbe2723)
fix: taint analysis false positives with G703,G705
([#&#8203;1522](https://redirect.github.com/securego/gosec/issues/1522))
-
[`e34e8dd`](https://redirect.github.com/securego/gosec/commit/e34e8dd8e880694cfa801d79977e2d9973df3fa1)
Extend the G117 rule to cover other types of serialization such as
yaml/xml/toml
([#&#8203;1529](https://redirect.github.com/securego/gosec/issues/1529))
-
[`b940702`](https://redirect.github.com/securego/gosec/commit/b940702d5e385d1a68def10326b1658e780655fe)
Fix the G117 rule to take the JSON serialization into account
([#&#8203;1528](https://redirect.github.com/securego/gosec/issues/1528))
-
[`4f84627`](https://redirect.github.com/securego/gosec/commit/4f846273804abaf7e040f77b26bf2866336e8af9)
(docs) fix justification format
([#&#8203;1524](https://redirect.github.com/securego/gosec/issues/1524))
-
[`36ba72b`](https://redirect.github.com/securego/gosec/commit/36ba72bb7f91306f5210a821f409696c03dcbf2b)
Add G121 analyzer for unsafe CORS bypass patterns in
CrossOriginProtection
([#&#8203;1521](https://redirect.github.com/securego/gosec/issues/1521))
-
[`238f982`](https://redirect.github.com/securego/gosec/commit/238f9823256b1c4a6d7b0ccd7fa0f2ce1123c820)
Add G120 SSA analyzer for unbounded form parsing in HTTP handlers
([#&#8203;1520](https://redirect.github.com/securego/gosec/issues/1520))
-
[`89cde27`](https://redirect.github.com/securego/gosec/commit/89cde277b5e2b4a5dc47eb710911c51a0cb33b63)
Add G119 analyzer for unsafe redirect header propagation in
CheckRedirect callbacks
([#&#8203;1519](https://redirect.github.com/securego/gosec/issues/1519))
-
[`14fdd9c`](https://redirect.github.com/securego/gosec/commit/14fdd9cb07c02ab1506fcc336f49c84bf27a5c2d)
Fix G115 false positives and negatives (Issue
[#&#8203;1501](https://redirect.github.com/securego/gosec/issues/1501))
([#&#8203;1518](https://redirect.github.com/securego/gosec/issues/1518))
-
[`cec54ec`](https://redirect.github.com/securego/gosec/commit/cec54ec685eda3083e2ab1adf72b6b7ec6cfdb6e)
chore(deps): update all dependencies
([#&#8203;1517](https://redirect.github.com/securego/gosec/issues/1517))
-
[`2b2077e`](https://redirect.github.com/securego/gosec/commit/2b2077e921b56c7ce6545cccceea0556ff8d5d91)
Add G118 SSA analyzer for context propagation failures that can cause
goroutine/resource leaks
([#&#8203;1516](https://redirect.github.com/securego/gosec/issues/1516))
-
[`a7666f3`](https://redirect.github.com/securego/gosec/commit/a7666f3c70c94d07dfb03e81613fed34bccc89ae)
Add G113: Detect HTTP Request Smuggling via conflicting headers
(CVE-2025-22891, CWE-444)
([#&#8203;1515](https://redirect.github.com/securego/gosec/issues/1515))
-
[`47f8b52`](https://redirect.github.com/securego/gosec/commit/47f8b52fb8700c7ba017ffcc0ea6a32c83e33115)
Add G408: SSH PublicKeyCallback Authentication Bypass Analyzer
([#&#8203;1513](https://redirect.github.com/securego/gosec/issues/1513))
-
[`4f1f362`](https://redirect.github.com/securego/gosec/commit/4f1f362671654660f7145c3c8655ffeaed037d55)
Add more unit tests to improve coverage
([#&#8203;1512](https://redirect.github.com/securego/gosec/issues/1512))
-
[`9344582`](https://redirect.github.com/securego/gosec/commit/9344582ee4bd87b8fa5bc2e483d90fa661f8aa71)
Improve test coverage in various areas
([#&#8203;1511](https://redirect.github.com/securego/gosec/issues/1511))
-
[`8d1b2c6`](https://redirect.github.com/securego/gosec/commit/8d1b2c63ae44e315fb0232813e535891ff0568fc)
Imprve the test coverage
([#&#8203;1510](https://redirect.github.com/securego/gosec/issues/1510))
-
[`993c1c4`](https://redirect.github.com/securego/gosec/commit/993c1c4da2d4426f7567591e23f53ee9f613d07c)
Fix incorrect detection of fixed iv in G407
([#&#8203;1509](https://redirect.github.com/securego/gosec/issues/1509))
-
[`8668b74`](https://redirect.github.com/securego/gosec/commit/8668b748925d8995cf7712d22bde62cbc96f2304)
Add support for go 1.26.x and removed support for go 1.24.x
([#&#8203;1508](https://redirect.github.com/securego/gosec/issues/1508))
-
[`514225c`](https://redirect.github.com/securego/gosec/commit/514225c8cb01a6bab714db1dd557aeb0d7ab9dc9)
Fix the sonar report to follow the latest schema
([#&#8203;1507](https://redirect.github.com/securego/gosec/issues/1507))
-
[`000384e`](https://redirect.github.com/securego/gosec/commit/000384e510a84a1e2a1118e0fbc56518d290113d)
fix: broken taint analysis causing false positives
([#&#8203;1506](https://redirect.github.com/securego/gosec/issues/1506))
-
[`616192c`](https://redirect.github.com/securego/gosec/commit/616192c9d92792998e2ff38530c080cd0fe293a8)
fix: panic on float constants in overflow analyzer
([#&#8203;1505](https://redirect.github.com/securego/gosec/issues/1505))
-
[`79956a3`](https://redirect.github.com/securego/gosec/commit/79956a3b4cdedc9a4cde5f567c57fc8b367448cf)
fix: panic when scanning multi-module repos from root
([#&#8203;1504](https://redirect.github.com/securego/gosec/issues/1504))
-
[`5736e8b`](https://redirect.github.com/securego/gosec/commit/5736e8b88b6ca97fc7e09ef1bf24b205ab35fd9c)
fix: G602 false positive for array element access
([#&#8203;1499](https://redirect.github.com/securego/gosec/issues/1499))
-
[`1b7e1e9`](https://redirect.github.com/securego/gosec/commit/1b7e1e94bc2077fc1adccfc1358399fad2958d5a)
Update gosec to version v2.23.0 in the Github action
([#&#8203;1496](https://redirect.github.com/securego/gosec/issues/1496))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-telemetry/opentelemetry-go).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40OC4xIiwidXBkYXRlZEluVmVyIjoiNDMuNDguMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiU2tpcCBDaGFuZ2Vsb2ciLCJkZXBlbmRlbmNpZXMiXX0=-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tyler Yahn <codingalias@gmail.com>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
2026-03-03 11:59:53 -08:00

334 lines
8.9 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package trace // import "go.opentelemetry.io/otel/trace"
import (
"encoding/json"
"fmt"
"strings"
)
const (
maxListMembers = 32
listDelimiters = ","
memberDelimiter = "="
errInvalidKey errorConst = "invalid tracestate key"
errInvalidValue errorConst = "invalid tracestate value"
errInvalidMember errorConst = "invalid tracestate list-member"
errMemberNumber errorConst = "too many list-members in tracestate"
errDuplicate errorConst = "duplicate list-member in tracestate"
)
type member struct {
Key string
Value string
}
// according to (chr = %x20 / (nblk-char = %x21-2B / %x2D-3C / %x3E-7E) )
// means (chr = %x20-2B / %x2D-3C / %x3E-7E) .
func checkValueChar(v byte) bool {
return v >= '\x20' && v <= '\x7e' && v != '\x2c' && v != '\x3d'
}
// according to (nblk-chr = %x21-2B / %x2D-3C / %x3E-7E) .
func checkValueLast(v byte) bool {
return v >= '\x21' && v <= '\x7e' && v != '\x2c' && v != '\x3d'
}
// based on the W3C Trace Context specification
//
// value = (0*255(chr)) nblk-chr
// nblk-chr = %x21-2B / %x2D-3C / %x3E-7E
// chr = %x20 / nblk-chr
//
// see https://www.w3.org/TR/trace-context-1/#value
func checkValue(val string) bool {
n := len(val)
if n == 0 || n > 256 {
return false
}
for i := 0; i < n-1; i++ {
if !checkValueChar(val[i]) {
return false
}
}
return checkValueLast(val[n-1])
}
func checkKeyRemain(key string) bool {
// ( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )
for _, v := range key {
if v > 127 {
return false
}
if isAlphaNumASCII(v) {
continue
}
switch v {
case '_', '-', '*', '/':
continue
}
return false
}
return true
}
// according to
//
// simple-key = lcalpha (0*255( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
// system-id = lcalpha (0*13( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
//
// param n is remain part length, should be 255 in simple-key or 13 in system-id.
func checkKeyPart(key string, n int) bool {
if key == "" {
return false
}
first := key[0] // key's first char
ret := len(key[1:]) <= n
ret = ret && first >= 'a' && first <= 'z'
return ret && checkKeyRemain(key[1:])
}
func isAlphaNumASCII[T rune | byte](c T) bool {
if c >= 'a' && c <= 'z' {
return true
}
return c >= '0' && c <= '9'
}
// according to
//
// tenant-id = ( lcalpha / DIGIT ) 0*240( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )
//
// param n is remain part length, should be 240 exactly.
func checkKeyTenant(key string, n int) bool {
if key == "" {
return false
}
return isAlphaNumASCII(key[0]) && len(key[1:]) <= n && checkKeyRemain(key[1:])
}
// based on the W3C Trace Context specification
//
// key = simple-key / multi-tenant-key
// simple-key = lcalpha (0*255( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
// multi-tenant-key = tenant-id "@" system-id
// tenant-id = ( lcalpha / DIGIT ) (0*240( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
// system-id = lcalpha (0*13( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ))
// lcalpha = %x61-7A ; a-z
//
// see https://www.w3.org/TR/trace-context-1/#tracestate-header.
func checkKey(key string) bool {
tenant, system, ok := strings.Cut(key, "@")
if !ok {
return checkKeyPart(key, 255)
}
return checkKeyTenant(tenant, 240) && checkKeyPart(system, 13)
}
func newMember(key, value string) (member, error) {
if !checkKey(key) {
return member{}, errInvalidKey
}
if !checkValue(value) {
return member{}, errInvalidValue
}
return member{Key: key, Value: value}, nil
}
func parseMember(m string) (member, error) {
key, val, ok := strings.Cut(m, memberDelimiter)
if !ok {
return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
}
key = strings.TrimLeft(key, " \t")
val = strings.TrimRight(val, " \t")
result, e := newMember(key, val)
if e != nil {
return member{}, fmt.Errorf("%w: %s", errInvalidMember, m)
}
return result, nil
}
// String encodes member into a string compliant with the W3C Trace Context
// specification.
func (m member) String() string {
return m.Key + "=" + m.Value
}
// TraceState provides additional vendor-specific trace identification
// information across different distributed tracing systems. It represents an
// immutable list consisting of key/value pairs, each pair is referred to as a
// list-member.
//
// TraceState conforms to the W3C Trace Context specification
// (https://www.w3.org/TR/trace-context-1). All operations that create or copy
// a TraceState do so by validating all input and will only produce TraceState
// that conform to the specification. Specifically, this means that all
// list-member's key/value pairs are valid, no duplicate list-members exist,
// and the maximum number of list-members (32) is not exceeded.
type TraceState struct { //nolint:revive // revive complains about stutter of `trace.TraceState`
// list is the members in order.
list []member
}
var _ json.Marshaler = TraceState{}
// ParseTraceState attempts to decode a TraceState from the passed
// string. It returns an error if the input is invalid according to the W3C
// Trace Context specification.
func ParseTraceState(ts string) (TraceState, error) {
if ts == "" {
return TraceState{}, nil
}
wrapErr := func(err error) error {
return fmt.Errorf("failed to parse tracestate: %w", err)
}
var members []member
found := make(map[string]struct{})
for ts != "" {
var memberStr string
memberStr, ts, _ = strings.Cut(ts, listDelimiters)
if memberStr == "" {
continue
}
m, err := parseMember(memberStr)
if err != nil {
return TraceState{}, wrapErr(err)
}
if _, ok := found[m.Key]; ok {
return TraceState{}, wrapErr(errDuplicate)
}
found[m.Key] = struct{}{}
members = append(members, m)
if n := len(members); n > maxListMembers {
return TraceState{}, wrapErr(errMemberNumber)
}
}
return TraceState{list: members}, nil
}
// MarshalJSON marshals the TraceState into JSON.
func (ts TraceState) MarshalJSON() ([]byte, error) {
return json.Marshal(ts.String())
}
// String encodes the TraceState into a string compliant with the W3C
// Trace Context specification. The returned string will be invalid if the
// TraceState contains any invalid members.
func (ts TraceState) String() string {
if len(ts.list) == 0 {
return ""
}
var n int
n += len(ts.list) // member delimiters: '='
n += len(ts.list) - 1 // list delimiters: ','
for _, mem := range ts.list {
n += len(mem.Key)
n += len(mem.Value)
}
var sb strings.Builder
sb.Grow(n)
_, _ = sb.WriteString(ts.list[0].Key)
_ = sb.WriteByte('=')
_, _ = sb.WriteString(ts.list[0].Value)
for i := 1; i < len(ts.list); i++ {
_ = sb.WriteByte(listDelimiters[0])
_, _ = sb.WriteString(ts.list[i].Key)
_ = sb.WriteByte('=')
_, _ = sb.WriteString(ts.list[i].Value)
}
return sb.String()
}
// Get returns the value paired with key from the corresponding TraceState
// list-member if it exists, otherwise an empty string is returned.
func (ts TraceState) Get(key string) string {
for _, member := range ts.list {
if member.Key == key {
return member.Value
}
}
return ""
}
// Walk walks all key value pairs in the TraceState by calling f
// Iteration stops if f returns false.
func (ts TraceState) Walk(f func(key, value string) bool) {
for _, m := range ts.list {
if !f(m.Key, m.Value) {
break
}
}
}
// Insert adds a new list-member defined by the key/value pair to the
// TraceState. If a list-member already exists for the given key, that
// list-member's value is updated. The new or updated list-member is always
// moved to the beginning of the TraceState as specified by the W3C Trace
// Context specification.
//
// If key or value are invalid according to the W3C Trace Context
// specification an error is returned with the original TraceState.
//
// If adding a new list-member means the TraceState would have more members
// then is allowed, the new list-member will be inserted and the right-most
// list-member will be dropped in the returned TraceState.
func (ts TraceState) Insert(key, value string) (TraceState, error) {
m, err := newMember(key, value)
if err != nil {
return ts, err
}
n := len(ts.list)
found := n
for i := range ts.list {
if ts.list[i].Key == key {
found = i
}
}
cTS := TraceState{}
if found == n && n < maxListMembers {
cTS.list = make([]member, n+1)
} else {
cTS.list = make([]member, n)
}
cTS.list[0] = m
// When the number of members exceeds capacity, drop the "right-most".
copy(cTS.list[1:], ts.list[0:found])
if found < n {
copy(cTS.list[1+found:], ts.list[found+1:])
}
return cTS, nil
}
// Delete returns a copy of the TraceState with the list-member identified by
// key removed.
func (ts TraceState) Delete(key string) TraceState {
members := make([]member, ts.Len())
copy(members, ts.list)
for i, member := range ts.list {
if member.Key == key {
members = append(members[:i], members[i+1:]...)
// TraceState should contain no duplicate members.
break
}
}
return TraceState{list: members}
}
// Len returns the number of list-members in the TraceState.
func (ts TraceState) Len() int {
return len(ts.list)
}