Chromium Code Reviews| Index: service/datastore/datastore.go |
| diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go |
| index 4bb31d4a5de096fdd2e2c9c8edd5ec8df608a14f..2f23a6c4882f9477765528688a9d437db12adeec 100644 |
| --- a/service/datastore/datastore.go |
| +++ b/service/datastore/datastore.go |
| @@ -27,26 +27,41 @@ func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) { |
| return newKeyObjErr(d.NewKey, src) |
| } |
| -func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error { |
| - if _, ok := proto.(*Key); ok { |
| - return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMap, gc func() (Cursor, error)) bool { |
| +func (d *datastoreImpl) Run(q Query, cbIface interface{}) error { |
| + cbTyp := reflect.TypeOf(cbIface) |
| + 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.
|
| + return fmt.Errorf("cb has the wrong number of args: %T", cbIface) |
| + } |
| + |
| + if cbTyp.Out(0) != typeOfBool { |
| + return fmt.Errorf("cb has the wrong return type (expected bool): %s", cbTyp.Out(0)) |
| + } |
| + |
| + if cbTyp.In(1) != typeOfCursorCB { |
| + return fmt.Errorf("cb has a bad second argument (expected CursorCB): %s", cbTyp.In(1)) |
| + } |
| + |
| + 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
|
| + cb := cbIface.(func(Key, CursorCB) bool) |
| + return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMap, gc CursorCB) bool { |
| return cb(k, gc) |
| }) |
| } |
| - mat := parseArg(reflect.TypeOf(proto)) |
| + mat := parseArg(cbTyp.In(0)) |
| if !mat.valid || mat.newElem == nil { |
| - return fmt.Errorf("invalid Run proto type: %T", proto) |
| + return fmt.Errorf("cb has a bad first argument: %s", cbTyp.In(0)) |
| } |
| + cbVal := reflect.ValueOf(cbIface) |
| innerErr := error(nil) |
| - err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Cursor, error)) bool { |
| + err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc CursorCB) bool { |
| itm := mat.newElem() |
| if innerErr = mat.setPM(itm, pm); innerErr != nil { |
| return false |
| } |
| mat.setKey(itm, k) |
| - return cb(itm.Interface(), gc) |
| + return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0].Bool() |
| }) |
| if err == nil { |
| err = innerErr |
| @@ -64,7 +79,7 @@ func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { |
| } |
| if keys, ok := dst.(*[]Key); ok { |
| - return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMap, _ func() (Cursor, error)) bool { |
| + return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMap, _ CursorCB) bool { |
| *keys = append(*keys, k) |
| return true |
| }) |
| @@ -78,7 +93,7 @@ func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { |
| lme := errors.LazyMultiError{Size: slice.Len()} |
| i := 0 |
| - err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Cursor, error)) bool { |
| + err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ CursorCB) bool { |
| slice.Set(reflect.Append(slice, mat.newElem())) |
| itm := slice.Index(i) |
| mat.setKey(itm, k) |