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

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

Issue 1414043006: Allow metadata fields to be PropertyConverters for symmetry. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix nits Created 5 years, 1 month 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
« no previous file with comments | « service/datastore/pls.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
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{}, error) {
296 if err := p.Problem(); err != nil { 296 if err := p.Problem(); err != nil {
297 return nil, err 297 return nil, err
298 } 298 }
299 299
300 if idx, ok := p.c.byMeta[key]; ok { 300 if idx, ok := p.c.byMeta[key]; ok {
301 » » return p.getMetaFor(idx), nil 301 » » if val, ok := p.getMetaFor(idx); ok {
302 » } 302 » » » return val, nil
303 303 » » }
304 » if key == "kind" { 304 » } else if key == "kind" {
305 return p.getDefaultKind(), nil 305 return p.getDefaultKind(), nil
306 } 306 }
307 return nil, ErrMetaFieldUnset 307 return nil, ErrMetaFieldUnset
308 } 308 }
309 309
310 func (p *structPLS) getMetaFor(idx int) interface{} { 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 f := p.o.Field(idx)
314 if st.canSet { 313 if st.canSet {
314 f := p.o.Field(idx)
315 if st.convert {
316 prop, err := f.Addr().Interface().(PropertyConverter).To Property()
317 if err != nil {
318 return nil, false
319 }
320 return prop.value, true
321 }
322
315 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) { 323 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) {
316 val = f.Interface() 324 val = f.Interface()
317 if bf, ok := val.(Toggle); ok { 325 if bf, ok := val.(Toggle); ok {
318 val = bf == On // true if On, otherwise false 326 val = bf == On // true if On, otherwise false
319 } 327 }
320 } 328 }
321 } 329 }
322 » return val 330 » return val, true
323 } 331 }
324 332
325 func (p *structPLS) GetAllMeta() PropertyMap { 333 func (p *structPLS) GetAllMeta() PropertyMap {
326 needKind := true 334 needKind := true
327 ret := make(PropertyMap, len(p.c.byMeta)+1) 335 ret := make(PropertyMap, len(p.c.byMeta)+1)
328 for k, idx := range p.c.byMeta { 336 for k, idx := range p.c.byMeta {
329 » » val := p.getMetaFor(idx) 337 » » if val, ok := p.getMetaFor(idx); ok {
330 » » p := Property{} 338 » » » p := Property{}
331 » » if err := p.SetValue(val, NoIndex); err != nil { 339 » » » if err := p.SetValue(val, NoIndex); err != nil {
332 » » » continue 340 » » » » continue
341 » » » }
342 » » » ret["$"+k] = []Property{p}
333 } 343 }
334 ret["$"+k] = []Property{p}
335 } 344 }
336 if needKind { 345 if needKind {
337 if _, ok := p.c.byMeta["kind"]; !ok { 346 if _, ok := p.c.byMeta["kind"]; !ok {
338 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))} 347 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))}
339 } 348 }
340 } 349 }
341 return ret 350 return ret
342 } 351 }
343 352
344 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { 353 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} {
345 return GetMetaDefaultImpl(p.GetMeta, key, def) 354 return GetMetaDefaultImpl(p.GetMeta, key, def)
346 } 355 }
347 356
348 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { 357 func (p *structPLS) SetMeta(key string, val interface{}) (err error) {
349 if err = p.Problem(); err != nil { 358 if err = p.Problem(); err != nil {
350 return 359 return
351 } 360 }
352 idx, ok := p.c.byMeta[key] 361 idx, ok := p.c.byMeta[key]
353 if !ok { 362 if !ok {
354 return ErrMetaFieldUnset 363 return ErrMetaFieldUnset
355 } 364 }
356 » if !p.c.byIndex[idx].canSet { 365 » st := p.c.byIndex[idx]
366 » if !st.canSet {
357 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 367 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key)
358 } 368 }
369 if st.convert {
370 return p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro mProperty(
371 MkPropertyNI(val))
372 }
373
359 // setting a BoolField 374 // setting a BoolField
360 if b, ok := val.(bool); ok { 375 if b, ok := val.(bool); ok {
361 if b { 376 if b {
362 val = On 377 val = On
363 } else { 378 } else {
364 val = Off 379 val = Off
365 } 380 }
366 } 381 }
367 f := p.o.Field(idx) 382 f := p.o.Field(idx)
368 if val == nil { 383 if val == nil {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 c.byIndex = nil 451 c.byIndex = nil
437 c.byName = nil 452 c.byName = nil
438 c.byMeta = nil 453 c.byMeta = nil
439 } 454 }
440 }() 455 }()
441 structCodecs[t] = c 456 structCodecs[t] = c
442 457
443 for i := range c.byIndex { 458 for i := range c.byIndex {
444 st := &c.byIndex[i] 459 st := &c.byIndex[i]
445 f := t.Field(i) 460 f := t.Field(i)
461 ft := f.Type
462
446 name := f.Tag.Get("gae") 463 name := f.Tag.Get("gae")
447 opts := "" 464 opts := ""
448 if i := strings.Index(name, ","); i != -1 { 465 if i := strings.Index(name, ","); i != -1 {
449 name, opts = name[:i], name[i+1:] 466 name, opts = name[:i], name[i+1:]
450 } 467 }
451 st.canSet = f.PkgPath == "" // blank == exported 468 st.canSet = f.PkgPath == "" // blank == exported
469 st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverte r)
452 switch { 470 switch {
453 case name == "": 471 case name == "":
454 if !f.Anonymous { 472 if !f.Anonymous {
455 name = f.Name 473 name = f.Name
456 } 474 }
457 case name[0] == '$': 475 case name[0] == '$':
458 name = name[1:] 476 name = name[1:]
459 if _, ok := c.byMeta[name]; ok { 477 if _, ok := c.byMeta[name]; ok {
460 c.problem = me("meta field %q set multiple times ", "$"+name) 478 c.problem = me("meta field %q set multiple times ", "$"+name)
461 return 479 return
462 } 480 }
463 c.byMeta[name] = i 481 c.byMeta[name] = i
464 » » » mv, err := convertMeta(opts, f.Type) 482 » » » if !st.convert {
465 » » » if err != nil { 483 » » » » mv, err := convertMeta(opts, ft)
466 » » » » c.problem = me("meta field %q has bad type: %s", "$"+name, err) 484 » » » » if err != nil {
467 » » » » return 485 » » » » » c.problem = me("meta field %q has bad ty pe: %s", "$"+name, err)
486 » » » » » return
487 » » » » }
488 » » » » st.metaVal = mv
468 } 489 }
469 st.metaVal = mv
470 fallthrough 490 fallthrough
471 case name == "-": 491 case name == "-":
472 st.name = "-" 492 st.name = "-"
473 continue 493 continue
474 default: 494 default:
475 if !validPropertyName(name) { 495 if !validPropertyName(name) {
476 c.problem = me("struct tag has invalid property name: %q", name) 496 c.problem = me("struct tag has invalid property name: %q", name)
477 return 497 return
478 } 498 }
479 } 499 }
480 if !st.canSet { 500 if !st.canSet {
481 st.name = "-" 501 st.name = "-"
482 continue 502 continue
483 } 503 }
484 504
485 substructType := reflect.Type(nil) 505 substructType := reflect.Type(nil)
486 » » ft := f.Type 506 » » if !st.convert {
487 » » if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { 507 » » » switch ft.Kind() {
488 » » » st.convert = true
489 » » } else {
490 » » » switch f.Type.Kind() {
491 case reflect.Struct: 508 case reflect.Struct:
492 if ft != typeOfTime && ft != typeOfGeoPoint { 509 if ft != typeOfTime && ft != typeOfGeoPoint {
493 substructType = ft 510 substructType = ft
494 } 511 }
495 case reflect.Slice: 512 case reflect.Slice:
496 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) { 513 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) {
497 st.convert = true 514 st.convert = true
498 } else if ft.Elem().Kind() == reflect.Struct { 515 } else if ft.Elem().Kind() == reflect.Struct {
499 substructType = ft.Elem() 516 substructType = ft.Elem()
500 } 517 }
501 st.isSlice = ft.Elem().Kind() != reflect.Uint8 518 st.isSlice = ft.Elem().Kind() != reflect.Uint8
502 c.hasSlice = c.hasSlice || st.isSlice 519 c.hasSlice = c.hasSlice || st.isSlice
503 case reflect.Interface: 520 case reflect.Interface:
504 c.problem = me("field %q has non-concrete interf ace type %s", 521 c.problem = me("field %q has non-concrete interf ace type %s",
505 » » » » » f.Name, f.Type) 522 » » » » » f.Name, ft)
506 return 523 return
507 } 524 }
508 } 525 }
509 526
510 if substructType != nil { 527 if substructType != nil {
511 sub := getStructCodecLocked(substructType) 528 sub := getStructCodecLocked(substructType)
512 if sub.problem != nil { 529 if sub.problem != nil {
513 if sub.problem == errRecursiveStruct { 530 if sub.problem == errRecursiveStruct {
514 c.problem = me("field %q is recursively defined", f.Name) 531 c.problem = me("field %q is recursively defined", f.Name)
515 } else { 532 } else {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 switch val { 601 switch val {
585 case "on", "On", "true": 602 case "on", "On", "true":
586 return true, nil 603 return true, nil
587 case "off", "Off", "false": 604 case "off", "Off", "false":
588 return false, nil 605 return false, nil
589 } 606 }
590 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 607 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
591 } 608 }
592 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 609 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
593 } 610 }
OLDNEW
« no previous file with comments | « service/datastore/pls.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698