-
Notifications
You must be signed in to change notification settings - Fork 1
/
context_dump.go
51 lines (43 loc) · 984 Bytes
/
context_dump.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package synx
import (
"context"
"fmt"
"unsafe"
)
// DumpContext values. Works for stdlib contexts only.
func DumpContext(ctx context.Context) map[any]any {
if ctx == nil {
return nil
}
values := map[any]any{}
for {
// cannot use type-switch here because those types are unexported
switch fmt.Sprintf("%T", ctx) {
case "*context.valueCtx":
v := *(*valueCtx)((*iface)(unsafe.Pointer(&ctx)).data)
values[v.key] = v.value
ctx = v.Context
case "*context.timerCtx", "*context.cancelCtx":
v := *(*parentCtx)((*iface)(unsafe.Pointer(&ctx)).data)
ctx = v.Context
default:
// know nothing about other types (or nil), so returning
return values
}
}
}
// Same as runtime.(iface)
type iface struct {
_ unsafe.Pointer
data unsafe.Pointer
}
// Same as of context.(valueCtx)
type valueCtx struct {
context.Context
key, value any
}
// Same as context.(*timerCtx) and context.(*cancelCtx)
type parentCtx struct {
context.Context
_ struct{}
}