Blame vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go

Packit Service 4d2de5
package protocol
Packit Service 4d2de5
Packit Service 4d2de5
import (
Packit Service 4d2de5
	"crypto/rand"
Packit Service 4d2de5
	"fmt"
Packit Service 4d2de5
	"reflect"
Packit Service 4d2de5
)
Packit Service 4d2de5
Packit Service 4d2de5
// RandReader is the random reader the protocol package will use to read
Packit Service 4d2de5
// random bytes from. This is exported for testing, and should not be used.
Packit Service 4d2de5
var RandReader = rand.Reader
Packit Service 4d2de5
Packit Service 4d2de5
const idempotencyTokenFillTag = `idempotencyToken`
Packit Service 4d2de5
Packit Service 4d2de5
// CanSetIdempotencyToken returns true if the struct field should be
Packit Service 4d2de5
// automatically populated with a Idempotency token.
Packit Service 4d2de5
//
Packit Service 4d2de5
// Only *string and string type fields that are tagged with idempotencyToken
Packit Service 4d2de5
// which are not already set can be auto filled.
Packit Service 4d2de5
func CanSetIdempotencyToken(v reflect.Value, f reflect.StructField) bool {
Packit Service 4d2de5
	switch u := v.Interface().(type) {
Packit Service 4d2de5
	// To auto fill an Idempotency token the field must be a string,
Packit Service 4d2de5
	// tagged for auto fill, and have a zero value.
Packit Service 4d2de5
	case *string:
Packit Service 4d2de5
		return u == nil && len(f.Tag.Get(idempotencyTokenFillTag)) != 0
Packit Service 4d2de5
	case string:
Packit Service 4d2de5
		return len(u) == 0 && len(f.Tag.Get(idempotencyTokenFillTag)) != 0
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	return false
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// GetIdempotencyToken returns a randomly generated idempotency token.
Packit Service 4d2de5
func GetIdempotencyToken() string {
Packit Service 4d2de5
	b := make([]byte, 16)
Packit Service 4d2de5
	RandReader.Read(b)
Packit Service 4d2de5
Packit Service 4d2de5
	return UUIDVersion4(b)
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// SetIdempotencyToken will set the value provided with a Idempotency Token.
Packit Service 4d2de5
// Given that the value can be set. Will panic if value is not setable.
Packit Service 4d2de5
func SetIdempotencyToken(v reflect.Value) {
Packit Service 4d2de5
	if v.Kind() == reflect.Ptr {
Packit Service 4d2de5
		if v.IsNil() && v.CanSet() {
Packit Service 4d2de5
			v.Set(reflect.New(v.Type().Elem()))
Packit Service 4d2de5
		}
Packit Service 4d2de5
		v = v.Elem()
Packit Service 4d2de5
	}
Packit Service 4d2de5
	v = reflect.Indirect(v)
Packit Service 4d2de5
Packit Service 4d2de5
	if !v.CanSet() {
Packit Service 4d2de5
		panic(fmt.Sprintf("unable to set idempotnecy token %v", v))
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	b := make([]byte, 16)
Packit Service 4d2de5
	_, err := rand.Read(b)
Packit Service 4d2de5
	if err != nil {
Packit Service 4d2de5
		// TODO handle error
Packit Service 4d2de5
		return
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	v.Set(reflect.ValueOf(UUIDVersion4(b)))
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// UUIDVersion4 returns a Version 4 random UUID from the byte slice provided
Packit Service 4d2de5
func UUIDVersion4(u []byte) string {
Packit Service 4d2de5
	// https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
Packit Service 4d2de5
	// 13th character is "4"
Packit Service 4d2de5
	u[6] = (u[6] | 0x40) & 0x4F
Packit Service 4d2de5
	// 17th character is "8", "9", "a", or "b"
Packit Service 4d2de5
	u[8] = (u[8] | 0x80) & 0xBF
Packit Service 4d2de5
Packit Service 4d2de5
	return fmt.Sprintf(`%X-%X-%X-%X-%X`, u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
Packit Service 4d2de5
}