OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // HEAVILY adapted from github.com/golang/appengine/datastore | 5 // HEAVILY adapted from github.com/golang/appengine/datastore |
6 | 6 |
7 package datastore | 7 package datastore |
8 | 8 |
9 import ( | 9 import ( |
10 "fmt" | 10 "fmt" |
11 "reflect" | 11 "reflect" |
12 "strconv" | 12 "strconv" |
13 "strings" | 13 "strings" |
14 "sync" | 14 "sync" |
15 "time" | |
16 "unicode" | 15 "unicode" |
17 | 16 |
18 "github.com/luci/gae/service/blobstore" | |
19 "github.com/luci/luci-go/common/errors" | 17 "github.com/luci/luci-go/common/errors" |
20 ) | 18 ) |
21 | 19 |
22 // Entities with more than this many indexed properties will not be saved. | 20 // Entities with more than this many indexed properties will not be saved. |
23 const maxIndexedProperties = 20000 | 21 const maxIndexedProperties = 20000 |
24 | 22 |
25 type structTag struct { | 23 type structTag struct { |
26 name string | 24 name string |
27 idxSetting IndexSetting | 25 idxSetting IndexSetting |
28 isSlice bool | 26 isSlice bool |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 } | 129 } |
132 | 130 |
133 var slice reflect.Value | 131 var slice reflect.Value |
134 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { | 132 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { |
135 slice = v | 133 slice = v |
136 v = reflect.New(v.Type().Elem()).Elem() | 134 v = reflect.New(v.Type().Elem()).Elem() |
137 } else if requireSlice { | 135 } else if requireSlice { |
138 return "multiple-valued property requires a slice field type" | 136 return "multiple-valued property requires a slice field type" |
139 } | 137 } |
140 | 138 |
141 pVal := p.Value() | |
142 | |
143 if ret, ok := doConversion(v); ok { | 139 if ret, ok := doConversion(v); ok { |
144 if ret != "" { | 140 if ret != "" { |
145 return ret | 141 return ret |
146 } | 142 } |
147 } else { | 143 } else { |
148 knd := v.Kind() | 144 knd := v.Kind() |
149 if v.Type().Implements(typeOfKey) { | 145 if v.Type().Implements(typeOfKey) { |
150 knd = reflect.Interface | 146 knd = reflect.Interface |
151 } | 147 } |
148 | |
149 project := PTNull | |
150 overflow := (func(interface{}) bool)(nil) | |
151 set := (func(interface{}))(nil) | |
152 | |
152 switch knd { | 153 switch knd { |
153 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, re flect.Int64: | 154 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, re flect.Int64: |
154 » » » x, ok := pVal.(int64) | 155 » » » project = PTInt |
155 » » » if !ok && pVal != nil { | 156 » » » overflow = func(x interface{}) bool { return v.OverflowI nt(x.(int64)) } |
156 » » » » return typeMismatchReason(pVal, v) | 157 » » » set = func(x interface{}) { v.SetInt(x.(int64)) } |
157 » » » } | |
158 » » » if v.OverflowInt(x) { | |
159 » » » » return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type()) | |
160 » » » } | |
161 » » » v.SetInt(x) | |
162 case reflect.Bool: | 158 case reflect.Bool: |
163 » » » x, ok := pVal.(bool) | 159 » » » project = PTBool |
164 » » » if !ok && pVal != nil { | 160 » » » set = func(x interface{}) { v.SetBool(x.(bool)) } |
165 » » » » return typeMismatchReason(pVal, v) | |
166 » » » } | |
167 » » » v.SetBool(x) | |
168 case reflect.String: | 161 case reflect.String: |
169 » » » switch x := pVal.(type) { | 162 » » » project = PTString |
170 » » » case blobstore.Key: | 163 » » » set = func(x interface{}) { v.SetString(x.(string)) } |
171 » » » » v.SetString(string(x)) | 164 » » case reflect.Float32, reflect.Float64: |
172 » » » case string: | 165 » » » project = PTFloat |
173 » » » » v.SetString(x) | 166 » » » overflow = func(x interface{}) bool { return v.OverflowF loat(x.(float64)) } |
174 » » » default: | 167 » » » set = func(x interface{}) { v.SetFloat(x.(float64)) } |
175 » » » » if pVal != nil { | 168 » » case reflect.Interface: |
dnj (Google)
2015/09/10 16:26:11
Before you were checking if the type was Key. Is b
iannucci
2015/09/10 17:29:21
No I wasn't. I was casting the property value to a
| |
176 » » » » » return typeMismatchReason(pVal, v) | 169 » » » project = PTKey |
170 » » » set = func(x interface{}) { | |
171 » » » » if k, ok := x.(Key); ok { | |
172 » » » » » v.Set(reflect.ValueOf(k)) | |
177 } | 173 } |
178 } | 174 } |
179 case reflect.Float32, reflect.Float64: | |
180 x, ok := pVal.(float64) | |
181 if !ok && pVal != nil { | |
182 return typeMismatchReason(pVal, v) | |
183 } | |
184 if v.OverflowFloat(x) { | |
185 return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type()) | |
186 } | |
187 v.SetFloat(x) | |
188 case reflect.Interface: | |
189 x, ok := pVal.(Key) | |
190 if !ok && pVal != nil { | |
191 return typeMismatchReason(pVal, v) | |
192 } | |
193 if x != nil { | |
194 v.Set(reflect.ValueOf(x)) | |
195 } | |
196 case reflect.Struct: | 175 case reflect.Struct: |
197 switch v.Type() { | 176 switch v.Type() { |
198 case typeOfTime: | 177 case typeOfTime: |
199 » » » » x, ok := pVal.(time.Time) | 178 » » » » project = PTTime |
200 » » » » if !ok && pVal != nil { | 179 » » » » set = func(x interface{}) { v.Set(reflect.ValueO f(x)) } |
201 » » » » » return typeMismatchReason(pVal, v) | |
202 » » » » } | |
203 » » » » v.Set(reflect.ValueOf(x)) | |
204 case typeOfGeoPoint: | 180 case typeOfGeoPoint: |
205 » » » » x, ok := pVal.(GeoPoint) | 181 » » » » project = PTGeoPoint |
206 » » » » if !ok && pVal != nil { | 182 » » » » set = func(x interface{}) { v.Set(reflect.ValueO f(x)) } |
207 » » » » » return typeMismatchReason(pVal, v) | |
208 » » » » } | |
209 » » » » v.Set(reflect.ValueOf(x)) | |
210 default: | 183 default: |
211 » » » » panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v))) | 184 » » » » panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(p.value, v))) |
212 } | 185 } |
213 case reflect.Slice: | 186 case reflect.Slice: |
214 » » » switch x := pVal.(type) { | 187 » » » project = PTBytes |
215 » » » case []byte: | 188 » » » set = func(x interface{}) { |
216 » » » » v.SetBytes(x) | 189 » » » » v.SetBytes(reflect.ValueOf(x).Bytes()) |
217 » » » case ByteString: | |
218 » » » » v.SetBytes([]byte(x)) | |
219 » » » default: | |
220 » » » » panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v))) | |
221 } | 190 } |
222 default: | 191 default: |
223 » » » panic(fmt.Errorf("helper: impossible: %s", typeMismatchR eason(pVal, v))) | 192 » » » panic(fmt.Errorf("helper: impossible: %s", typeMismatchR eason(p.value, v))) |
224 } | 193 } |
194 | |
195 pVal, err := p.Project(project) | |
196 if err != nil { | |
197 return typeMismatchReason(p.value, v) | |
198 } | |
199 if overflow != nil && overflow(pVal) { | |
200 return fmt.Sprintf("value %v overflows struct field of t ype %v", pVal, v.Type()) | |
201 } | |
202 set(pVal) | |
225 } | 203 } |
226 if slice.IsValid() { | 204 if slice.IsValid() { |
227 slice.Set(reflect.Append(slice, v)) | 205 slice.Set(reflect.Append(slice, v)) |
228 } | 206 } |
229 return "" | 207 return "" |
230 } | 208 } |
231 | 209 |
232 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { | 210 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { |
233 size := len(p.c.byName) | 211 size := len(p.c.byName) |
234 if withMeta { | 212 if withMeta { |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
595 switch val { | 573 switch val { |
596 case "on", "On", "true": | 574 case "on", "On", "true": |
597 return true, nil | 575 return true, nil |
598 case "off", "Off", "false": | 576 case "off", "Off", "false": |
599 return false, nil | 577 return false, nil |
600 } | 578 } |
601 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) | 579 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) |
602 } | 580 } |
603 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) | 581 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) |
604 } | 582 } |
OLD | NEW |