func (t *Iterator) getCursor() *Cursor {
	return &Cursor{t.res.CompiledCursor}
}
getCursor returns the cursor for the current batch.
package datastore
import (
	"encoding/base64"
	"errors"
	"fmt"
	"math"
	"reflect"
	"strings"
	"code.google.com/p/goprotobuf/proto"
	"appengine"
	pb "appengine_internal/datastore"
)
type queryOperator int
const (
	QueryOperatorLessThan queryOperator = iota
	QueryOperatorLessThanOrEqual
	QueryOperatorEqual
	QueryOperatorGreaterThanOrEqual
	QueryOperatorGreaterThan
)
var queryOperatorToProto = map[queryOperator]*pb.Query_Filter_Operator{
	QueryOperatorLessThan:           pb.NewQuery_Filter_Operator(pb.Query_Filter_LESS_THAN),
	QueryOperatorLessThanOrEqual:    pb.NewQuery_Filter_Operator(pb.Query_Filter_LESS_THAN_OR_EQUAL),
	QueryOperatorEqual:              pb.NewQuery_Filter_Operator(pb.Query_Filter_EQUAL),
	QueryOperatorGreaterThanOrEqual: pb.NewQuery_Filter_Operator(pb.Query_Filter_GREATER_THAN_OR_EQUAL),
	QueryOperatorGreaterThan:        pb.NewQuery_Filter_Operator(pb.Query_Filter_GREATER_THAN),
}
type queryDirection int
const (
	QueryDirectionAscending queryDirection = iota
	QueryDirectionDescending
)
var queryDirectionToProto = map[queryDirection]*pb.Query_Order_Direction{
	QueryDirectionAscending:  pb.NewQuery_Order_Direction(pb.Query_Order_ASCENDING),
	QueryDirectionDescending: pb.NewQuery_Order_Direction(pb.Query_Order_DESCENDING),
}
func NewBaseQuery() *BaseQuery {
	return &BaseQuery{pbq: new(pb.Query)}
}
type BaseQuery struct {
	pbq *pb.Query
	err error
}
func (q *BaseQuery) Clone() *BaseQuery {
	return &BaseQuery{pbq: &(*q.pbq), err: q.err}
}
func (q *BaseQuery) Namespace(namespace string) *BaseQuery {
	if q.err == nil {
		if namespace == "" {
			q.pbq.NameSpace = nil
		} else {
			q.pbq.NameSpace = proto.String(namespace)
		}
	}
	return q
}
func (q *BaseQuery) Ancestor(key *Key) *BaseQuery {
	if q.err == nil {
		if key == nil {
			q.pbq.Ancestor = nil
		} else {
			if key.Incomplete() {
				q.err = errors.New("datastore: incomplete query ancestor key")
			} else {
				q.pbq.Ancestor = keyToProto(key)
			}
		}
	}
	return q
}
func (q *BaseQuery) Kind(kind string) *BaseQuery {
	if q.err == nil {
		if kind == "" {
			q.pbq.Kind = nil
		} else {
			q.pbq.Kind = proto.String(kind)
		}
	}
	return q
}
func (q *BaseQuery) Filter(property string, operator queryOperator,
	value interface{}) *BaseQuery {
	if q.err == nil {
		var p *pb.Property
		p, q.err = valueToProto(property, value, false)
		if q.err == nil {
			q.pbq.Filter = append(q.pbq.Filter, &pb.Query_Filter{
				Op:       queryOperatorToProto[operator],
				Property: []*pb.Property{p},
			})
		}
	}
	return q
}
func (q *BaseQuery) Order(property string, direction queryDirection) *BaseQuery {
	if q.err == nil {
		q.pbq.Order = append(q.pbq.Order, &pb.Query_Order{
			Property:  proto.String(property),
			Direction: queryDirectionToProto[direction],
		})
	}
	return q
}
func (q *BaseQuery) Limit(limit int) *BaseQuery {
	if q.err == nil {
		if q.err = validateInt32(limit, "limit"); q.err == nil {
			q.pbq.Limit = proto.Int32(int32(limit))
		}
	}
	return q
}
func (q *BaseQuery) Offset(offset int) *BaseQuery {
	if q.err == nil {
		if q.err = validateInt32(offset, "offset"); q.err == nil {
			q.pbq.Offset = proto.Int32(int32(offset))
		}
	}
	return q
}
func (q *BaseQuery) KeysOnly(keysOnly bool) *BaseQuery {
	if q.err == nil {
		q.pbq.KeysOnly = proto.Bool(keysOnly)
		q.pbq.RequirePerfectPlan = proto.Bool(keysOnly)
	}
	return q
}
func (q *BaseQuery) Compile(compile bool) *BaseQuery {
	if q.err == nil {
		q.pbq.Compile = proto.Bool(compile)
	}
	return q
}
func (q *BaseQuery) Cursor(cursor *Cursor) *BaseQuery {
	if q.err == nil {
		if cursor == nil {
			q.pbq.CompiledCursor = nil
		} else if cursor.compiled == nil {
			q.err = errors.New("datastore: empty start cursor")
		} else {
			q.pbq.CompiledCursor = cursor.compiled
		}
	}
	if q.err == nil {
		q.pbq.Compile = proto.Bool(true)
	}
	return q
}
func (q *BaseQuery) EndCursor(cursor *Cursor) *BaseQuery {
	if q.err == nil {
		if cursor == nil {
			q.pbq.EndCompiledCursor = nil
		} else if cursor.compiled == nil {
			q.err = errors.New("datastore: empty end cursor")
		} else {
			q.pbq.EndCompiledCursor = cursor.compiled
		}
	}
	if q.err == nil {
		q.pbq.Compile = proto.Bool(true)
	}
	return q
}
func (q *BaseQuery) toProto(pbq *pb.Query, zeroLimitMeansZero bool) error {
	if q.err != nil {
		return q.err
	}
	if !zeroLimitMeansZero && proto.GetInt32(pbq.Limit) == 0 {
		pbq.Limit = nil
	}
	return nil
}
func (q *BaseQuery) Run(c appengine.Context) *Iterator {
	req := *q.pbq
	if err := q.toProto(&req, false); err != nil {
		return &Iterator{err: q.err}
	}
	req.App = proto.String(c.FullyQualifiedAppID())
	t := &Iterator{
		c:      c,
		q:      q,
		limit:  proto.GetInt32(req.Limit),
		offset: proto.GetInt32(req.Offset),
	}
	if err := c.Call("datastore_v3", "RunQuery", &req, &t.res, nil); err != nil {
		t.err = err
		return t
	}
	return t
}
func (q *BaseQuery) GetAll(c appengine.Context, dst interface{}) ([]*Key, error) {
	var (
		dv       reflect.Value
		mat      multiArgType
		elemType reflect.Type
	)
	keysOnly := q.pbq.KeysOnly != nil && *q.pbq.KeysOnly
	if !keysOnly {
		dv = reflect.ValueOf(dst)
		if dv.Kind() != reflect.Ptr || dv.IsNil() {
			return nil, ErrInvalidEntityType
		}
		dv = dv.Elem()
		mat, elemType = checkMultiArg(dv)
		if mat == multiArgTypeInvalid || mat == multiArgTypeInterface {
			return nil, ErrInvalidEntityType
		}
	}
	var keys []*Key
	for t := q.Run(c); ; {
		k, e, err := t.next()
		if err == Done {
			break
		}
		if err != nil {
			return keys, err
		}
		if !keysOnly {
			ev := reflect.New(elemType)
			if elemType.Kind() == reflect.Map {
				x := reflect.MakeMap(elemType)
				ev.Elem().Set(x)
			}
			if err = loadEntity(ev.Interface(), e); err != nil {
				return keys, err
			}
			if mat != multiArgTypeStructPtr {
				ev = ev.Elem()
			}
			dv.Set(reflect.Append(dv, ev))
		}
		keys = append(keys, k)
	}
	return keys, nil
}
func (q *BaseQuery) GetPage(c appengine.Context, dst interface{}) (keys []*Key,
	cursor *Cursor, hasMore bool, err error) {
	q = q.Clone()
	limit := int(proto.GetInt32(q.pbq.Limit))
	q.Limit(limit + 1)
	if keys, err = q.GetAll(c, dst); err != nil {
		return nil, nil, false, err
	}
	if len(keys) > limit {
		hasMore = true
		keys = keys[:limit]
	}
	if cursor, err = q.GetCursorAt(c, limit); err != nil {
		return nil, nil, false, err
	}
	return
}
func (q *BaseQuery) Count(c appengine.Context) (int, error) {
	if q.err != nil {
		return 0, q.err
	}
	newQ := q.Clone()
	newQ.KeysOnly(true)
	newQ.Limit(0)
	limit := proto.GetInt32(q.pbq.Limit)
	offset := proto.GetInt32(q.pbq.Offset)
	var newOffset int32
	if limit == 0 {
		newOffset = math.MaxInt32
	} else {
		newOffset = offset + limit
		if newOffset < 0 {
			newOffset = math.MaxInt32
		}
	}
	newQ.Offset(int(newOffset))
	req := &pb.Query{}
	if err := newQ.toProto(req, true); err != nil {
		return 0, err
	}
	res := &pb.QueryResult{}
	if err := c.Call("datastore_v3", "RunQuery", req, res, nil); err != nil {
		return 0, err
	}
	var n int32
	for {
		if len(res.Result) != 0 {
			return 0, errors.New("datastore: internal error: Count request returned too much data")
		}
		n += proto.GetInt32(res.SkippedResults)
		if !proto.GetBool(res.MoreResults) {
			break
		}
		if err := callNext(c, res, newOffset-n, 0, true); err != nil {
			return 0, err
		}
	}
	n -= offset
	if n < 0 {
		n = 0
	}
	return int(n), nil
}
func (q *BaseQuery) GetCursorAt(c appengine.Context, position int) (*Cursor, error) {
	if q.err != nil {
		return nil, q.err
	}
	if err := validateInt32(position, "cursor position"); err != nil {
		return nil, err
	}
	q = q.Clone().Limit(0).Offset(position).KeysOnly(true).Compile(true)
	t := q.Run(c)
	for {
		if _, err := t.Next(nil); err == Done {
			break
		} else if err != nil {
			return nil, err
		}
	}
	return t.getCursor(), nil
}
func validateInt32(v int, name string) error {
	if v < 0 {
		return fmt.Errorf("datastore: negative value for %v", name)
	}
	if v > math.MaxInt32 {
		return fmt.Errorf("datastore: value overflow for %v", name)
	}
	return nil
}
var Done = errors.New("datastore: query has no more results")
type Iterator struct {
	c      appengine.Context
	q      *BaseQuery
	offset int32
	limit  int32
	res    pb.QueryResult
	curr   int  
	last   int  
	err    error
}
func (t *Iterator) Next(dst interface{}) (*Key, error) {
	k, e, err := t.next()
	if err != nil || e == nil {
		return k, err
	}
	t.curr += 1
	return k, loadEntity(dst, e)
}
func (t *Iterator) next() (*Key, *pb.EntityProto, error) {
	if err := t.nextBatch(); err != nil {
		return nil, nil, err
	}
	var e *pb.EntityProto
	e, t.res.Result = t.res.Result[0], t.res.Result[1:]
	if e.Key == nil {
		return nil, nil, errors.New("datastore: internal error: server did not return a key")
	}
	k, err := protoToKey(e.Key)
	if err != nil || k.Incomplete() {
		return nil, nil, errors.New("datastore: internal error: server returned an invalid key")
	}
	if proto.GetBool(t.res.KeysOnly) {
		return k, nil, nil
	}
	return k, e, nil
}
func (t *Iterator) nextBatch() error {
	if t.err != nil {
		return t.err
	}
	for len(t.res.Result) == 0 {
		if !proto.GetBool(t.res.MoreResults) {
			t.err = Done
			return t.err
		}
		t.offset -= proto.GetInt32(t.res.SkippedResults)
		if t.offset < 0 {
			t.offset = 0
		}
		if err := callNext(t.c, &t.res, t.offset, t.limit, false); err != nil {
			t.err = err
			return t.err
		}
		t.last += len(t.res.Result)
		if t.limit == 0 {
			continue
		}
		t.limit -= int32(len(t.res.Result))
		if t.limit > 0 {
			continue
		}
		t.limit = 0
		if proto.GetBool(t.res.MoreResults) {
			t.err = errors.New("datastore: internal error: limit exhausted but more_results is true")
			return t.err
		}
	}
	return nil
}
func (t *Iterator) GetCursorAfter() *Cursor {
	return t.getCursorAt(t.curr)
}
func (t *Iterator) GetCursorBefore() *Cursor {
	return t.getCursorAt(t.curr - 1)
}
func (t *Iterator) getCursorAt(position int) *Cursor {
	if err := t.nextBatch(); err != nil && err != Done {
		return nil
	}
	if t.curr == 0 || t.res.CompiledCursor == nil {
		return nil
	}
	if position == t.last {
		return t.getCursor()
	}
	cursor, err := t.q.GetCursorAt(t.c, position)
	if err != nil {
		return nil
	}
	return cursor
}