/
context.go
124 lines (105 loc) · 3.29 KB
/
context.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Package behaviour stores and accesses the values defined in this package in
// and from a github.com/the-anna-project/context.Context.
package behaviour
import (
"reflect"
"github.com/the-anna-project/context"
"github.com/the-anna-project/gopkg"
)
// Value is the context value being managed by this package.
type Value struct {
// ID represents the ID of the current behaviour.
ID string `json:"id"`
// Input reprepresents an extension of the context value.
Input ValueInput `json:"input"`
// Name represents the name of the current behaviour.
Name string `json:"name"`
}
// ValueInput extends the context value.
type ValueInput struct {
// Types represents the input types of the current behaviour.
Types []string `json:"types"`
}
// Equals checks whether the properties of the current value equals the
// properties of the given value.
func (v Value) Equals(other Value) bool {
if v.ID != other.ID {
return false
}
if !reflect.DeepEqual(v.Input.Types, other.Input.Types) {
return false
}
if v.Name != other.Name {
return false
}
return true
}
var (
// valueKey is the key for context values in
// github.com/the-anna-project/context.Context. Clients use
// behaviour.NewContext and behaviour.FromContext instead of using this key
// directly.
valueKey = gopkg.String()
// restoreKey is the key for restoring context values in
// github.com/the-anna-project/context.Context. Clients use behaviour.Disable
// and behaviour.Restore instead of using this key directly.
restoreKey = gopkg.String() + "/restore"
)
// Disable removes the context value being stored using valueKey and backs it up
// using restoreKey.
func Disable(ctx context.Context) context.Context {
val, _ := FromContext(ctx)
ctx.Create(restoreKey, val)
ctx.Delete(valueKey)
return ctx
}
// FromContext returns the context value stored in ctx, if any.
func FromContext(ctx context.Context) (Value, bool) {
val, ok := ctx.Search(valueKey).(Value)
return val, ok
}
// IsDisabled checks whether the given context has the context value removed and
// backed up.
func IsDisabled(ctx context.Context) bool {
var ok bool
_, ok = ctx.Search(valueKey).(Value)
if ok {
return false
}
_, ok = ctx.Search(restoreKey).(Value)
if !ok {
return false
}
return true
}
// NewContext returns a new github.com/the-anna-project/context.Context that
// carries the context value val.
func NewContext(ctx context.Context, val Value) context.Context {
ctx.Create(valueKey, val)
return ctx
}
// NewContextFromContexts sets the context value from the given list of contexts
// to the given single context. Therefore all context values transported by all
// contexts of the given list of contexts have to be equal.
func NewContextFromContexts(ctx context.Context, ctxs []context.Context) (context.Context, error) {
var reference Value
for i, c := range ctxs {
value, _ := FromContext(c)
if i == 0 {
reference = value
}
if !value.Equals(reference) {
return nil, maskAnyf(invalidExecutionError, "context values must be equal")
}
}
ctx = NewContext(ctx, reference)
return ctx, nil
}
// Restore sets the context value using the value being backed up by a previous
// call to Disable.
func Restore(ctx context.Context) context.Context {
val, _ := ctx.Search(restoreKey).(Value)
ctx.Create(valueKey, val)
ctx.Delete(restoreKey)
return ctx
}