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

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: more simplification 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 { 56 » if p.c.problem != nil {
57 » » return err 57 » » panic(p.c.problem)
58 } 58 }
59 59
60 convFailures := errors.MultiError(nil) 60 convFailures := errors.MultiError(nil)
61 61
62 t := reflect.Type(nil) 62 t := reflect.Type(nil)
63 for name, props := range propMap { 63 for name, props := range propMap {
64 multiple := len(props) > 1 64 multiple := len(props) > 1
65 for i, prop := range props { 65 for i, prop := range props {
66 if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" { 66 if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" {
67 if t == nil { 67 if t == nil {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 } 198 }
199 set(pVal) 199 set(pVal)
200 } 200 }
201 if slice.IsValid() { 201 if slice.IsValid() {
202 slice.Set(reflect.Append(slice, v)) 202 slice.Set(reflect.Append(slice, v))
203 } 203 }
204 return "" 204 return ""
205 } 205 }
206 206
207 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { 207 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) {
208 » if err := p.Problem(); err != nil { 208 » if p.c.problem != nil {
209 » » return nil, err 209 » » panic(p.c.problem)
210 } 210 }
211 211
212 ret := PropertyMap(nil) 212 ret := PropertyMap(nil)
213 if withMeta { 213 if withMeta {
214 ret = getMGS(p.o.Addr().Interface()).GetAllMeta() 214 ret = getMGS(p.o.Addr().Interface()).GetAllMeta()
215 } else { 215 } else {
216 ret = make(PropertyMap, len(p.c.byName)) 216 ret = make(PropertyMap, len(p.c.byName))
217 } 217 }
218 if _, err := p.save(ret, "", ShouldIndex); err != nil { 218 if _, err := p.save(ret, "", ShouldIndex); err != nil {
219 return nil, err 219 return nil, err
220 } 220 }
221 return ret, nil 221 return ret, nil
222 } 222 }
223 223
224 func (p *structPLS) getDefaultKind() string { 224 func (p *structPLS) getDefaultKind() string {
225 if !p.o.IsValid() { 225 if !p.o.IsValid() {
226 return "" 226 return ""
227 } 227 }
228 return p.o.Type().Name() 228 return p.o.Type().Name()
229 } 229 }
230 230
231 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) { 231 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) {
232 » if err = p.Problem(); err != nil { 232 » if p.c.problem != nil {
233 » » return 233 » » panic(p.c.problem)
234 } 234 }
235 235
236 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) { 236 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) {
237 if st.substructCodec != nil { 237 if st.substructCodec != nil {
238 count, err := (&structPLS{v, st.substructCodec}).save(pr opMap, name, si) 238 count, err := (&structPLS{v, st.substructCodec}).save(pr opMap, name, si)
239 if err == nil { 239 if err == nil {
240 idxCount += count 240 idxCount += count
241 if idxCount > maxIndexedProperties { 241 if idxCount > maxIndexedProperties {
242 err = errors.New("gae: too many indexed properties") 242 err = errors.New("gae: too many indexed properties")
243 } 243 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 } 285 }
286 } else { 286 } else {
287 if err = saveProp(name, is1, v, &st); err != nil { 287 if err = saveProp(name, is1, v, &st); err != nil {
288 return 288 return
289 } 289 }
290 } 290 }
291 } 291 }
292 return 292 return
293 } 293 }
294 294
295 func (p *structPLS) GetMeta(key string) (interface{}, error) { 295 func (p *structPLS) GetMeta(key string) (interface{}, bool) {
296 » if err := p.Problem(); err != nil { 296 » if p.c.problem != nil {
297 » » return nil, err 297 » » panic(p.c.problem)
298 } 298 }
299 299
300 if idx, ok := p.c.byMeta[key]; ok { 300 if idx, ok := p.c.byMeta[key]; ok {
301 if val, ok := p.getMetaFor(idx); ok { 301 if val, ok := p.getMetaFor(idx); ok {
302 » » » return val, nil 302 » » » return val, true
303 } 303 }
304 } else if key == "kind" { 304 } else if key == "kind" {
305 » » return p.getDefaultKind(), nil 305 » » return p.getDefaultKind(), true
306 } 306 }
307 » return nil, ErrMetaFieldUnset 307 » return nil, false
308 } 308 }
309 309
310 func (p *structPLS) getMetaFor(idx int) (interface{}, bool) { 310 func (p *structPLS) getMetaFor(idx int) (interface{}, bool) {
311 st := p.c.byIndex[idx] 311 st := p.c.byIndex[idx]
312 val := st.metaVal 312 val := st.metaVal
313 if st.canSet { 313 if st.canSet {
314 f := p.o.Field(idx) 314 f := p.o.Field(idx)
315 if st.convert { 315 if st.convert {
316 prop, err := f.Addr().Interface().(PropertyConverter).To Property() 316 prop, err := f.Addr().Interface().(PropertyConverter).To Property()
317 if err != nil { 317 if err != nil {
(...skipping 27 matching lines...) Expand all
345 } 345 }
346 } 346 }
347 if needKind { 347 if needKind {
348 if _, ok := p.c.byMeta["kind"]; !ok { 348 if _, ok := p.c.byMeta["kind"]; !ok {
349 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))} 349 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))}
350 } 350 }
351 } 351 }
352 return ret 352 return ret
353 } 353 }
354 354
355 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { 355 func (p *structPLS) SetMeta(key string, val interface{}) bool {
356 » return GetMetaDefaultImpl(p.GetMeta, key, def) 356 » if p.c.problem != nil {
357 } 357 » » panic(p.c.problem)
358 » }
358 359
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] 360 idx, ok := p.c.byMeta[key]
364 if !ok { 361 if !ok {
365 » » return ErrMetaFieldUnset 362 » » return false
366 } 363 }
367 st := p.c.byIndex[idx] 364 st := p.c.byIndex[idx]
368 if !st.canSet { 365 if !st.canSet {
369 » » return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 366 » » return false
370 } 367 }
371 if st.convert { 368 if st.convert {
372 » » return p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro mProperty( 369 » » err := p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro mProperty(
373 MkPropertyNI(val)) 370 MkPropertyNI(val))
371 return err == nil
374 } 372 }
375 373
376 // setting a BoolField 374 // setting a BoolField
377 if b, ok := val.(bool); ok { 375 if b, ok := val.(bool); ok {
378 if b { 376 if b {
379 val = On 377 val = On
380 } else { 378 } else {
381 val = Off 379 val = Off
382 } 380 }
383 } 381 }
384 f := p.o.Field(idx) 382 f := p.o.Field(idx)
385 if val == nil { 383 if val == nil {
386 f.Set(reflect.Zero(f.Type())) 384 f.Set(reflect.Zero(f.Type()))
387 } else { 385 } else {
388 value := reflect.ValueOf(val) 386 value := reflect.ValueOf(val)
389 f.Set(value.Convert(f.Type())) 387 f.Set(value.Convert(f.Type()))
390 } 388 }
391 » return nil 389 » return true
392 } 390 }
393 391
394 func (p *structPLS) Problem() error { return p.c.problem }
395
396 var ( 392 var (
397 // The RWMutex is chosen intentionally, as the majority of access to the 393 // 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. 394 // structCodecs map will be in parallel and will be to read an existing codec.
399 // There's no reason to serialize goroutines on every 395 // There's no reason to serialize goroutines on every
400 // gae.Interface.{Get,Put}{,Multi} call. 396 // gae.Interface.{Get,Put}{,Multi} call.
401 structCodecsMutex sync.RWMutex 397 structCodecsMutex sync.RWMutex
402 structCodecs = map[reflect.Type]*structCodec{} 398 structCodecs = map[reflect.Type]*structCodec{}
403 ) 399 )
404 400
405 // validPropertyName returns whether name consists of one or more valid Go 401 // validPropertyName returns whether name consists of one or more valid Go
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverte r) 468 st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverte r)
473 switch { 469 switch {
474 case name == "": 470 case name == "":
475 if !f.Anonymous { 471 if !f.Anonymous {
476 name = f.Name 472 name = f.Name
477 } 473 }
478 case name[0] == '$': 474 case name[0] == '$':
479 name = name[1:] 475 name = name[1:]
480 if _, ok := c.byMeta[name]; ok { 476 if _, ok := c.byMeta[name]; ok {
481 c.problem = me("meta field %q set multiple times ", "$"+name) 477 c.problem = me("meta field %q set multiple times ", "$"+name)
482 return 478 return
dnj 2015/12/12 02:47:50 I think you should panic when the problem is ident
iannucci 2015/12/12 03:52:22 Ok, now we panic harder (in getCodec).
483 } 479 }
484 c.byMeta[name] = i 480 c.byMeta[name] = i
485 if !st.convert { 481 if !st.convert {
486 mv, err := convertMeta(opts, ft) 482 mv, err := convertMeta(opts, ft)
487 if err != nil { 483 if err != nil {
488 c.problem = me("meta field %q has bad ty pe: %s", "$"+name, err) 484 c.problem = me("meta field %q has bad ty pe: %s", "$"+name, err)
489 return 485 return
490 } 486 }
491 st.metaVal = mv 487 st.metaVal = mv
492 } 488 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 switch val { 602 switch val {
607 case "on", "On", "true": 603 case "on", "On", "true":
608 return true, nil 604 return true, nil
609 case "off", "Off", "false": 605 case "off", "Off", "false":
610 return false, nil 606 return false, nil
611 } 607 }
612 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 608 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
613 } 609 }
614 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 610 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
615 } 611 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698