mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-12-03 02:33:36 +00:00
Update godeps
This commit is contained in:
64
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter.go
generated
vendored
64
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter.go
generated
vendored
@@ -1,50 +1,3 @@
|
||||
// Package dynamodbattribute provides conversion utilities from dynamodb.AttributeValue
|
||||
// to concrete Go types and structures. These conversion utilities allow you to
|
||||
// convert a Struct, Slice, Map, or Scalar value to or from dynamodb.AttributeValue.
|
||||
// These are most useful to serialize concrete types to dynamodb.AttributeValue for
|
||||
// requests or unmarshalling the dynamodb.AttributeValue into a well known typed form.
|
||||
//
|
||||
// Converting []byte fields to dynamodb.AttributeValue are only currently supported
|
||||
// if the input is a map[string]interface{} type. []byte within typed structs are not
|
||||
// converted correctly and are converted into base64 strings. This is a known bug,
|
||||
// and will be fixed in a later release.
|
||||
//
|
||||
// Convert concrete type to dynamodb.AttributeValue: See (ExampleConvertTo)
|
||||
//
|
||||
// type Record struct {
|
||||
// MyField string
|
||||
// Letters []string
|
||||
// A2Num map[string]int
|
||||
// }
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// r := Record{
|
||||
// MyField: "dynamodbattribute.ConvertToX example",
|
||||
// Letters: []string{"a", "b", "c", "d"},
|
||||
// A2Num: map[string]int{"a": 1, "b": 2, "c": 3},
|
||||
// }
|
||||
// av, err := dynamodbattribute.ConvertTo(r)
|
||||
// fmt.Println(av, err)
|
||||
//
|
||||
// Convert dynamodb.AttributeValue to Concrete type: See (ExampleConvertFrom)
|
||||
//
|
||||
// r2 := Record{}
|
||||
// err = dynamodbattribute.ConvertFrom(av, &r2)
|
||||
// fmt.Println(err, reflect.DeepEqual(r, r2))
|
||||
//
|
||||
// Use Conversion utilities with DynamoDB.PutItem: See ()
|
||||
//
|
||||
// svc := dynamodb.New(nil)
|
||||
// item, err := dynamodbattribute.ConvertToMap(r)
|
||||
// if err != nil {
|
||||
// fmt.Println("Failed to convert", err)
|
||||
// return
|
||||
// }
|
||||
// result, err := svc.PutItem(&dynamodb.PutItemInput{
|
||||
// Item: item,
|
||||
// TableName: aws.String("exampleTable"),
|
||||
// })
|
||||
package dynamodbattribute
|
||||
|
||||
import (
|
||||
@@ -64,6 +17,8 @@ import (
|
||||
//
|
||||
// If in contains any structs, it is first JSON encoded/decoded it to convert it
|
||||
// to a map[string]interface{}, so `json` struct tags are respected.
|
||||
//
|
||||
// Deprecated: Use MarshalMap instead
|
||||
func ConvertToMap(in interface{}) (item map[string]*dynamodb.AttributeValue, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -110,6 +65,8 @@ func ConvertToMap(in interface{}) (item map[string]*dynamodb.AttributeValue, err
|
||||
// If v points to a struct, the result is first converted it to a
|
||||
// map[string]interface{}, then JSON encoded/decoded it to convert to a struct,
|
||||
// so `json` struct tags are respected.
|
||||
//
|
||||
// Deprecated: Use UnmarshalMap instead
|
||||
func ConvertFromMap(item map[string]*dynamodb.AttributeValue, v interface{}) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -155,8 +112,15 @@ func ConvertFromMap(item map[string]*dynamodb.AttributeValue, v interface{}) (er
|
||||
// ConvertToList accepts an array or slice and converts it to a
|
||||
// []*dynamodb.AttributeValue.
|
||||
//
|
||||
// Converting []byte fields to dynamodb.AttributeValue are only currently supported
|
||||
// if the input is a map[string]interface{} type. []byte within typed structs are not
|
||||
// converted correctly and are converted into base64 strings. This is a known bug,
|
||||
// and will be fixed in a later release.
|
||||
//
|
||||
// If in contains any structs, it is first JSON encoded/decoded it to convert it
|
||||
// to a []interface{}, so `json` struct tags are respected.
|
||||
//
|
||||
// Deprecated: Use MarshalList instead
|
||||
func ConvertToList(in interface{}) (item []*dynamodb.AttributeValue, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -204,6 +168,8 @@ func ConvertToList(in interface{}) (item []*dynamodb.AttributeValue, err error)
|
||||
// If v contains any structs, the result is first converted it to a
|
||||
// []interface{}, then JSON encoded/decoded it to convert to a typed array or
|
||||
// slice, so `json` struct tags are respected.
|
||||
//
|
||||
// Deprecated: Use UnmarshalList instead
|
||||
func ConvertFromList(item []*dynamodb.AttributeValue, v interface{}) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -250,6 +216,8 @@ func ConvertFromList(item []*dynamodb.AttributeValue, v interface{}) (err error)
|
||||
//
|
||||
// If in contains any structs, it is first JSON encoded/decoded it to convert it
|
||||
// to a interface{}, so `json` struct tags are respected.
|
||||
//
|
||||
// Deprecated: Use Marshal instead
|
||||
func ConvertTo(in interface{}) (item *dynamodb.AttributeValue, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -278,6 +246,8 @@ func ConvertTo(in interface{}) (item *dynamodb.AttributeValue, err error) {
|
||||
// If v contains any structs, the result is first converted it to a interface{},
|
||||
// then JSON encoded/decoded it to convert to a struct, so `json` struct tags
|
||||
// are respected.
|
||||
//
|
||||
// Deprecated: Use Unmarshal instead
|
||||
func ConvertFrom(item *dynamodb.AttributeValue, v interface{}) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
||||
628
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode.go
generated
vendored
Normal file
628
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode.go
generated
vendored
Normal file
@@ -0,0 +1,628 @@
|
||||
package dynamodbattribute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
)
|
||||
|
||||
// An Unmarshaler is an interface to provide custom unmarshaling of
|
||||
// AttributeValues. Use this to provide custom logic determining
|
||||
// how AttributeValues should be unmarshaled.
|
||||
// type ExampleUnmarshaler struct {
|
||||
// Value int
|
||||
// }
|
||||
//
|
||||
// type (u *exampleUnmarshaler) UnmarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error {
|
||||
// if av.N == nil {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// n, err := strconv.ParseInt(*av.N, 10, 0)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// u.Value = n
|
||||
// return nil
|
||||
// }
|
||||
type Unmarshaler interface {
|
||||
UnmarshalDynamoDBAttributeValue(*dynamodb.AttributeValue) error
|
||||
}
|
||||
|
||||
// Unmarshal will unmarshal DynamoDB AttributeValues to Go value types.
|
||||
// Both generic interface{} and concrete types are valid unmarshal
|
||||
// destination types.
|
||||
//
|
||||
// Unmarshal will allocate maps, slices, and pointers as needed to
|
||||
// unmarshal the AttributeValue into the provided type value.
|
||||
//
|
||||
// When unmarshaling AttributeValues into structs Unmarshal matches
|
||||
// the field names of the struct to the AttributeValue Map keys.
|
||||
// Initially it will look for exact field name matching, but will
|
||||
// fall back to case insensitive if not exact match is found.
|
||||
//
|
||||
// With the exception of omitempty, omitemptyelem, binaryset, numberset
|
||||
// and stringset all struct tags used by Marshal are also used by
|
||||
// Unmarshal.
|
||||
//
|
||||
// When decoding AttributeValues to interfaces Unmarshal will use the
|
||||
// following types.
|
||||
//
|
||||
// []byte, AV Binary (B)
|
||||
// [][]byte, AV Binary Set (BS)
|
||||
// bool, AV Boolean (BOOL)
|
||||
// []interface{}, AV List (L)
|
||||
// map[string]interface{}, AV Map (M)
|
||||
// float64, AV Number (N)
|
||||
// Number, AV Number (N) with UseNumber set
|
||||
// []float64, AV Number Set (NS)
|
||||
// []Number, AV Number Set (NS) with UseNumber set
|
||||
// string, AV String (S)
|
||||
// []string, AV String Set (SS)
|
||||
//
|
||||
// If the Decoder option, UseNumber is set numbers will be unmarshaled
|
||||
// as Number values instead of float64. Use this to maintain the original
|
||||
// string formating of the number as it was represented in the AttributeValue.
|
||||
// In addition provides additional opportunities to parse the number
|
||||
// string based on individual use cases.
|
||||
//
|
||||
// When unmarshaling any error that occurs will halt the unmarshal
|
||||
// and return the error.
|
||||
//
|
||||
// The output value provided must be a non-nil pointer
|
||||
func Unmarshal(av *dynamodb.AttributeValue, out interface{}) error {
|
||||
return NewDecoder().Decode(av, out)
|
||||
}
|
||||
|
||||
// UnmarshalMap is an alias for Unmarshal which unmarshals from
|
||||
// a map of AttributeValues.
|
||||
//
|
||||
// The output value provided must be a non-nil pointer
|
||||
func UnmarshalMap(m map[string]*dynamodb.AttributeValue, out interface{}) error {
|
||||
return NewDecoder().Decode(&dynamodb.AttributeValue{M: m}, out)
|
||||
}
|
||||
|
||||
// UnmarshalList is an alias for Unmarshal func which unmarshals
|
||||
// a slice of AttributeValues.
|
||||
//
|
||||
// The output value provided must be a non-nil pointer
|
||||
func UnmarshalList(l []*dynamodb.AttributeValue, out interface{}) error {
|
||||
return NewDecoder().Decode(&dynamodb.AttributeValue{L: l}, out)
|
||||
}
|
||||
|
||||
// A Decoder provides unmarshaling AttributeValues to Go value types.
|
||||
type Decoder struct {
|
||||
MarshalOptions
|
||||
|
||||
// Instructs the decoder to decode AttributeValue Numbers as
|
||||
// Number type instead of float64 when the destination type
|
||||
// is interface{}. Similar to encoding/json.Number
|
||||
UseNumber bool
|
||||
}
|
||||
|
||||
// NewDecoder creates a new Decoder with default configuration. Use
|
||||
// the `opts` functional options to override the default configuration.
|
||||
func NewDecoder(opts ...func(*Decoder)) *Decoder {
|
||||
d := &Decoder{
|
||||
MarshalOptions: MarshalOptions{
|
||||
SupportJSONTags: true,
|
||||
},
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(d)
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// Decode will unmarshal an AttributeValue into a Go value type. An error
|
||||
// will be return if the decoder is unable to unmarshal the AttributeValue
|
||||
// to the provide Go value type.
|
||||
//
|
||||
// The output value provided must be a non-nil pointer
|
||||
func (d *Decoder) Decode(av *dynamodb.AttributeValue, out interface{}, opts ...func(*Decoder)) error {
|
||||
v := reflect.ValueOf(out)
|
||||
if v.Kind() != reflect.Ptr || v.IsNil() || !v.IsValid() {
|
||||
return &InvalidUnmarshalError{Type: reflect.TypeOf(out)}
|
||||
}
|
||||
|
||||
return d.decode(av, v, tag{})
|
||||
}
|
||||
|
||||
var stringInterfaceMapType = reflect.TypeOf(map[string]interface{}(nil))
|
||||
var byteSliceType = reflect.TypeOf([]byte(nil))
|
||||
var byteSliceSlicetype = reflect.TypeOf([][]byte(nil))
|
||||
var numberType = reflect.TypeOf(Number(""))
|
||||
|
||||
func (d *Decoder) decode(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error {
|
||||
var u Unmarshaler
|
||||
if av == nil || av.NULL != nil {
|
||||
u, v = indirect(v, true)
|
||||
if u != nil {
|
||||
return u.UnmarshalDynamoDBAttributeValue(av)
|
||||
}
|
||||
return d.decodeNull(v)
|
||||
}
|
||||
|
||||
u, v = indirect(v, false)
|
||||
if u != nil {
|
||||
return u.UnmarshalDynamoDBAttributeValue(av)
|
||||
}
|
||||
|
||||
switch {
|
||||
case len(av.B) != 0:
|
||||
return d.decodeBinary(av.B, v)
|
||||
case av.BOOL != nil:
|
||||
return d.decodeBool(av.BOOL, v)
|
||||
case len(av.BS) != 0:
|
||||
return d.decodeBinarySet(av.BS, v)
|
||||
case len(av.L) != 0:
|
||||
return d.decodeList(av.L, v)
|
||||
case len(av.M) != 0:
|
||||
return d.decodeMap(av.M, v)
|
||||
case av.N != nil:
|
||||
return d.decodeNumber(av.N, v)
|
||||
case len(av.NS) != 0:
|
||||
return d.decodeNumberSet(av.NS, v)
|
||||
case av.S != nil:
|
||||
return d.decodeString(av.S, v, fieldTag)
|
||||
case len(av.SS) != 0:
|
||||
return d.decodeStringSet(av.SS, v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeBinary(b []byte, v reflect.Value) error {
|
||||
if v.Kind() == reflect.Interface {
|
||||
buf := make([]byte, len(b))
|
||||
copy(buf, b)
|
||||
v.Set(reflect.ValueOf(buf))
|
||||
return nil
|
||||
}
|
||||
|
||||
switch v.Interface().(type) {
|
||||
case []byte:
|
||||
if v.IsNil() || v.Cap() < len(b) {
|
||||
v.Set(reflect.MakeSlice(byteSliceType, len(b), len(b)))
|
||||
} else if v.Len() != len(b) {
|
||||
v.SetLen(len(b))
|
||||
}
|
||||
copy(v.Interface().([]byte), b)
|
||||
default:
|
||||
if v.Kind() == reflect.Array && v.Type().Elem().Kind() == reflect.Uint8 {
|
||||
reflect.Copy(v, reflect.ValueOf(b))
|
||||
break
|
||||
}
|
||||
return &UnmarshalTypeError{Value: "binary", Type: v.Type()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeBool(b *bool, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Bool, reflect.Interface:
|
||||
v.Set(reflect.ValueOf(*b))
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "bool", Type: v.Type()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
// Make room for the slice elements if needed
|
||||
if v.IsNil() || v.Cap() < len(bs) {
|
||||
// What about if ignoring nil/empty values?
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, len(bs)))
|
||||
}
|
||||
case reflect.Array:
|
||||
// Limited to capacity of existing array.
|
||||
case reflect.Interface:
|
||||
set := make([][]byte, len(bs))
|
||||
for i, b := range bs {
|
||||
if err := d.decodeBinary(b, reflect.ValueOf(&set[i]).Elem()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(reflect.ValueOf(set))
|
||||
return nil
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "binary set", Type: v.Type()}
|
||||
}
|
||||
|
||||
for i := 0; i < v.Cap() && i < len(bs); i++ {
|
||||
v.SetLen(i + 1)
|
||||
u, elem := indirect(v.Index(i), false)
|
||||
if u != nil {
|
||||
return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{BS: bs})
|
||||
}
|
||||
if err := d.decodeBinary(bs[i], elem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeNumber(n *string, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Interface:
|
||||
i, err := d.decodeNumberToInterface(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
return nil
|
||||
case reflect.String:
|
||||
if v.Type() == numberType { // Support Number value type
|
||||
v.Set(reflect.ValueOf(Number(*n)))
|
||||
return nil
|
||||
}
|
||||
v.Set(reflect.ValueOf(*n))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i, err := strconv.ParseInt(*n, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v.OverflowInt(i) {
|
||||
return &UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number overflow, %s", *n),
|
||||
Type: v.Type(),
|
||||
}
|
||||
}
|
||||
v.SetInt(i)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
i, err := strconv.ParseUint(*n, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v.OverflowUint(i) {
|
||||
return &UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number overflow, %s", *n),
|
||||
Type: v.Type(),
|
||||
}
|
||||
}
|
||||
v.SetUint(i)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
i, err := strconv.ParseFloat(*n, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v.OverflowFloat(i) {
|
||||
return &UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number overflow, %s", *n),
|
||||
Type: v.Type(),
|
||||
}
|
||||
}
|
||||
v.SetFloat(i)
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "number", Type: v.Type()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeNumberToInterface(n *string) (interface{}, error) {
|
||||
if d.UseNumber {
|
||||
return Number(*n), nil
|
||||
}
|
||||
|
||||
// Default to float64 for all numbers
|
||||
return strconv.ParseFloat(*n, 64)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeNumberSet(ns []*string, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
// Make room for the slice elements if needed
|
||||
if v.IsNil() || v.Cap() < len(ns) {
|
||||
// What about if ignoring nil/empty values?
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, len(ns)))
|
||||
}
|
||||
case reflect.Array:
|
||||
// Limited to capacity of existing array.
|
||||
case reflect.Interface:
|
||||
if d.UseNumber {
|
||||
set := make([]Number, len(ns))
|
||||
for i, n := range ns {
|
||||
if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(reflect.ValueOf(set))
|
||||
} else {
|
||||
set := make([]float64, len(ns))
|
||||
for i, n := range ns {
|
||||
if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(reflect.ValueOf(set))
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "number set", Type: v.Type()}
|
||||
}
|
||||
|
||||
for i := 0; i < v.Cap() && i < len(ns); i++ {
|
||||
v.SetLen(i + 1)
|
||||
u, elem := indirect(v.Index(i), false)
|
||||
if u != nil {
|
||||
return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{NS: ns})
|
||||
}
|
||||
if err := d.decodeNumber(ns[i], elem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeList(avList []*dynamodb.AttributeValue, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
// Make room for the slice elements if needed
|
||||
if v.IsNil() || v.Cap() < len(avList) {
|
||||
// What about if ignoring nil/empty values?
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, len(avList)))
|
||||
}
|
||||
case reflect.Array:
|
||||
// Limited to capacity of existing array.
|
||||
case reflect.Interface:
|
||||
s := make([]interface{}, len(avList))
|
||||
for i, av := range avList {
|
||||
if err := d.decode(av, reflect.ValueOf(&s[i]).Elem(), tag{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(reflect.ValueOf(s))
|
||||
return nil
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "list", Type: v.Type()}
|
||||
}
|
||||
|
||||
// If v is not a slice, array
|
||||
for i := 0; i < v.Cap() && i < len(avList); i++ {
|
||||
v.SetLen(i + 1)
|
||||
if err := d.decode(avList[i], v.Index(i), tag{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeMap(avMap map[string]*dynamodb.AttributeValue, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Map:
|
||||
t := v.Type()
|
||||
if t.Key().Kind() != reflect.String {
|
||||
return &UnmarshalTypeError{Value: "map string key", Type: t.Key()}
|
||||
}
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.MakeMap(t))
|
||||
}
|
||||
case reflect.Struct:
|
||||
case reflect.Interface:
|
||||
v.Set(reflect.MakeMap(stringInterfaceMapType))
|
||||
v = v.Elem()
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "map", Type: v.Type()}
|
||||
}
|
||||
|
||||
if v.Kind() == reflect.Map {
|
||||
for k, av := range avMap {
|
||||
key := reflect.ValueOf(k)
|
||||
elem := reflect.New(v.Type().Elem()).Elem()
|
||||
if err := d.decode(av, elem, tag{}); err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetMapIndex(key, elem)
|
||||
}
|
||||
} else if v.Kind() == reflect.Struct {
|
||||
fields := unionStructFields(v.Type(), d.MarshalOptions)
|
||||
for k, av := range avMap {
|
||||
if f, ok := fieldByName(fields, k); ok {
|
||||
fv := v.FieldByIndex(f.Index)
|
||||
if err := d.decode(av, fv, f.tag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeNull(v reflect.Value) error {
|
||||
if v.IsValid() && v.CanSet() {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeString(s *string, v reflect.Value, fieldTag tag) error {
|
||||
if fieldTag.AsString {
|
||||
return d.decodeNumber(s, v)
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.String, reflect.Interface:
|
||||
v.Set(reflect.ValueOf(*s))
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "string", Type: v.Type()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeStringSet(ss []*string, v reflect.Value) error {
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
// Make room for the slice elements if needed
|
||||
if v.IsNil() || v.Cap() < len(ss) {
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, len(ss)))
|
||||
}
|
||||
case reflect.Array:
|
||||
// Limited to capacity of existing array.
|
||||
case reflect.Interface:
|
||||
set := make([]string, len(ss))
|
||||
for i, s := range ss {
|
||||
if err := d.decodeString(s, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.Set(reflect.ValueOf(set))
|
||||
return nil
|
||||
default:
|
||||
return &UnmarshalTypeError{Value: "string set", Type: v.Type()}
|
||||
}
|
||||
|
||||
for i := 0; i < v.Cap() && i < len(ss); i++ {
|
||||
v.SetLen(i + 1)
|
||||
u, elem := indirect(v.Index(i), false)
|
||||
if u != nil {
|
||||
return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{SS: ss})
|
||||
}
|
||||
if err := d.decodeString(ss[i], elem, tag{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// indirect will walk a value's interface or pointer value types. Returning
|
||||
// the final value or the value a unmarshaler is defined on.
|
||||
//
|
||||
// Based on the enoding/json type reflect value type indirection in Go Stdlib
|
||||
// https://golang.org/src/encoding/json/decode.go indirect func.
|
||||
func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
|
||||
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
for {
|
||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||
e := v.Elem()
|
||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||
v = e
|
||||
continue
|
||||
}
|
||||
}
|
||||
if v.Kind() != reflect.Ptr {
|
||||
break
|
||||
}
|
||||
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
|
||||
break
|
||||
}
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
if v.Type().NumMethod() > 0 {
|
||||
if u, ok := v.Interface().(Unmarshaler); ok {
|
||||
return u, reflect.Value{}
|
||||
}
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
return nil, v
|
||||
}
|
||||
|
||||
// A Number represents a Attributevalue number literal.
|
||||
type Number string
|
||||
|
||||
// Float64 attempts to cast the number ot a float64, returning
|
||||
// the result of the case or error if the case failed.
|
||||
func (n Number) Float64() (float64, error) {
|
||||
return strconv.ParseFloat(string(n), 64)
|
||||
}
|
||||
|
||||
// Int64 attempts to cast the number ot a int64, returning
|
||||
// the result of the case or error if the case failed.
|
||||
func (n Number) Int64() (int64, error) {
|
||||
return strconv.ParseInt(string(n), 10, 64)
|
||||
}
|
||||
|
||||
// Uint64 attempts to cast the number ot a uint64, returning
|
||||
// the result of the case or error if the case failed.
|
||||
func (n Number) Uint64() (uint64, error) {
|
||||
return strconv.ParseUint(string(n), 10, 64)
|
||||
}
|
||||
|
||||
// String returns the raw number represented as a string
|
||||
func (n Number) String() string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
type emptyOrigError struct{}
|
||||
|
||||
func (e emptyOrigError) OrigErr() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// An UnmarshalTypeError is an error type representing a error
|
||||
// unmarshaling the AttributeValue's element to a Go value type.
|
||||
// Includes details about the AttributeValue type and Go value type.
|
||||
type UnmarshalTypeError struct {
|
||||
emptyOrigError
|
||||
Value string
|
||||
Type reflect.Type
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
// satisfying the error interface
|
||||
func (e *UnmarshalTypeError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code(), e.Message())
|
||||
}
|
||||
|
||||
// Code returns the code of the error, satisfying the awserr.Error
|
||||
// interface.
|
||||
func (e *UnmarshalTypeError) Code() string {
|
||||
return "UnmarshalTypeError"
|
||||
}
|
||||
|
||||
// Message returns the detailed message of the error, satisfying
|
||||
// the awserr.Error interface.
|
||||
func (e *UnmarshalTypeError) Message() string {
|
||||
return "cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
|
||||
}
|
||||
|
||||
// An InvalidUnmarshalError is an error type representing an invalid type
|
||||
// encountered while unmarshaling a AttributeValue to a Go value type.
|
||||
type InvalidUnmarshalError struct {
|
||||
emptyOrigError
|
||||
Type reflect.Type
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
// satisfying the error interface
|
||||
func (e *InvalidUnmarshalError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code(), e.Message())
|
||||
}
|
||||
|
||||
// Code returns the code of the error, satisfying the awserr.Error
|
||||
// interface.
|
||||
func (e *InvalidUnmarshalError) Code() string {
|
||||
return "InvalidUnmarshalError"
|
||||
}
|
||||
|
||||
// Message returns the detailed message of the error, satisfying
|
||||
// the awserr.Error interface.
|
||||
func (e *InvalidUnmarshalError) Message() string {
|
||||
if e.Type == nil {
|
||||
return "cannot unmarshal to nil value"
|
||||
}
|
||||
if e.Type.Kind() != reflect.Ptr {
|
||||
return "cannot unmasrhal to non-pointer value, got " + e.Type.String()
|
||||
}
|
||||
return "cannot unmarshal to nil value, " + e.Type.String()
|
||||
}
|
||||
58
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/doc.go
generated
vendored
Normal file
58
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/doc.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Package dynamodbattribute provides marshaling utilities for marshaling to
|
||||
// dynamodb.AttributeValue types and unmarshaling to Go value types. These
|
||||
// utilities allow you to marshal slices, maps, structs, and scalar values
|
||||
// to and from dynamodb.AttributeValue. These are useful when marshaling
|
||||
// Go value tyes to dynamodb.AttributeValue for DynamoDB requests, or
|
||||
// unmarshaling the dynamodb.AttributeValue back into a Go value type.
|
||||
//
|
||||
// Marshal Go value types to dynamodb.AttributeValue: See (ExampleMarshal)
|
||||
//
|
||||
// type Record struct {
|
||||
// MyField string
|
||||
// Letters []string
|
||||
// A2Num map[string]int
|
||||
// }
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// r := Record{
|
||||
// MyField: "dynamodbattribute.Marshal example",
|
||||
// Letters: []string{"a", "b", "c", "d"},
|
||||
// A2Num: map[string]int{"a": 1, "b": 2, "c": 3},
|
||||
// }
|
||||
// av, err := dynamodbattribute.Marshal(r)
|
||||
// fmt.Println(av, err)
|
||||
//
|
||||
// Unmarshal dynamodb.AttributeValue to Go value type: See (ExampleUnmarshal)
|
||||
//
|
||||
// r2 := Record{}
|
||||
// err = dynamodbattribute.Unmarshal(av, &r2)
|
||||
// fmt.Println(err, reflect.DeepEqual(r, r2))
|
||||
//
|
||||
// Marshal Go value type for DynamoDB.PutItem:
|
||||
//
|
||||
// svc := dynamodb.New(nil)
|
||||
// item, err := dynamodbattribute.MarshalMap(r)
|
||||
// if err != nil {
|
||||
// fmt.Println("Failed to convert", err)
|
||||
// return
|
||||
// }
|
||||
// result, err := svc.PutItem(&dynamodb.PutItemInput{
|
||||
// Item: item,
|
||||
// TableName: aws.String("exampleTable"),
|
||||
// })
|
||||
//
|
||||
//
|
||||
//
|
||||
// The ConvertTo, ConvertToList, ConvertToMap, ConvertFrom, ConvertFromMap
|
||||
// and ConvertFromList methods have been deprecated. The Marshal and Unmarshal
|
||||
// functions should be used instead. The ConvertTo|From marshallers do not
|
||||
// support BinarySet, NumberSet, nor StringSets, and will incorrect marshal
|
||||
// binary data fields in structs as base64 strings.
|
||||
//
|
||||
// The Marshal and Unmarshal functions correct this behavior, and removes
|
||||
// the reliance on encoding.json. `json` struct tags are still supported.
|
||||
// Support for the json.Marshaler nor json.Unmarshaler interfaces have
|
||||
// been removed and replaced with have been replaced with dynamodbattribute.Marshaler
|
||||
// and dynamodbattribute.Unmarshaler interfaces.
|
||||
package dynamodbattribute
|
||||
560
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode.go
generated
vendored
Normal file
560
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode.go
generated
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
package dynamodbattribute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
)
|
||||
|
||||
// A Marshaler is an interface to provide custom marshalling of Go value types
|
||||
// to AttributeValues. Use this to provide custom logic determining how a
|
||||
// Go Value type should be marshaled.
|
||||
//
|
||||
// type ExampleMarshaler struct {
|
||||
// Value int
|
||||
// }
|
||||
// type (m *ExampleMarshaler) MarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error {
|
||||
// n := fmt.Sprintf("%v", m.Value)
|
||||
// av.N = &n
|
||||
//
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
type Marshaler interface {
|
||||
MarshalDynamoDBAttributeValue(*dynamodb.AttributeValue) error
|
||||
}
|
||||
|
||||
// Marshal will serialize the passed in Go value type into a DynamoDB AttributeValue
|
||||
// type. This value can be used in DynamoDB API operations to simplify marshaling
|
||||
// your Go value types into AttributeValues.
|
||||
//
|
||||
// Marshal will recursively transverse the passed in value marshaling its
|
||||
// contents into a AttributeValue. Marshal supports basic scalars
|
||||
// (int,uint,float,bool,string), maps, slices, and structs. Anonymous
|
||||
// nested types are flattened based on Go anonymous type visibility.
|
||||
//
|
||||
// Marshaling slices to AttributeValue will default to a List for all
|
||||
// types except for []byte and [][]byte. []byte will be marshaled as
|
||||
// Binary data (B), and [][]byte will be marshaled as binary data set
|
||||
// (BS).
|
||||
//
|
||||
// `dynamodb` struct tag can be used to control how the value will be
|
||||
// marshaled into a AttributeValue.
|
||||
//
|
||||
// // Field is ignored
|
||||
// Field int `dynamodb:"-"`
|
||||
//
|
||||
// // Field AttributeValue map key "myName"
|
||||
// Field int `dynamodb:"myName"`
|
||||
//
|
||||
// // Field AttributeValue map key "myName", and
|
||||
// // Field is omitted if it is empty
|
||||
// Field int `dynamodb:"myName,omitempty"`
|
||||
//
|
||||
// // Field AttributeValue map key "Field", and
|
||||
// // Field is omitted if it is empty
|
||||
// Field int `dynamodb:",omitempty"`
|
||||
//
|
||||
// // Field's elems will be omitted if empty
|
||||
// // only valid for slices, and maps.
|
||||
// Field []string `dynamodb:",omitemptyelem"`
|
||||
//
|
||||
// // Field will be marshaled as a AttributeValue string
|
||||
// // only value for number types, (int,uint,float)
|
||||
// Field int `dynamodb:",string"`
|
||||
//
|
||||
// // Field will be marshaled as a binary set
|
||||
// Field [][]byte `dynamodb:",binaryset"`
|
||||
//
|
||||
// // Field will be marshaled as a number set
|
||||
// Field []int `dynamodb:",numberset"`
|
||||
//
|
||||
// // Field will be marshaled as a string set
|
||||
// Field []string `dynamodb:",stringset"`
|
||||
//
|
||||
// The omitempty tag is only used during Marshaling and is ignored for
|
||||
// Unmarshal. Any zero value or a value when marshaled results in a
|
||||
// AttributeValue NULL will be added to AttributeValue Maps during struct
|
||||
// marshal. The omitemptyelem tag works the same as omitempty except it
|
||||
// applies to maps and slices instead of struct fields, and will not be
|
||||
// included in the marshaled AttributeValue Map, List, or Set.
|
||||
//
|
||||
// For convenience and backwards compatibility with ConvertTo functions
|
||||
// json struct tags are supported by the Marshal and Unmarshal. If
|
||||
// both json and dynamodbav struct tags are provided the json tag will
|
||||
// be ignored in favor of dynamodbav.
|
||||
//
|
||||
// All struct fields and with anonymous fields, are marshaled unless the
|
||||
// any of the following conditions are meet.
|
||||
//
|
||||
// - the field is not exported
|
||||
// - json or dynamodbav field tag is "-"
|
||||
// - json or dynamodbav field tag specifies "omitempty", and is empty.
|
||||
//
|
||||
// Pointer and interfaces values encode as the value pointed to or contained
|
||||
// in the interface. A nil value encodes as the AttributeValue NULL value.
|
||||
//
|
||||
// Channel, complex, and function values are not encoded and will be skipped
|
||||
// when walking the value to be marshaled.
|
||||
//
|
||||
// When marshaling any error that occurs will halt the marshal and return
|
||||
// the error.
|
||||
//
|
||||
// Marshal cannot represent cyclic data structures and will not handle them.
|
||||
// Passing cyclic structures to Marshal will result in an infinite recursion.
|
||||
func Marshal(in interface{}) (*dynamodb.AttributeValue, error) {
|
||||
return NewEncoder().Encode(in)
|
||||
}
|
||||
|
||||
// MarshalMap is an alias for Marshal func which marshals Go value
|
||||
// type to a map of AttributeValues.
|
||||
func MarshalMap(in interface{}) (map[string]*dynamodb.AttributeValue, error) {
|
||||
av, err := NewEncoder().Encode(in)
|
||||
if err != nil || av == nil || av.M == nil {
|
||||
return map[string]*dynamodb.AttributeValue{}, err
|
||||
}
|
||||
|
||||
return av.M, nil
|
||||
}
|
||||
|
||||
// MarshalList is an alias for Marshal func which marshals Go value
|
||||
// type to a slice of AttributeValues.
|
||||
func MarshalList(in interface{}) ([]*dynamodb.AttributeValue, error) {
|
||||
av, err := NewEncoder().Encode(in)
|
||||
if err != nil || av == nil || av.L == nil {
|
||||
return []*dynamodb.AttributeValue{}, err
|
||||
}
|
||||
|
||||
return av.L, nil
|
||||
}
|
||||
|
||||
// A MarshalOptions is a collection of options shared between marshaling
|
||||
// and unmarshaling
|
||||
type MarshalOptions struct {
|
||||
// States that the encoding/json struct tags should be supported.
|
||||
// if a `dynamodbav` struct tag is also provided the encoding/json
|
||||
// tag will be ignored.
|
||||
//
|
||||
// Enabled by default.
|
||||
SupportJSONTags bool
|
||||
}
|
||||
|
||||
// An Encoder provides marshaling Go value types to AttributeValues.
|
||||
type Encoder struct {
|
||||
MarshalOptions
|
||||
|
||||
// Empty strings, "", will be marked as NULL AttributeValue types.
|
||||
// Empty strings are not valid values for DynamoDB. Will not apply
|
||||
// to lists, sets, or maps. Use the struct tag `omitemptyelem`
|
||||
// to skip empty (zero) values in lists, sets and maps.
|
||||
//
|
||||
// Enabled by default.
|
||||
NullEmptyString bool
|
||||
}
|
||||
|
||||
// NewEncoder creates a new Encoder with default configuration. Use
|
||||
// the `opts` functional options to override the default configuration.
|
||||
func NewEncoder(opts ...func(*Encoder)) *Encoder {
|
||||
e := &Encoder{
|
||||
MarshalOptions: MarshalOptions{
|
||||
SupportJSONTags: true,
|
||||
},
|
||||
NullEmptyString: true,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(e)
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
// Encode will marshal a Go value type to an AttributeValue. Returning
|
||||
// the AttributeValue constructed or error.
|
||||
func (e *Encoder) Encode(in interface{}) (*dynamodb.AttributeValue, error) {
|
||||
av := &dynamodb.AttributeValue{}
|
||||
if err := e.encode(av, reflect.ValueOf(in), tag{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return av, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encode(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error {
|
||||
// Handle both pointers and interface conversion into types
|
||||
v = valueElem(v)
|
||||
|
||||
if v.Kind() != reflect.Invalid {
|
||||
if used, err := tryMarshaler(av, v); used {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if fieldTag.OmitEmpty && emptyValue(v) {
|
||||
encodeNull(av)
|
||||
return nil
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Invalid:
|
||||
encodeNull(av)
|
||||
case reflect.Struct:
|
||||
return e.encodeStruct(av, v)
|
||||
case reflect.Map:
|
||||
return e.encodeMap(av, v, fieldTag)
|
||||
case reflect.Slice, reflect.Array:
|
||||
return e.encodeSlice(av, v, fieldTag)
|
||||
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||
// do nothing for unsupported types
|
||||
default:
|
||||
return e.encodeScalar(av, v, fieldTag)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeStruct(av *dynamodb.AttributeValue, v reflect.Value) error {
|
||||
av.M = map[string]*dynamodb.AttributeValue{}
|
||||
fields := unionStructFields(v.Type(), e.MarshalOptions)
|
||||
for _, f := range fields {
|
||||
if f.Name == "" {
|
||||
return &InvalidMarshalError{msg: "map key cannot be empty"}
|
||||
}
|
||||
|
||||
fv := v.FieldByIndex(f.Index)
|
||||
elem := &dynamodb.AttributeValue{}
|
||||
err := e.encode(elem, fv, f.tag)
|
||||
skip, err := keepOrOmitEmpty(f.OmitEmpty, elem, err)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
av.M[f.Name] = elem
|
||||
}
|
||||
if len(av.M) == 0 {
|
||||
encodeNull(av)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeMap(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error {
|
||||
av.M = map[string]*dynamodb.AttributeValue{}
|
||||
for _, key := range v.MapKeys() {
|
||||
keyName := fmt.Sprint(key.Interface())
|
||||
if keyName == "" {
|
||||
return &InvalidMarshalError{msg: "map key cannot be empty"}
|
||||
}
|
||||
|
||||
elemVal := v.MapIndex(key)
|
||||
elem := &dynamodb.AttributeValue{}
|
||||
err := e.encode(elem, elemVal, tag{})
|
||||
skip, err := keepOrOmitEmpty(fieldTag.OmitEmptyElem, elem, err)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
av.M[keyName] = elem
|
||||
}
|
||||
if len(av.M) == 0 {
|
||||
encodeNull(av)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeSlice(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error {
|
||||
switch typed := v.Interface().(type) {
|
||||
case []byte:
|
||||
if len(typed) == 0 {
|
||||
encodeNull(av)
|
||||
return nil
|
||||
}
|
||||
av.B = append([]byte{}, typed...)
|
||||
default:
|
||||
var elemFn func(dynamodb.AttributeValue) error
|
||||
|
||||
if fieldTag.AsBinSet || v.Type() == byteSliceSlicetype { // Binary Set
|
||||
av.BS = make([][]byte, 0, v.Len())
|
||||
elemFn = func(elem dynamodb.AttributeValue) error {
|
||||
if elem.B == nil {
|
||||
return &InvalidMarshalError{msg: "binary set must only contain non-nil byte slices"}
|
||||
}
|
||||
av.BS = append(av.BS, elem.B)
|
||||
return nil
|
||||
}
|
||||
} else if fieldTag.AsNumSet { // Number Set
|
||||
av.NS = make([]*string, 0, v.Len())
|
||||
elemFn = func(elem dynamodb.AttributeValue) error {
|
||||
if elem.N == nil {
|
||||
return &InvalidMarshalError{msg: "number set must only contain non-nil string numbers"}
|
||||
}
|
||||
av.NS = append(av.NS, elem.N)
|
||||
return nil
|
||||
}
|
||||
} else if fieldTag.AsStrSet { // String Set
|
||||
av.SS = make([]*string, 0, v.Len())
|
||||
elemFn = func(elem dynamodb.AttributeValue) error {
|
||||
if elem.S == nil {
|
||||
return &InvalidMarshalError{msg: "string set must only contain non-nil strings"}
|
||||
}
|
||||
av.SS = append(av.SS, elem.S)
|
||||
return nil
|
||||
}
|
||||
} else { // List
|
||||
av.L = make([]*dynamodb.AttributeValue, 0, v.Len())
|
||||
elemFn = func(elem dynamodb.AttributeValue) error {
|
||||
av.L = append(av.L, &elem)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if n, err := e.encodeList(v, fieldTag, elemFn); err != nil {
|
||||
return err
|
||||
} else if n == 0 {
|
||||
encodeNull(av)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeList(v reflect.Value, fieldTag tag, elemFn func(dynamodb.AttributeValue) error) (int, error) {
|
||||
count := 0
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
elem := dynamodb.AttributeValue{}
|
||||
err := e.encode(&elem, v.Index(i), tag{OmitEmpty: fieldTag.OmitEmptyElem})
|
||||
skip, err := keepOrOmitEmpty(fieldTag.OmitEmptyElem, &elem, err)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := elemFn(elem); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeScalar(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error {
|
||||
switch typed := v.Interface().(type) {
|
||||
case bool:
|
||||
av.BOOL = new(bool)
|
||||
*av.BOOL = typed
|
||||
case string:
|
||||
if err := e.encodeString(av, v); err != nil {
|
||||
return err
|
||||
}
|
||||
case Number:
|
||||
s := string(typed)
|
||||
if fieldTag.AsString {
|
||||
av.S = &s
|
||||
} else {
|
||||
av.N = &s
|
||||
}
|
||||
default:
|
||||
// Fallback to encoding numbers, will return invalid type if not supported
|
||||
if err := e.encodeNumber(av, v); err != nil {
|
||||
return err
|
||||
}
|
||||
if fieldTag.AsString && av.NULL == nil && av.N != nil {
|
||||
av.S = av.N
|
||||
av.N = nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeNumber(av *dynamodb.AttributeValue, v reflect.Value) error {
|
||||
if used, err := tryMarshaler(av, v); used {
|
||||
return err
|
||||
}
|
||||
|
||||
var out string
|
||||
switch typed := v.Interface().(type) {
|
||||
case int:
|
||||
out = encodeInt(int64(typed))
|
||||
case int8:
|
||||
out = encodeInt(int64(typed))
|
||||
case int16:
|
||||
out = encodeInt(int64(typed))
|
||||
case int32:
|
||||
out = encodeInt(int64(typed))
|
||||
case int64:
|
||||
out = encodeInt(typed)
|
||||
case uint:
|
||||
out = encodeUint(uint64(typed))
|
||||
case uint8:
|
||||
out = encodeUint(uint64(typed))
|
||||
case uint16:
|
||||
out = encodeUint(uint64(typed))
|
||||
case uint32:
|
||||
out = encodeUint(uint64(typed))
|
||||
case uint64:
|
||||
out = encodeUint(typed)
|
||||
case float32:
|
||||
out = encodeFloat(float64(typed))
|
||||
case float64:
|
||||
out = encodeFloat(typed)
|
||||
default:
|
||||
return &unsupportedMarshalTypeError{Type: v.Type()}
|
||||
}
|
||||
|
||||
av.N = &out
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeString(av *dynamodb.AttributeValue, v reflect.Value) error {
|
||||
if used, err := tryMarshaler(av, v); used {
|
||||
return err
|
||||
}
|
||||
|
||||
switch typed := v.Interface().(type) {
|
||||
case string:
|
||||
if len(typed) == 0 && e.NullEmptyString {
|
||||
encodeNull(av)
|
||||
} else {
|
||||
av.S = &typed
|
||||
}
|
||||
default:
|
||||
return &unsupportedMarshalTypeError{Type: v.Type()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeInt(i int64) string {
|
||||
return strconv.FormatInt(i, 10)
|
||||
}
|
||||
func encodeUint(u uint64) string {
|
||||
return strconv.FormatUint(u, 10)
|
||||
}
|
||||
func encodeFloat(f float64) string {
|
||||
return strconv.FormatFloat(f, 'f', -1, 64)
|
||||
}
|
||||
func encodeNull(av *dynamodb.AttributeValue) {
|
||||
t := true
|
||||
*av = dynamodb.AttributeValue{NULL: &t}
|
||||
}
|
||||
|
||||
func valueElem(v reflect.Value) reflect.Value {
|
||||
switch v.Kind() {
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
for v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func emptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func tryMarshaler(av *dynamodb.AttributeValue, v reflect.Value) (bool, error) {
|
||||
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
|
||||
if v.Type().NumMethod() == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if m, ok := v.Interface().(Marshaler); ok {
|
||||
return true, m.MarshalDynamoDBAttributeValue(av)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func keepOrOmitEmpty(omitEmpty bool, av *dynamodb.AttributeValue, err error) (bool, error) {
|
||||
if err != nil {
|
||||
if _, ok := err.(*unsupportedMarshalTypeError); ok {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
if av.NULL != nil && omitEmpty {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// An InvalidMarshalError is an error type representing an error
|
||||
// occurring when marshaling a Go value type to an AttributeValue.
|
||||
type InvalidMarshalError struct {
|
||||
emptyOrigError
|
||||
msg string
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
// satisfying the error interface
|
||||
func (e *InvalidMarshalError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code(), e.Message())
|
||||
}
|
||||
|
||||
// Code returns the code of the error, satisfying the awserr.Error
|
||||
// interface.
|
||||
func (e *InvalidMarshalError) Code() string {
|
||||
return "InvalidMarshalError"
|
||||
}
|
||||
|
||||
// Message returns the detailed message of the error, satisfying
|
||||
// the awserr.Error interface.
|
||||
func (e *InvalidMarshalError) Message() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
// An unsupportedMarshalTypeError represents a Go value type
|
||||
// which cannot be marshaled into an AttributeValue and should
|
||||
// be skipped by the marshaler.
|
||||
type unsupportedMarshalTypeError struct {
|
||||
emptyOrigError
|
||||
Type reflect.Type
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
// satisfying the error interface
|
||||
func (e *unsupportedMarshalTypeError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code(), e.Message())
|
||||
}
|
||||
|
||||
// Code returns the code of the error, satisfying the awserr.Error
|
||||
// interface.
|
||||
func (e *unsupportedMarshalTypeError) Code() string {
|
||||
return "unsupportedMarshalTypeError"
|
||||
}
|
||||
|
||||
// Message returns the detailed message of the error, satisfying
|
||||
// the awserr.Error interface.
|
||||
func (e *unsupportedMarshalTypeError) Message() string {
|
||||
return "Go value type " + e.Type.String() + " is not supported"
|
||||
}
|
||||
269
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field.go
generated
vendored
Normal file
269
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field.go
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
package dynamodbattribute
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type field struct {
|
||||
tag
|
||||
|
||||
Name string
|
||||
NameFromTag bool
|
||||
|
||||
Index []int
|
||||
Type reflect.Type
|
||||
}
|
||||
|
||||
func fieldByName(fields []field, name string) (field, bool) {
|
||||
foldExists := false
|
||||
foldField := field{}
|
||||
|
||||
for _, f := range fields {
|
||||
if f.Name == name {
|
||||
return f, true
|
||||
}
|
||||
if !foldExists && strings.EqualFold(f.Name, name) {
|
||||
foldField = f
|
||||
foldExists = true
|
||||
}
|
||||
}
|
||||
|
||||
return foldField, foldExists
|
||||
}
|
||||
|
||||
func buildField(pIdx []int, i int, sf reflect.StructField, fieldTag tag) field {
|
||||
f := field{
|
||||
Name: sf.Name,
|
||||
Type: sf.Type,
|
||||
tag: fieldTag,
|
||||
}
|
||||
if len(fieldTag.Name) != 0 {
|
||||
f.NameFromTag = true
|
||||
f.Name = fieldTag.Name
|
||||
}
|
||||
|
||||
f.Index = make([]int, len(pIdx)+1)
|
||||
copy(f.Index, pIdx)
|
||||
f.Index[len(pIdx)] = i
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func unionStructFields(t reflect.Type, opts MarshalOptions) []field {
|
||||
fields := enumFields(t, opts)
|
||||
|
||||
sort.Sort(fieldsByName(fields))
|
||||
|
||||
fields = visibleFields(fields)
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// enumFields will recursively iterate through a structure and its nested
|
||||
// anonymous fields.
|
||||
//
|
||||
// Based on the enoding/json struct field enumeration of the Go Stdlib
|
||||
// https://golang.org/src/encoding/json/encode.go typeField func.
|
||||
func enumFields(t reflect.Type, opts MarshalOptions) []field {
|
||||
// Fields to explore
|
||||
current := []field{}
|
||||
next := []field{{Type: t}}
|
||||
|
||||
// count of queued names
|
||||
count := map[reflect.Type]int{}
|
||||
nextCount := map[reflect.Type]int{}
|
||||
|
||||
visited := map[reflect.Type]struct{}{}
|
||||
fields := []field{}
|
||||
|
||||
for len(next) > 0 {
|
||||
current, next = next, current[:0]
|
||||
count, nextCount = nextCount, map[reflect.Type]int{}
|
||||
|
||||
for _, f := range current {
|
||||
if _, ok := visited[f.Type]; ok {
|
||||
continue
|
||||
}
|
||||
visited[f.Type] = struct{}{}
|
||||
|
||||
for i := 0; i < f.Type.NumField(); i++ {
|
||||
sf := f.Type.Field(i)
|
||||
if sf.PkgPath != "" && !sf.Anonymous {
|
||||
// Ignore unexported and non-anonymous fields
|
||||
// unexported but anonymous field may still be used if
|
||||
// the type has exported nested fields
|
||||
continue
|
||||
}
|
||||
|
||||
fieldTag := tag{}
|
||||
fieldTag.parseAVTag(sf.Tag)
|
||||
if opts.SupportJSONTags && fieldTag == (tag{}) {
|
||||
fieldTag.parseJSONTag(sf.Tag)
|
||||
}
|
||||
|
||||
if fieldTag.Ignore {
|
||||
continue
|
||||
}
|
||||
|
||||
ft := sf.Type
|
||||
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
structField := buildField(f.Index, i, sf, fieldTag)
|
||||
structField.Type = ft
|
||||
|
||||
if !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
fields = append(fields, structField)
|
||||
if count[f.Type] > 1 {
|
||||
// If there were multiple instances, add a second,
|
||||
// so that the annihilation code will see a duplicate.
|
||||
// It only cares about the distinction between 1 or 2,
|
||||
// so don't bother generating any more copies.
|
||||
fields = append(fields, structField)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Record new anon struct to explore next round
|
||||
nextCount[ft]++
|
||||
if nextCount[ft] == 1 {
|
||||
next = append(next, structField)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// visibleFields will return a slice of fields which are visible based on
|
||||
// Go's standard visiblity rules with the exception of ties being broken
|
||||
// by depth and struct tag naming.
|
||||
//
|
||||
// Based on the enoding/json field filtering of the Go Stdlib
|
||||
// https://golang.org/src/encoding/json/encode.go typeField func.
|
||||
func visibleFields(fields []field) []field {
|
||||
// Delete all fields that are hidden by the Go rules for embedded fields,
|
||||
// except that fields with JSON tags are promoted.
|
||||
|
||||
// The fields are sorted in primary order of name, secondary order
|
||||
// of field index length. Loop over names; for each name, delete
|
||||
// hidden fields by choosing the one dominant field that survives.
|
||||
out := fields[:0]
|
||||
for advance, i := 0, 0; i < len(fields); i += advance {
|
||||
// One iteration per name.
|
||||
// Find the sequence of fields with the name of this first field.
|
||||
fi := fields[i]
|
||||
name := fi.Name
|
||||
for advance = 1; i+advance < len(fields); advance++ {
|
||||
fj := fields[i+advance]
|
||||
if fj.Name != name {
|
||||
break
|
||||
}
|
||||
}
|
||||
if advance == 1 { // Only one field with this name
|
||||
out = append(out, fi)
|
||||
continue
|
||||
}
|
||||
dominant, ok := dominantField(fields[i : i+advance])
|
||||
if ok {
|
||||
out = append(out, dominant)
|
||||
}
|
||||
}
|
||||
|
||||
fields = out
|
||||
sort.Sort(fieldsByIndex(fields))
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// dominantField looks through the fields, all of which are known to
|
||||
// have the same name, to find the single field that dominates the
|
||||
// others using Go's embedding rules, modified by the presence of
|
||||
// JSON tags. If there are multiple top-level fields, the boolean
|
||||
// will be false: This condition is an error in Go and we skip all
|
||||
// the fields.
|
||||
//
|
||||
// Based on the enoding/json field filtering of the Go Stdlib
|
||||
// https://golang.org/src/encoding/json/encode.go dominantField func.
|
||||
func dominantField(fields []field) (field, bool) {
|
||||
// The fields are sorted in increasing index-length order. The winner
|
||||
// must therefore be one with the shortest index length. Drop all
|
||||
// longer entries, which is easy: just truncate the slice.
|
||||
length := len(fields[0].Index)
|
||||
tagged := -1 // Index of first tagged field.
|
||||
for i, f := range fields {
|
||||
if len(f.Index) > length {
|
||||
fields = fields[:i]
|
||||
break
|
||||
}
|
||||
if f.NameFromTag {
|
||||
if tagged >= 0 {
|
||||
// Multiple tagged fields at the same level: conflict.
|
||||
// Return no field.
|
||||
return field{}, false
|
||||
}
|
||||
tagged = i
|
||||
}
|
||||
}
|
||||
if tagged >= 0 {
|
||||
return fields[tagged], true
|
||||
}
|
||||
// All remaining fields have the same length. If there's more than one,
|
||||
// we have a conflict (two fields named "X" at the same level) and we
|
||||
// return no field.
|
||||
if len(fields) > 1 {
|
||||
return field{}, false
|
||||
}
|
||||
return fields[0], true
|
||||
}
|
||||
|
||||
// fieldsByName sorts field by name, breaking ties with depth,
|
||||
// then breaking ties with "name came from json tag", then
|
||||
// breaking ties with index sequence.
|
||||
//
|
||||
// Based on the enoding/json field filtering of the Go Stdlib
|
||||
// https://golang.org/src/encoding/json/encode.go fieldsByName type.
|
||||
type fieldsByName []field
|
||||
|
||||
func (x fieldsByName) Len() int { return len(x) }
|
||||
|
||||
func (x fieldsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x fieldsByName) Less(i, j int) bool {
|
||||
if x[i].Name != x[j].Name {
|
||||
return x[i].Name < x[j].Name
|
||||
}
|
||||
if len(x[i].Index) != len(x[j].Index) {
|
||||
return len(x[i].Index) < len(x[j].Index)
|
||||
}
|
||||
if x[i].NameFromTag != x[j].NameFromTag {
|
||||
return x[i].NameFromTag
|
||||
}
|
||||
return fieldsByIndex(x).Less(i, j)
|
||||
}
|
||||
|
||||
// fieldsByIndex sorts field by index sequence.
|
||||
//
|
||||
// Based on the enoding/json field filtering of the Go Stdlib
|
||||
// https://golang.org/src/encoding/json/encode.go fieldsByIndex type.
|
||||
type fieldsByIndex []field
|
||||
|
||||
func (x fieldsByIndex) Len() int { return len(x) }
|
||||
|
||||
func (x fieldsByIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x fieldsByIndex) Less(i, j int) bool {
|
||||
for k, xik := range x[i].Index {
|
||||
if k >= len(x[j].Index) {
|
||||
return false
|
||||
}
|
||||
if xik != x[j].Index[k] {
|
||||
return xik < x[j].Index[k]
|
||||
}
|
||||
}
|
||||
return len(x[i].Index) < len(x[j].Index)
|
||||
}
|
||||
65
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag.go
generated
vendored
Normal file
65
vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package dynamodbattribute
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type tag struct {
|
||||
Name string
|
||||
Ignore bool
|
||||
OmitEmpty bool
|
||||
OmitEmptyElem bool
|
||||
AsString bool
|
||||
AsBinSet, AsNumSet, AsStrSet bool
|
||||
}
|
||||
|
||||
func (t *tag) parseAVTag(structTag reflect.StructTag) {
|
||||
tagStr := structTag.Get("dynamodbav")
|
||||
if len(tagStr) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
t.parseTagStr(tagStr)
|
||||
}
|
||||
|
||||
func (t *tag) parseJSONTag(structTag reflect.StructTag) {
|
||||
tagStr := structTag.Get("json")
|
||||
if len(tagStr) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
t.parseTagStr(tagStr)
|
||||
}
|
||||
|
||||
func (t *tag) parseTagStr(tagStr string) {
|
||||
parts := strings.SplitN(tagStr, ",", 2)
|
||||
if len(parts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if name := parts[0]; name == "-" {
|
||||
t.Name = ""
|
||||
t.Ignore = true
|
||||
} else {
|
||||
t.Name = name
|
||||
t.Ignore = false
|
||||
}
|
||||
|
||||
for _, opt := range parts[1:] {
|
||||
switch opt {
|
||||
case "omitempty":
|
||||
t.OmitEmpty = true
|
||||
case "omitemptyelem":
|
||||
t.OmitEmptyElem = true
|
||||
case "string":
|
||||
t.AsString = true
|
||||
case "binaryset":
|
||||
t.AsBinSet = true
|
||||
case "numberset":
|
||||
t.AsNumSet = true
|
||||
case "stringset":
|
||||
t.AsStrSet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user