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

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

Issue 1401533007: Add ability to override just the metadata in a struct. (Closed) Base URL: https://github.com/luci/gae.git@add_exists_method
Patch Set: Created 5 years, 2 months 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 17 matching lines...) Expand all
28 convert bool 28 convert bool
29 metaVal interface{} 29 metaVal interface{}
30 canSet bool 30 canSet bool
31 } 31 }
32 32
33 type structCodec struct { 33 type structCodec struct {
34 byMeta map[string]int 34 byMeta map[string]int
35 byName map[string]int 35 byName map[string]int
36 byIndex []structTag 36 byIndex []structTag
37 hasSlice bool 37 hasSlice bool
38 mgs bool
38 problem error 39 problem error
39 } 40 }
40 41
41 type structPLS struct { 42 type structPLS struct {
42 o reflect.Value 43 o reflect.Value
43 c *structCodec 44 c *structCodec
44 } 45 }
45 46
47 func (p *structPLS) getMGS() MetaGetterSetter {
Vadim Sh. 2015/10/13 04:27:48 :) https://goo.gl/ik3wWF
iannucci 2015/10/13 04:34:40 :)
48 if !p.c.mgs {
49 return nil
50 }
51 return p.o.Addr().Interface().(MetaGetterSetter)
52 }
53
46 var _ PropertyLoadSaver = (*structPLS)(nil) 54 var _ PropertyLoadSaver = (*structPLS)(nil)
47 55
48 // typeMismatchReason returns a string explaining why the property p could not 56 // typeMismatchReason returns a string explaining why the property p could not
49 // be stored in an entity field of type v.Type(). 57 // be stored in an entity field of type v.Type().
50 func typeMismatchReason(val interface{}, v reflect.Value) string { 58 func typeMismatchReason(val interface{}, v reflect.Value) string {
51 entityType := reflect.TypeOf(val) 59 entityType := reflect.TypeOf(val)
52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) 60 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
53 } 61 }
54 62
55 func (p *structPLS) Load(propMap PropertyMap) error { 63 func (p *structPLS) Load(propMap PropertyMap) error {
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 } 290 }
283 } 291 }
284 } 292 }
285 return 293 return
286 } 294 }
287 295
288 func (p *structPLS) GetMeta(key string) (interface{}, error) { 296 func (p *structPLS) GetMeta(key string) (interface{}, error) {
289 if err := p.Problem(); err != nil { 297 if err := p.Problem(); err != nil {
290 return nil, err 298 return nil, err
291 } 299 }
292 » idx, ok := p.c.byMeta[key] 300
293 » if !ok { 301 » if idx, ok := p.c.byMeta[key]; ok {
294 » » if key == "kind" { 302 » » return p.getMetaFor(idx), nil
295 » » » return p.getDefaultKind(), nil 303 » }
304
305 » if p.c.mgs {
306 » » ret, err := p.getMGS().GetMeta(key)
307 » » if err == nil {
308 » » » return ret, err
309 » » } else if err != ErrMetaFieldUnset {
310 » » » return nil, err
296 } 311 }
297 return nil, ErrMetaFieldUnset
298 } 312 }
299 » return p.getMetaFor(idx), nil 313 » if key == "kind" {
314 » » return p.getDefaultKind(), nil
315 » }
316 » return nil, ErrMetaFieldUnset
300 } 317 }
301 318
302 func (p *structPLS) getMetaFor(idx int) interface{} { 319 func (p *structPLS) getMetaFor(idx int) interface{} {
303 st := p.c.byIndex[idx] 320 st := p.c.byIndex[idx]
304 val := st.metaVal 321 val := st.metaVal
305 f := p.o.Field(idx) 322 f := p.o.Field(idx)
306 if st.canSet { 323 if st.canSet {
307 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) { 324 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) {
308 val = f.Interface() 325 val = f.Interface()
309 if bf, ok := val.(Toggle); ok { 326 if bf, ok := val.(Toggle); ok {
310 val = bf == On // true if On, otherwise false 327 val = bf == On // true if On, otherwise false
311 } 328 }
312 } 329 }
313 } 330 }
314 return val 331 return val
315 } 332 }
316 333
317 func (p *structPLS) GetAllMeta() PropertyMap { 334 func (p *structPLS) GetAllMeta() PropertyMap {
318 » ret := make(PropertyMap, len(p.c.byMeta)+1) 335 » ret := PropertyMap(nil)
336 » needKind := true
337 » if p.c.mgs {
338 » » ret = p.getMGS().GetAllMeta()
339 » » _, haveKind := ret["$kind"]
340 » » needKind = !haveKind
341 » } else {
342 » » ret = make(PropertyMap, len(p.c.byMeta)+1)
343 » }
319 for k, idx := range p.c.byMeta { 344 for k, idx := range p.c.byMeta {
320 val := p.getMetaFor(idx) 345 val := p.getMetaFor(idx)
321 p := Property{} 346 p := Property{}
322 if err := p.SetValue(val, NoIndex); err != nil { 347 if err := p.SetValue(val, NoIndex); err != nil {
323 continue 348 continue
324 } 349 }
325 ret["$"+k] = []Property{p} 350 ret["$"+k] = []Property{p}
326 } 351 }
327 » if _, ok := p.c.byMeta["kind"]; !ok { 352 » if needKind {
328 » » ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind())} 353 » » if _, ok := p.c.byMeta["kind"]; !ok {
354 » » » ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))}
355 » » }
329 } 356 }
330 return ret 357 return ret
331 } 358 }
332 359
333 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { 360 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} {
334 return GetMetaDefaultImpl(p.GetMeta, key, def) 361 return GetMetaDefaultImpl(p.GetMeta, key, def)
335 } 362 }
336 363
337 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { 364 func (p *structPLS) SetMeta(key string, val interface{}) (err error) {
338 if err = p.Problem(); err != nil { 365 if err = p.Problem(); err != nil {
339 return 366 return
340 } 367 }
341 idx, ok := p.c.byMeta[key] 368 idx, ok := p.c.byMeta[key]
342 if !ok { 369 if !ok {
370 if p.c.mgs {
371 return p.getMGS().SetMeta(key, val)
372 }
343 return ErrMetaFieldUnset 373 return ErrMetaFieldUnset
344 } 374 }
345 if !p.c.byIndex[idx].canSet { 375 if !p.c.byIndex[idx].canSet {
346 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 376 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key)
347 } 377 }
348 // setting a BoolField 378 // setting a BoolField
349 if b, ok := val.(bool); ok { 379 if b, ok := val.(bool); ok {
350 if b { 380 if b {
351 val = On 381 val = On
352 } else { 382 } else {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 441
412 me := func(fmtStr string, args ...interface{}) error { 442 me := func(fmtStr string, args ...interface{}) error {
413 return fmt.Errorf(fmtStr, args...) 443 return fmt.Errorf(fmtStr, args...)
414 } 444 }
415 445
416 c = &structCodec{ 446 c = &structCodec{
417 byIndex: make([]structTag, t.NumField()), 447 byIndex: make([]structTag, t.NumField()),
418 byName: make(map[string]int, t.NumField()), 448 byName: make(map[string]int, t.NumField()),
419 byMeta: make(map[string]int, t.NumField()), 449 byMeta: make(map[string]int, t.NumField()),
420 problem: errRecursiveStruct, // we'll clear this later if it's n ot recursive 450 problem: errRecursiveStruct, // we'll clear this later if it's n ot recursive
451 mgs: reflect.PtrTo(t).Implements(typeOfMGS),
421 } 452 }
422 defer func() { 453 defer func() {
423 // If the codec has a problem, free up the indexes 454 // If the codec has a problem, free up the indexes
424 if c.problem != nil { 455 if c.problem != nil {
425 c.byIndex = nil 456 c.byIndex = nil
426 c.byName = nil 457 c.byName = nil
427 c.byMeta = nil 458 c.byMeta = nil
428 } 459 }
429 }() 460 }()
430 structCodecs[t] = c 461 structCodecs[t] = c
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 switch val { 604 switch val {
574 case "on", "On", "true": 605 case "on", "On", "true":
575 return true, nil 606 return true, nil
576 case "off", "Off", "false": 607 case "off", "Off", "false":
577 return false, nil 608 return false, nil
578 } 609 }
579 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 610 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
580 } 611 }
581 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 612 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
582 } 613 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698