diff options
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.go | 75 |
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 @@ | |||
1 | package protocol | ||
2 | |||
3 | import ( | ||
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. | ||
11 | var RandReader = rand.Reader | ||
12 | |||
13 | const 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. | ||
20 | func 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. | ||
34 | func 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. | ||
43 | func 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 | ||
67 | func 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 | } | ||