aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go
new file mode 100644
index 0000000..53831df
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go
@@ -0,0 +1,75 @@
1package protocol
2
3import (
4 "crypto/rand"
5 "fmt"
6 "reflect"
7)
8
9// RandReader is the random reader the protocol package will use to read
10// random bytes from. This is exported for testing, and should not be used.
11var RandReader = rand.Reader
12
13const idempotencyTokenFillTag = `idempotencyToken`
14
15// CanSetIdempotencyToken returns true if the struct field should be
16// automatically populated with a Idempotency token.
17//
18// Only *string and string type fields that are tagged with idempotencyToken
19// which are not already set can be auto filled.
20func CanSetIdempotencyToken(v reflect.Value, f reflect.StructField) bool {
21 switch u := v.Interface().(type) {
22 // To auto fill an Idempotency token the field must be a string,
23 // tagged for auto fill, and have a zero value.
24 case *string:
25 return u == nil && len(f.Tag.Get(idempotencyTokenFillTag)) != 0
26 case string:
27 return len(u) == 0 && len(f.Tag.Get(idempotencyTokenFillTag)) != 0
28 }
29
30 return false
31}
32
33// GetIdempotencyToken returns a randomly generated idempotency token.
34func GetIdempotencyToken() string {
35 b := make([]byte, 16)
36 RandReader.Read(b)
37
38 return UUIDVersion4(b)
39}
40
41// SetIdempotencyToken will set the value provided with a Idempotency Token.
42// Given that the value can be set. Will panic if value is not setable.
43func SetIdempotencyToken(v reflect.Value) {
44 if v.Kind() == reflect.Ptr {
45 if v.IsNil() && v.CanSet() {
46 v.Set(reflect.New(v.Type().Elem()))
47 }
48 v = v.Elem()
49 }
50 v = reflect.Indirect(v)
51
52 if !v.CanSet() {
53 panic(fmt.Sprintf("unable to set idempotnecy token %v", v))
54 }
55
56 b := make([]byte, 16)
57 _, err := rand.Read(b)
58 if err != nil {
59 // TODO handle error
60 return
61 }
62
63 v.Set(reflect.ValueOf(UUIDVersion4(b)))
64}
65
66// UUIDVersion4 returns a Version 4 random UUID from the byte slice provided
67func UUIDVersion4(u []byte) string {
68 // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
69 // 13th character is "4"
70 u[6] = (u[6] | 0x40) & 0x4F
71 // 17th character is "8", "9", "a", or "b"
72 u[8] = (u[8] | 0x80) & 0xBF
73
74 return fmt.Sprintf(`%X-%X-%X-%X-%X`, u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
75}