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

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

Issue 1279703003: Get rid of awkward proto argument to Interface.Run (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: In/Out return Type not interface{} Created 5 years, 4 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
« no previous file with comments | « service/datastore/checkfilter_test.go ('k') | service/datastore/datastore_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 package datastore 5 package datastore
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "reflect" 9 "reflect"
10 10
11 "github.com/luci/luci-go/common/errors" 11 "github.com/luci/luci-go/common/errors"
12 ) 12 )
13 13
14 type datastoreImpl struct{ RawInterface } 14 type datastoreImpl struct{ RawInterface }
15 15
16 var _ Interface = (*datastoreImpl)(nil) 16 var _ Interface = (*datastoreImpl)(nil)
17 17
18 func (d *datastoreImpl) KeyForObj(src interface{}) Key { 18 func (d *datastoreImpl) KeyForObj(src interface{}) Key {
19 ret, err := d.KeyForObjErr(src) 19 ret, err := d.KeyForObjErr(src)
20 if err != nil { 20 if err != nil {
21 panic(err) 21 panic(err)
22 } 22 }
23 return ret 23 return ret
24 } 24 }
25 25
26 func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) { 26 func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) {
27 return newKeyObjErr(d.NewKey, src) 27 return newKeyObjErr(d.NewKey, src)
28 } 28 }
29 29
30 func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error { 30 func (d *datastoreImpl) Run(q Query, cbIface interface{}) error {
31 » if _, ok := proto.(*Key); ok { 31 » cbTyp := reflect.TypeOf(cbIface)
32 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc func() (Cursor, error)) bool { 32 » if cbTyp.NumIn() != 2 || cbTyp.NumOut() != 1 {
Vadim Sh. 2015/08/07 20:23:05 check that cbTyp is a function?
iannucci 2015/08/07 20:37:50 Done.
33 » » return fmt.Errorf("cb has the wrong number of args: %T", cbIface )
34 » }
35
36 » if cbTyp.Out(0) != typeOfBool {
37 » » return fmt.Errorf("cb has the wrong return type (expected bool): %s", cbTyp.Out(0))
38 » }
39
40 » if cbTyp.In(1) != typeOfCursorCB {
41 » » return fmt.Errorf("cb has a bad second argument (expected Cursor CB): %s", cbTyp.In(1))
42 » }
43
44 » if cbTyp.In(0) == typeOfKey {
Vadim Sh. 2015/08/07 20:23:05 nit: you can probably cache all this checks (using
iannucci 2015/08/07 20:37:50 Yeah, probably can. I suspect it's overkill though
iannucci 2015/08/07 20:37:50 Yeah, probably can. I suspect it's overkill though
45 » » cb := cbIface.(func(Key, CursorCB) bool)
46 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc CursorCB) bool {
33 return cb(k, gc) 47 return cb(k, gc)
34 }) 48 })
35 } 49 }
36 50
37 » mat := parseArg(reflect.TypeOf(proto)) 51 » mat := parseArg(cbTyp.In(0))
38 if !mat.valid || mat.newElem == nil { 52 if !mat.valid || mat.newElem == nil {
39 » » return fmt.Errorf("invalid Run proto type: %T", proto) 53 » » return fmt.Errorf("cb has a bad first argument: %s", cbTyp.In(0) )
40 } 54 }
55 cbVal := reflect.ValueOf(cbIface)
41 56
42 innerErr := error(nil) 57 innerErr := error(nil)
43 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs or, error)) bool { 58 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc CursorCB) bo ol {
44 itm := mat.newElem() 59 itm := mat.newElem()
45 if innerErr = mat.setPM(itm, pm); innerErr != nil { 60 if innerErr = mat.setPM(itm, pm); innerErr != nil {
46 return false 61 return false
47 } 62 }
48 mat.setKey(itm, k) 63 mat.setKey(itm, k)
49 » » return cb(itm.Interface(), gc) 64 » » return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0]. Bool()
50 }) 65 })
51 if err == nil { 66 if err == nil {
52 err = innerErr 67 err = innerErr
53 } 68 }
54 return err 69 return err
55 } 70 }
56 71
57 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { 72 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error {
58 v := reflect.ValueOf(dst) 73 v := reflect.ValueOf(dst)
59 if v.Kind() != reflect.Ptr { 74 if v.Kind() != reflect.Ptr {
60 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) 75 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst)
61 } 76 }
62 if !v.IsValid() || v.IsNil() { 77 if !v.IsValid() || v.IsNil() {
63 return errors.New("invalid GetAll dst: <nil>") 78 return errors.New("invalid GetAll dst: <nil>")
64 } 79 }
65 80
66 if keys, ok := dst.(*[]Key); ok { 81 if keys, ok := dst.(*[]Key); ok {
67 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ func() (Cursor, error)) bool { 82 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ CursorCB) bool {
68 *keys = append(*keys, k) 83 *keys = append(*keys, k)
69 return true 84 return true
70 }) 85 })
71 } 86 }
72 87
73 slice := v.Elem() 88 slice := v.Elem()
74 mat := parseMultiArg(slice.Type()) 89 mat := parseMultiArg(slice.Type())
75 if !mat.valid || mat.newElem == nil { 90 if !mat.valid || mat.newElem == nil {
76 return fmt.Errorf("invalid GetAll input type: %T", dst) 91 return fmt.Errorf("invalid GetAll input type: %T", dst)
77 } 92 }
78 93
79 lme := errors.LazyMultiError{Size: slice.Len()} 94 lme := errors.LazyMultiError{Size: slice.Len()}
80 i := 0 95 i := 0
81 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso r, error)) bool { 96 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ CursorCB) boo l {
82 slice.Set(reflect.Append(slice, mat.newElem())) 97 slice.Set(reflect.Append(slice, mat.newElem()))
83 itm := slice.Index(i) 98 itm := slice.Index(i)
84 mat.setKey(itm, k) 99 mat.setKey(itm, k)
85 lme.Assign(i, mat.setPM(itm, pm)) 100 lme.Assign(i, mat.setPM(itm, pm))
86 i++ 101 i++
87 return true 102 return true
88 }) 103 })
89 if err == nil { 104 if err == nil {
90 err = lme.Get() 105 err = lme.Get()
91 } 106 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 err = lme.Get() 201 err = lme.Get()
187 if err == nil { 202 if err == nil {
188 err = extErr 203 err = extErr
189 } 204 }
190 return 205 return
191 } 206 }
192 207
193 func (d *datastoreImpl) Raw() RawInterface { 208 func (d *datastoreImpl) Raw() RawInterface {
194 return d.RawInterface 209 return d.RawInterface
195 } 210 }
OLDNEW
« no previous file with comments | « service/datastore/checkfilter_test.go ('k') | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698