1// +build codegen 2 3package api 4 5import ( 6 "encoding/json" 7 "fmt" 8 "reflect" 9 "strings" 10 11 "github.com/aws/aws-sdk-go/private/util" 12) 13 14// A paramFiller provides string formatting for a shape and its types. 15type paramFiller struct { 16 prefixPackageName bool 17} 18 19// typeName returns the type name of a shape. 20func (f paramFiller) typeName(shape *Shape) string { 21 if f.prefixPackageName && shape.Type == "structure" { 22 return "*" + shape.API.PackageName() + "." + shape.GoTypeElem() 23 } 24 return shape.GoType() 25} 26 27// ParamsStructFromJSON returns a JSON string representation of a structure. 28func ParamsStructFromJSON(value interface{}, shape *Shape, prefixPackageName bool) string { 29 f := paramFiller{prefixPackageName: prefixPackageName} 30 return util.GoFmt(f.paramsStructAny(value, shape)) 31} 32 33// paramsStructAny returns the string representation of any value. 34func (f paramFiller) paramsStructAny(value interface{}, shape *Shape) string { 35 if value == nil { 36 return "" 37 } 38 39 switch shape.Type { 40 case "structure": 41 if value != nil { 42 vmap := value.(map[string]interface{}) 43 return f.paramsStructStruct(vmap, shape) 44 } 45 case "list": 46 vlist := value.([]interface{}) 47 return f.paramsStructList(vlist, shape) 48 case "map": 49 vmap := value.(map[string]interface{}) 50 return f.paramsStructMap(vmap, shape) 51 case "string", "character": 52 v := reflect.Indirect(reflect.ValueOf(value)) 53 if v.IsValid() { 54 return fmt.Sprintf("aws.String(%#v)", v.Interface()) 55 } 56 case "blob": 57 v := reflect.Indirect(reflect.ValueOf(value)) 58 if v.IsValid() && shape.Streaming { 59 return fmt.Sprintf("bytes.NewReader([]byte(%#v))", v.Interface()) 60 } else if v.IsValid() { 61 return fmt.Sprintf("[]byte(%#v)", v.Interface()) 62 } 63 case "boolean": 64 v := reflect.Indirect(reflect.ValueOf(value)) 65 if v.IsValid() { 66 return fmt.Sprintf("aws.Bool(%#v)", v.Interface()) 67 } 68 case "integer", "long": 69 v := reflect.Indirect(reflect.ValueOf(value)) 70 if v.IsValid() { 71 return fmt.Sprintf("aws.Int64(%v)", v.Interface()) 72 } 73 case "float", "double": 74 v := reflect.Indirect(reflect.ValueOf(value)) 75 if v.IsValid() { 76 return fmt.Sprintf("aws.Float64(%v)", v.Interface()) 77 } 78 case "timestamp": 79 v := reflect.Indirect(reflect.ValueOf(value)) 80 if v.IsValid() { 81 return fmt.Sprintf("aws.Time(time.Unix(%d, 0))", int(v.Float())) 82 } 83 case "jsonvalue": 84 v, err := json.Marshal(value) 85 if err != nil { 86 panic("failed to marshal JSONValue, " + err.Error()) 87 } 88 const tmpl = `func() aws.JSONValue { 89 var m aws.JSONValue 90 if err := json.Unmarshal([]byte(%q), &m); err != nil { 91 panic("failed to unmarshal JSONValue, "+err.Error()) 92 } 93 return m 94 }()` 95 return fmt.Sprintf(tmpl, string(v)) 96 default: 97 panic("Unhandled type " + shape.Type) 98 } 99 return "" 100} 101 102// paramsStructStruct returns the string representation of a structure 103func (f paramFiller) paramsStructStruct(value map[string]interface{}, shape *Shape) string { 104 out := "&" + f.typeName(shape)[1:] + "{\n" 105 for _, n := range shape.MemberNames() { 106 ref := shape.MemberRefs[n] 107 name := findParamMember(value, n) 108 109 if val := f.paramsStructAny(value[name], ref.Shape); val != "" { 110 out += fmt.Sprintf("%s: %s,\n", n, val) 111 } 112 } 113 out += "}" 114 return out 115} 116 117// paramsStructMap returns the string representation of a map of values 118func (f paramFiller) paramsStructMap(value map[string]interface{}, shape *Shape) string { 119 out := f.typeName(shape) + "{\n" 120 keys := util.SortedKeys(value) 121 for _, k := range keys { 122 v := value[k] 123 out += fmt.Sprintf("%q: %s,\n", k, f.paramsStructAny(v, shape.ValueRef.Shape)) 124 } 125 out += "}" 126 return out 127} 128 129// paramsStructList returns the string representation of slice of values 130func (f paramFiller) paramsStructList(value []interface{}, shape *Shape) string { 131 out := f.typeName(shape) + "{\n" 132 for _, v := range value { 133 out += fmt.Sprintf("%s,\n", f.paramsStructAny(v, shape.MemberRef.Shape)) 134 } 135 out += "}" 136 return out 137} 138 139// findParamMember searches a map for a key ignoring case. Returns the map key if found. 140func findParamMember(value map[string]interface{}, key string) string { 141 for actualKey := range value { 142 if strings.EqualFold(key, actualKey) { 143 return actualKey 144 } 145 } 146 return "" 147} 148