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

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
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 » » return p.getMetaFor(idx)
302 } 302 }
303 303
304 if key == "kind" { 304 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{}, error) {
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, err
319 }
320 return prop.value, err
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, nil
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 » » val, err := p.getMetaFor(idx)
330 » » p := Property{} 338 » » if err == nil {
331 » » if err := p.SetValue(val, NoIndex); err != nil { 339 » » » p := Property{}
332 » » » continue 340 » » » if err := p.SetValue(val, NoIndex); err != nil {
341 » » » » continue
342 » » » }
343 » » » ret["$"+k] = []Property{p}
333 } 344 }
334 ret["$"+k] = []Property{p}
335 } 345 }
336 if needKind { 346 if needKind {
337 if _, ok := p.c.byMeta["kind"]; !ok { 347 if _, ok := p.c.byMeta["kind"]; !ok {
338 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))} 348 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))}
339 } 349 }
340 } 350 }
341 return ret 351 return ret
342 } 352 }
343 353
344 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { 354 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} {
345 return GetMetaDefaultImpl(p.GetMeta, key, def) 355 return GetMetaDefaultImpl(p.GetMeta, key, def)
346 } 356 }
347 357
348 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { 358 func (p *structPLS) SetMeta(key string, val interface{}) (err error) {
349 if err = p.Problem(); err != nil { 359 if err = p.Problem(); err != nil {
350 return 360 return
351 } 361 }
352 idx, ok := p.c.byMeta[key] 362 idx, ok := p.c.byMeta[key]
353 if !ok { 363 if !ok {
354 return ErrMetaFieldUnset 364 return ErrMetaFieldUnset
355 } 365 }
356 » if !p.c.byIndex[idx].canSet { 366 » st := p.c.byIndex[idx]
367 » if !st.canSet {
357 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 368 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key)
358 } 369 }
370 if st.convert {
371 return p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro mProperty(
372 MkPropertyNI(val))
373 }
374
359 // setting a BoolField 375 // setting a BoolField
360 if b, ok := val.(bool); ok { 376 if b, ok := val.(bool); ok {
361 if b { 377 if b {
362 val = On 378 val = On
363 } else { 379 } else {
364 val = Off 380 val = Off
365 } 381 }
366 } 382 }
367 f := p.o.Field(idx) 383 f := p.o.Field(idx)
368 if val == nil { 384 if val == nil {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 c.byIndex = nil 452 c.byIndex = nil
437 c.byName = nil 453 c.byName = nil
438 c.byMeta = nil 454 c.byMeta = nil
439 } 455 }
440 }() 456 }()
441 structCodecs[t] = c 457 structCodecs[t] = c
442 458
443 for i := range c.byIndex { 459 for i := range c.byIndex {
444 st := &c.byIndex[i] 460 st := &c.byIndex[i]
445 f := t.Field(i) 461 f := t.Field(i)
462 ft := f.Type
463
446 name := f.Tag.Get("gae") 464 name := f.Tag.Get("gae")
447 opts := "" 465 opts := ""
448 if i := strings.Index(name, ","); i != -1 { 466 if i := strings.Index(name, ","); i != -1 {
449 name, opts = name[:i], name[i+1:] 467 name, opts = name[:i], name[i+1:]
450 } 468 }
451 st.canSet = f.PkgPath == "" // blank == exported 469 st.canSet = f.PkgPath == "" // blank == exported
470 st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverte r)
452 switch { 471 switch {
453 case name == "": 472 case name == "":
454 if !f.Anonymous { 473 if !f.Anonymous {
455 name = f.Name 474 name = f.Name
456 } 475 }
457 case name[0] == '$': 476 case name[0] == '$':
458 name = name[1:] 477 name = name[1:]
459 if _, ok := c.byMeta[name]; ok { 478 if _, ok := c.byMeta[name]; ok {
460 c.problem = me("meta field %q set multiple times ", "$"+name) 479 c.problem = me("meta field %q set multiple times ", "$"+name)
461 return 480 return
462 } 481 }
463 c.byMeta[name] = i 482 c.byMeta[name] = i
464 » » » mv, err := convertMeta(opts, f.Type) 483 » » » if !st.convert {
465 » » » if err != nil { 484 » » » » mv, err := convertMeta(opts, ft)
466 » » » » c.problem = me("meta field %q has bad type: %s", "$"+name, err) 485 » » » » if err != nil {
467 » » » » return 486 » » » » » c.problem = me("meta field %q has bad ty pe: %s", "$"+name, err)
487 » » » » » return
488 » » » » }
489 » » » » st.metaVal = mv
468 } 490 }
469 st.metaVal = mv
470 fallthrough 491 fallthrough
471 case name == "-": 492 case name == "-":
472 st.name = "-" 493 st.name = "-"
473 continue 494 continue
474 default: 495 default:
475 if !validPropertyName(name) { 496 if !validPropertyName(name) {
476 c.problem = me("struct tag has invalid property name: %q", name) 497 c.problem = me("struct tag has invalid property name: %q", name)
477 return 498 return
478 } 499 }
479 } 500 }
480 if !st.canSet { 501 if !st.canSet {
481 st.name = "-" 502 st.name = "-"
482 continue 503 continue
483 } 504 }
484 505
485 substructType := reflect.Type(nil) 506 substructType := reflect.Type(nil)
486 » » ft := f.Type 507 » » if !st.convert {
487 » » if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { 508 » » » switch ft.Kind() {
488 » » » st.convert = true
489 » » } else {
490 » » » switch f.Type.Kind() {
491 case reflect.Struct: 509 case reflect.Struct:
492 if ft != typeOfTime && ft != typeOfGeoPoint { 510 if ft != typeOfTime && ft != typeOfGeoPoint {
493 substructType = ft 511 substructType = ft
494 } 512 }
495 case reflect.Slice: 513 case reflect.Slice:
496 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) { 514 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) {
497 st.convert = true 515 st.convert = true
498 } else if ft.Elem().Kind() == reflect.Struct { 516 } else if ft.Elem().Kind() == reflect.Struct {
499 substructType = ft.Elem() 517 substructType = ft.Elem()
500 } 518 }
501 st.isSlice = ft.Elem().Kind() != reflect.Uint8 519 st.isSlice = ft.Elem().Kind() != reflect.Uint8
502 c.hasSlice = c.hasSlice || st.isSlice 520 c.hasSlice = c.hasSlice || st.isSlice
503 case reflect.Interface: 521 case reflect.Interface:
504 c.problem = me("field %q has non-concrete interf ace type %s", 522 c.problem = me("field %q has non-concrete interf ace type %s",
505 » » » » » f.Name, f.Type) 523 » » » » » f.Name, ft)
506 return 524 return
507 } 525 }
508 } 526 }
509 527
510 if substructType != nil { 528 if substructType != nil {
511 sub := getStructCodecLocked(substructType) 529 sub := getStructCodecLocked(substructType)
512 if sub.problem != nil { 530 if sub.problem != nil {
513 if sub.problem == errRecursiveStruct { 531 if sub.problem == errRecursiveStruct {
514 c.problem = me("field %q is recursively defined", f.Name) 532 c.problem = me("field %q is recursively defined", f.Name)
515 } else { 533 } else {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 switch val { 602 switch val {
585 case "on", "On", "true": 603 case "on", "On", "true":
586 return true, nil 604 return true, nil
587 case "off", "Off", "false": 605 case "off", "Off", "false":
588 return false, nil 606 return false, nil
589 } 607 }
590 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)
591 } 609 }
592 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)
593 } 611 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698