OSDN Git Service

feat(warder): add warder backbone (#181)
[bytom/vapor.git] / vendor / github.com / gin-gonic / gin / binding / form_mapping.go
1 // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
2 // Use of this source code is governed by a MIT style
3 // license that can be found in the LICENSE file.
4
5 package binding
6
7 import (
8         "errors"
9         "reflect"
10         "strconv"
11         "strings"
12         "time"
13 )
14
15 func mapForm(ptr interface{}, form map[string][]string) error {
16         typ := reflect.TypeOf(ptr).Elem()
17         val := reflect.ValueOf(ptr).Elem()
18         for i := 0; i < typ.NumField(); i++ {
19                 typeField := typ.Field(i)
20                 structField := val.Field(i)
21                 if !structField.CanSet() {
22                         continue
23                 }
24
25                 structFieldKind := structField.Kind()
26                 inputFieldName := typeField.Tag.Get("form")
27                 inputFieldNameList := strings.Split(inputFieldName, ",")
28                 inputFieldName = inputFieldNameList[0]
29                 var defaultValue string
30                 if len(inputFieldNameList) > 1 {
31                         defaultList := strings.SplitN(inputFieldNameList[1], "=", 2)
32                         if defaultList[0] == "default" {
33                                 defaultValue = defaultList[1]
34                         }
35                 }
36                 if inputFieldName == "" {
37                         inputFieldName = typeField.Name
38
39                         // if "form" tag is nil, we inspect if the field is a struct or struct pointer.
40                         // this would not make sense for JSON parsing but it does for a form
41                         // since data is flatten
42                         if structFieldKind == reflect.Ptr {
43                                 if !structField.Elem().IsValid() {
44                                         structField.Set(reflect.New(structField.Type().Elem()))
45                                 }
46                                 structField = structField.Elem()
47                                 structFieldKind = structField.Kind()
48                         }
49                         if structFieldKind == reflect.Struct {
50                                 err := mapForm(structField.Addr().Interface(), form)
51                                 if err != nil {
52                                         return err
53                                 }
54                                 continue
55                         }
56                 }
57                 inputValue, exists := form[inputFieldName]
58
59                 if !exists {
60                         if defaultValue == "" {
61                                 continue
62                         }
63                         inputValue = make([]string, 1)
64                         inputValue[0] = defaultValue
65                 }
66
67                 numElems := len(inputValue)
68                 if structFieldKind == reflect.Slice && numElems > 0 {
69                         sliceOf := structField.Type().Elem().Kind()
70                         slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
71                         for i := 0; i < numElems; i++ {
72                                 if err := setWithProperType(sliceOf, inputValue[i], slice.Index(i)); err != nil {
73                                         return err
74                                 }
75                         }
76                         val.Field(i).Set(slice)
77                 } else {
78                         if _, isTime := structField.Interface().(time.Time); isTime {
79                                 if err := setTimeField(inputValue[0], typeField, structField); err != nil {
80                                         return err
81                                 }
82                                 continue
83                         }
84                         if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
85                                 return err
86                         }
87                 }
88         }
89         return nil
90 }
91
92 func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
93         switch valueKind {
94         case reflect.Int:
95                 return setIntField(val, 0, structField)
96         case reflect.Int8:
97                 return setIntField(val, 8, structField)
98         case reflect.Int16:
99                 return setIntField(val, 16, structField)
100         case reflect.Int32:
101                 return setIntField(val, 32, structField)
102         case reflect.Int64:
103                 return setIntField(val, 64, structField)
104         case reflect.Uint:
105                 return setUintField(val, 0, structField)
106         case reflect.Uint8:
107                 return setUintField(val, 8, structField)
108         case reflect.Uint16:
109                 return setUintField(val, 16, structField)
110         case reflect.Uint32:
111                 return setUintField(val, 32, structField)
112         case reflect.Uint64:
113                 return setUintField(val, 64, structField)
114         case reflect.Bool:
115                 return setBoolField(val, structField)
116         case reflect.Float32:
117                 return setFloatField(val, 32, structField)
118         case reflect.Float64:
119                 return setFloatField(val, 64, structField)
120         case reflect.String:
121                 structField.SetString(val)
122         case reflect.Ptr:
123                 if !structField.Elem().IsValid() {
124                         structField.Set(reflect.New(structField.Type().Elem()))
125                 }
126                 structFieldElem := structField.Elem()
127                 return setWithProperType(structFieldElem.Kind(), val, structFieldElem)
128         default:
129                 return errors.New("Unknown type")
130         }
131         return nil
132 }
133
134 func setIntField(val string, bitSize int, field reflect.Value) error {
135         if val == "" {
136                 val = "0"
137         }
138         intVal, err := strconv.ParseInt(val, 10, bitSize)
139         if err == nil {
140                 field.SetInt(intVal)
141         }
142         return err
143 }
144
145 func setUintField(val string, bitSize int, field reflect.Value) error {
146         if val == "" {
147                 val = "0"
148         }
149         uintVal, err := strconv.ParseUint(val, 10, bitSize)
150         if err == nil {
151                 field.SetUint(uintVal)
152         }
153         return err
154 }
155
156 func setBoolField(val string, field reflect.Value) error {
157         if val == "" {
158                 val = "false"
159         }
160         boolVal, err := strconv.ParseBool(val)
161         if err == nil {
162                 field.SetBool(boolVal)
163         }
164         return err
165 }
166
167 func setFloatField(val string, bitSize int, field reflect.Value) error {
168         if val == "" {
169                 val = "0.0"
170         }
171         floatVal, err := strconv.ParseFloat(val, bitSize)
172         if err == nil {
173                 field.SetFloat(floatVal)
174         }
175         return err
176 }
177
178 func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
179         timeFormat := structField.Tag.Get("time_format")
180         if timeFormat == "" {
181                 return errors.New("Blank time format")
182         }
183
184         if val == "" {
185                 value.Set(reflect.ValueOf(time.Time{}))
186                 return nil
187         }
188
189         l := time.Local
190         if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
191                 l = time.UTC
192         }
193
194         if locTag := structField.Tag.Get("time_location"); locTag != "" {
195                 loc, err := time.LoadLocation(locTag)
196                 if err != nil {
197                         return err
198                 }
199                 l = loc
200         }
201
202         t, err := time.ParseInLocation(timeFormat, val, l)
203         if err != nil {
204                 return err
205         }
206
207         value.Set(reflect.ValueOf(t))
208         return nil
209 }