Index: service/datastore/datastore.go |
diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go |
index 4bb31d4a5de096fdd2e2c9c8edd5ec8df608a14f..ea49eb4c440d523458168377c06da5321441fd38 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 { |
+ return fmt.Errorf("cb has the wrong number of args: %T", cbIface) |
dnj
2015/08/07 20:21:02
WDYT about bundling all of these objections togeth
iannucci
2015/08/07 20:22:03
yeah, ok, SGTM
|
+ } |
+ |
+ if cbTyp.Out(0) != typeOfBool { |
+ return fmt.Errorf("cb has the wrong return type (expected bool): %T", cbTyp.Out(0)) |
+ } |
+ |
+ if cbTyp.In(1) != typeOfCursorCB { |
+ return fmt.Errorf("cb has a bad second argument (expected CursorCB): %T", cbTyp.In(1)) |
+ } |
+ |
+ if cbTyp.In(0) == typeOfKey { |
+ 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) |