Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(847)

Side by Side Diff: service/datastore/pls_impl.go

Issue 1516173002: Fix error message from KeyForObj when passing an invalid struct. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: remove accidental extra test Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 var _ PropertyLoadSaver = (*structPLS)(nil) 46 var _ PropertyLoadSaver = (*structPLS)(nil)
47 47
48 // typeMismatchReason returns a string explaining why the property p could not 48 // typeMismatchReason returns a string explaining why the property p could not
49 // be stored in an entity field of type v.Type(). 49 // be stored in an entity field of type v.Type().
50 func typeMismatchReason(val interface{}, v reflect.Value) string { 50 func typeMismatchReason(val interface{}, v reflect.Value) string {
51 entityType := reflect.TypeOf(val) 51 entityType := reflect.TypeOf(val)
52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) 52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
53 } 53 }
54 54
55 func (p *structPLS) Load(propMap PropertyMap) error { 55 func (p *structPLS) Load(propMap PropertyMap) error {
56 if err := p.Problem(); err != nil {
57 return err
58 }
59
60 convFailures := errors.MultiError(nil) 56 convFailures := errors.MultiError(nil)
61 57
62 t := reflect.Type(nil) 58 t := reflect.Type(nil)
63 for name, props := range propMap { 59 for name, props := range propMap {
64 multiple := len(props) > 1 60 multiple := len(props) > 1
65 for i, prop := range props { 61 for i, prop := range props {
66 if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" { 62 if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" {
67 if t == nil { 63 if t == nil {
68 t = p.o.Type() 64 t = p.o.Type()
69 } 65 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 } 194 }
199 set(pVal) 195 set(pVal)
200 } 196 }
201 if slice.IsValid() { 197 if slice.IsValid() {
202 slice.Set(reflect.Append(slice, v)) 198 slice.Set(reflect.Append(slice, v))
203 } 199 }
204 return "" 200 return ""
205 } 201 }
206 202
207 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { 203 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) {
208 if err := p.Problem(); err != nil {
209 return nil, err
210 }
211
212 ret := PropertyMap(nil) 204 ret := PropertyMap(nil)
213 if withMeta { 205 if withMeta {
214 ret = getMGS(p.o.Addr().Interface()).GetAllMeta() 206 ret = getMGS(p.o.Addr().Interface()).GetAllMeta()
215 } else { 207 } else {
216 ret = make(PropertyMap, len(p.c.byName)) 208 ret = make(PropertyMap, len(p.c.byName))
217 } 209 }
218 if _, err := p.save(ret, "", ShouldIndex); err != nil { 210 if _, err := p.save(ret, "", ShouldIndex); err != nil {
219 return nil, err 211 return nil, err
220 } 212 }
221 return ret, nil 213 return ret, nil
222 } 214 }
223 215
224 func (p *structPLS) getDefaultKind() string { 216 func (p *structPLS) getDefaultKind() string {
225 if !p.o.IsValid() { 217 if !p.o.IsValid() {
226 return "" 218 return ""
227 } 219 }
228 return p.o.Type().Name() 220 return p.o.Type().Name()
229 } 221 }
230 222
231 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) { 223 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) {
232 if err = p.Problem(); err != nil {
233 return
234 }
235
236 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) { 224 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) {
237 if st.substructCodec != nil { 225 if st.substructCodec != nil {
238 count, err := (&structPLS{v, st.substructCodec}).save(pr opMap, name, si) 226 count, err := (&structPLS{v, st.substructCodec}).save(pr opMap, name, si)
239 if err == nil { 227 if err == nil {
240 idxCount += count 228 idxCount += count
241 if idxCount > maxIndexedProperties { 229 if idxCount > maxIndexedProperties {
242 err = errors.New("gae: too many indexed properties") 230 err = errors.New("gae: too many indexed properties")
243 } 231 }
244 } 232 }
245 return err 233 return err
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 } 273 }
286 } else { 274 } else {
287 if err = saveProp(name, is1, v, &st); err != nil { 275 if err = saveProp(name, is1, v, &st); err != nil {
288 return 276 return
289 } 277 }
290 } 278 }
291 } 279 }
292 return 280 return
293 } 281 }
294 282
295 func (p *structPLS) GetMeta(key string) (interface{}, error) { 283 func (p *structPLS) GetMeta(key string) (interface{}, bool) {
296 » if err := p.Problem(); err != nil {
297 » » return nil, err
298 » }
299
300 if idx, ok := p.c.byMeta[key]; ok { 284 if idx, ok := p.c.byMeta[key]; ok {
301 if val, ok := p.getMetaFor(idx); ok { 285 if val, ok := p.getMetaFor(idx); ok {
302 » » » return val, nil 286 » » » return val, true
303 } 287 }
304 } else if key == "kind" { 288 } else if key == "kind" {
305 » » return p.getDefaultKind(), nil 289 » » return p.getDefaultKind(), true
306 } 290 }
307 » return nil, ErrMetaFieldUnset 291 » return nil, false
308 } 292 }
309 293
310 func (p *structPLS) getMetaFor(idx int) (interface{}, bool) { 294 func (p *structPLS) getMetaFor(idx int) (interface{}, bool) {
311 st := p.c.byIndex[idx] 295 st := p.c.byIndex[idx]
312 val := st.metaVal 296 val := st.metaVal
313 if st.canSet { 297 if st.canSet {
314 f := p.o.Field(idx) 298 f := p.o.Field(idx)
315 if st.convert { 299 if st.convert {
316 prop, err := f.Addr().Interface().(PropertyConverter).To Property() 300 prop, err := f.Addr().Interface().(PropertyConverter).To Property()
317 if err != nil { 301 if err != nil {
(...skipping 27 matching lines...) Expand all
345 } 329 }
346 } 330 }
347 if needKind { 331 if needKind {
348 if _, ok := p.c.byMeta["kind"]; !ok { 332 if _, ok := p.c.byMeta["kind"]; !ok {
349 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))} 333 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))}
350 } 334 }
351 } 335 }
352 return ret 336 return ret
353 } 337 }
354 338
355 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { 339 func (p *structPLS) SetMeta(key string, val interface{}) bool {
356 » return GetMetaDefaultImpl(p.GetMeta, key, def)
357 }
358
359 func (p *structPLS) SetMeta(key string, val interface{}) (err error) {
360 » if err = p.Problem(); err != nil {
361 » » return
362 » }
363 idx, ok := p.c.byMeta[key] 340 idx, ok := p.c.byMeta[key]
364 if !ok { 341 if !ok {
365 » » return ErrMetaFieldUnset 342 » » return false
366 } 343 }
367 st := p.c.byIndex[idx] 344 st := p.c.byIndex[idx]
368 if !st.canSet { 345 if !st.canSet {
369 » » return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 346 » » return false
370 } 347 }
371 if st.convert { 348 if st.convert {
372 » » return p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro mProperty( 349 » » err := p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro mProperty(
373 MkPropertyNI(val)) 350 MkPropertyNI(val))
351 return err == nil
374 } 352 }
375 353
376 // setting a BoolField 354 // setting a BoolField
377 if b, ok := val.(bool); ok { 355 if b, ok := val.(bool); ok {
378 if b { 356 if b {
379 val = On 357 val = On
380 } else { 358 } else {
381 val = Off 359 val = Off
382 } 360 }
383 } 361 }
384 f := p.o.Field(idx) 362 f := p.o.Field(idx)
385 if val == nil { 363 if val == nil {
386 f.Set(reflect.Zero(f.Type())) 364 f.Set(reflect.Zero(f.Type()))
387 } else { 365 } else {
388 value := reflect.ValueOf(val) 366 value := reflect.ValueOf(val)
389 f.Set(value.Convert(f.Type())) 367 f.Set(value.Convert(f.Type()))
390 } 368 }
391 » return nil 369 » return true
392 } 370 }
393 371
394 func (p *structPLS) Problem() error { return p.c.problem }
395
396 var ( 372 var (
397 // The RWMutex is chosen intentionally, as the majority of access to the 373 // The RWMutex is chosen intentionally, as the majority of access to the
398 // structCodecs map will be in parallel and will be to read an existing codec. 374 // structCodecs map will be in parallel and will be to read an existing codec.
399 // There's no reason to serialize goroutines on every 375 // There's no reason to serialize goroutines on every
400 // gae.Interface.{Get,Put}{,Multi} call. 376 // gae.Interface.{Get,Put}{,Multi} call.
401 structCodecsMutex sync.RWMutex 377 structCodecsMutex sync.RWMutex
402 structCodecs = map[reflect.Type]*structCodec{} 378 structCodecs = map[reflect.Type]*structCodec{}
403 ) 379 )
404 380
405 // validPropertyName returns whether name consists of one or more valid Go 381 // validPropertyName returns whether name consists of one or more valid Go
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 } 415 }
440 416
441 me := func(fmtStr string, args ...interface{}) error { 417 me := func(fmtStr string, args ...interface{}) error {
442 return fmt.Errorf(fmtStr, args...) 418 return fmt.Errorf(fmtStr, args...)
443 } 419 }
444 420
445 c = &structCodec{ 421 c = &structCodec{
446 byIndex: make([]structTag, t.NumField()), 422 byIndex: make([]structTag, t.NumField()),
447 byName: make(map[string]int, t.NumField()), 423 byName: make(map[string]int, t.NumField()),
448 byMeta: make(map[string]int, t.NumField()), 424 byMeta: make(map[string]int, t.NumField()),
425
449 problem: errRecursiveStruct, // we'll clear this later if it's n ot recursive 426 problem: errRecursiveStruct, // we'll clear this later if it's n ot recursive
450 } 427 }
451 defer func() { 428 defer func() {
452 // If the codec has a problem, free up the indexes 429 // If the codec has a problem, free up the indexes
453 if c.problem != nil { 430 if c.problem != nil {
454 c.byIndex = nil 431 c.byIndex = nil
455 c.byName = nil 432 c.byName = nil
456 c.byMeta = nil 433 c.byMeta = nil
457 } 434 }
458 }() 435 }()
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 switch val { 583 switch val {
607 case "on", "On", "true": 584 case "on", "On", "true":
608 return true, nil 585 return true, nil
609 case "off", "Off", "false": 586 case "off", "Off", "false":
610 return false, nil 587 return false, nil
611 } 588 }
612 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 589 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
613 } 590 }
614 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 591 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
615 } 592 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698