func loadEntity(dst interface{}, k *Key, e *pb.EntityProto) (*Key, error) {
	if m, ok := dst.(Map); ok {
		return k, loadMap(m, k, e)
	}
	sv, err := asStructValue(dst)
	if err != nil {
		return nil, err
	}
	return k, loadStruct(sv, k, e)
}
loadEntity loads an EntityProto into a Map or struct.
package datastore
import (
	"errors"
	"fmt"
	"math"
	"reflect"
	"strings"
	"appengine"
	"goprotobuf.googlecode.com/hg/proto"
	pb "appengine_internal/datastore"
)
type operator int
const (
	lessThan operator = iota
	lessEq
	equal
	greaterEq
	greaterThan
)
var operatorToProto = map[operator]*pb.Query_Filter_Operator{
	lessThan:    pb.NewQuery_Filter_Operator(pb.Query_Filter_LESS_THAN),
	lessEq:      pb.NewQuery_Filter_Operator(pb.Query_Filter_LESS_THAN_OR_EQUAL),
	equal:       pb.NewQuery_Filter_Operator(pb.Query_Filter_EQUAL),
	greaterEq:   pb.NewQuery_Filter_Operator(pb.Query_Filter_GREATER_THAN_OR_EQUAL),
	greaterThan: pb.NewQuery_Filter_Operator(pb.Query_Filter_GREATER_THAN),
}
type filter struct {
	FieldName string
	Op        operator
	Value     interface{}
}
type sortDirection int
const (
	ascending sortDirection = iota
	descending
)
var sortDirectionToProto = map[sortDirection]*pb.Query_Order_Direction{
	ascending:  pb.NewQuery_Order_Direction(pb.Query_Order_ASCENDING),
	descending: pb.NewQuery_Order_Direction(pb.Query_Order_DESCENDING),
}
type order struct {
	FieldName string
	Direction sortDirection
}
func NewQuery(kind string) *Query {
	q := &Query{kind: kind}
	if kind == "" {
		q.err = errors.New("datastore: empty kind")
	}
	return q
}
type Query struct {
	kind     string
	ancestor *Key
	filter   []filter
	order    []order
	keysOnly bool
	limit    int32
	offset   int32
	err error
}
func (q *Query) Ancestor(ancestor *Key) *Query {
	if ancestor == nil {
		q.err = errors.New("datastore: nil query ancestor")
		return q
	}
	q.ancestor = ancestor
	return q
}
func (q *Query) Filter(filterStr string, value interface{}) *Query {
	filterStr = strings.TrimSpace(filterStr)
	if len(filterStr) < 1 {
		q.err = errors.New("datastore: invalid filter: " + filterStr)
		return q
	}
	f := filter{
		FieldName: strings.TrimRight(filterStr, " ><="),
		Value:     value,
	}
	switch op := strings.TrimSpace(filterStr[len(f.FieldName):]); op {
	case "<=":
		f.Op = lessEq
	case ">=":
		f.Op = greaterEq
	case "<":
		f.Op = lessThan
	case ">":
		f.Op = greaterThan
	case "=":
		f.Op = equal
	default:
		q.err = fmt.Errorf("datastore: invalid operator %q in filter %q", op, filterStr)
		return q
	}
	q.filter = append(q.filter, f)
	return q
}
func (q *Query) Order(fieldName string) *Query {
	fieldName = strings.TrimSpace(fieldName)
	o := order{Direction: ascending, FieldName: fieldName}
	if strings.HasPrefix(fieldName, "-") {
		o.Direction = descending
		o.FieldName = strings.TrimSpace(fieldName[1:])
	} else if strings.HasPrefix(fieldName, "+") {
		q.err = fmt.Errorf("datastore: invalid order: %q", fieldName)
		return q
	}
	if len(o.FieldName) == 0 {
		q.err = errors.New("datastore: empty order")
		return q
	}
	q.order = append(q.order, o)
	return q
}
func (q *Query) KeysOnly() *Query {
	q.keysOnly = true
	return q
}
func (q *Query) Limit(limit int) *Query {
	if limit < 0 {
		q.err = errors.New("datastore: negative query limit")
		return q
	}
	if limit > math.MaxInt32 {
		q.err = errors.New("datastore: query limit overflow")
		return q
	}
	q.limit = int32(limit)
	return q
}
func (q *Query) Offset(offset int) *Query {
	if offset < 0 {
		q.err = errors.New("datastore: negative query offset")
		return q
	}
	if offset > math.MaxInt32 {
		q.err = errors.New("datastore: query offset overflow")
		return q
	}
	q.offset = int32(offset)
	return q
}
type zeroLimitPolicy int
const (
	zeroLimitMeansUnlimited zeroLimitPolicy = iota
	zeroLimitMeansZero
)
func (q *Query) toProto(dst *pb.Query, appID string, zlp zeroLimitPolicy) error {
	if q.kind == "" {
		return errors.New("datastore: empty query kind")
	}
	dst.Reset()
	dst.App = proto.String(appID)
	dst.Kind = proto.String(q.kind)
	if q.ancestor != nil {
		dst.Ancestor = keyToProto(appID, q.ancestor)
	}
	if q.keysOnly {
		dst.KeysOnly = proto.Bool(true)
		dst.RequirePerfectPlan = proto.Bool(true)
	}
	for _, qf := range q.filter {
		if qf.FieldName == "" {
			return errors.New("datastore: empty query filter field name")
		}
		p, errStr := valueToProto(appID, qf.FieldName, reflect.ValueOf(qf.Value), false)
		if errStr != "" {
			return errors.New("datastore: bad query filter value type: " + errStr)
		}
		xf := &pb.Query_Filter{
			Op:       operatorToProto[qf.Op],
			Property: []*pb.Property{p},
		}
		if xf.Op == nil {
			return errors.New("datastore: unknown query filter operator")
		}
		dst.Filter = append(dst.Filter, xf)
	}
	for _, qo := range q.order {
		if qo.FieldName == "" {
			return errors.New("datastore: empty query order field name")
		}
		xo := &pb.Query_Order{
			Property:  proto.String(qo.FieldName),
			Direction: sortDirectionToProto[qo.Direction],
		}
		if xo.Direction == nil {
			return errors.New("datastore: unknown query order direction")
		}
		dst.Order = append(dst.Order, xo)
	}
	if q.limit != 0 || zlp == zeroLimitMeansZero {
		dst.Limit = proto.Int32(q.limit)
	}
	if q.offset != 0 {
		dst.Offset = proto.Int32(q.offset)
	}
	return nil
}
func (q *Query) Count(c appengine.Context) (int, error) {
	if q.err != nil {
		return 0, q.err
	}
	newQ := *q
	newQ.keysOnly = true
	newQ.limit = 0
	if q.limit == 0 {
		newQ.offset = math.MaxInt32
	} else {
		newQ.offset = q.offset + q.limit
		if newQ.offset < 0 {
			newQ.offset = math.MaxInt32
		}
	}
	req := &pb.Query{}
	if err := newQ.toProto(req, c.FullyQualifiedAppID(), zeroLimitMeansZero); 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, newQ.offset-n, 0, zeroLimitMeansZero); err != nil {
			return 0, err
		}
	}
	n -= q.offset
	if n < 0 {
		n = 0
	}
	return int(n), nil
}
func callNext(c appengine.Context, res *pb.QueryResult, offset, limit int32, zlp zeroLimitPolicy) error {
	if res.Cursor == nil {
		return errors.New("datastore: internal error: server did not return a cursor")
	}
	req := &pb.NextRequest{
		Cursor: res.Cursor,
		Offset: proto.Int32(offset),
	}
	if limit != 0 || zlp == zeroLimitMeansZero {
		req.Count = proto.Int32(limit)
	}
	if res.CompiledCursor != nil {
		req.Compile = proto.Bool(true)
	}
	res.Reset()
	return c.Call("datastore_v3", "Next", req, res, nil)
}
func (q *Query) GetAll(c appengine.Context, dst interface{}) ([]*Key, error) {
	var (
		dv       reflect.Value
		et       reflect.Type
		isMap    bool
		isStruct bool
	)
	if !q.keysOnly {
		dv = reflect.ValueOf(dst)
		if dv.Kind() != reflect.Ptr || dv.Elem().Kind() != reflect.Slice {
			return nil, ErrInvalidEntityType
		}
		if dv.IsNil() {
			return nil, ErrInvalidEntityType
		}
		dv = dv.Elem()
		et = dv.Type().Elem()
		switch {
		case et == reflect.TypeOf(Map(nil)):
			isMap = true
		case et.Kind() == reflect.Ptr && et.Elem().Kind() == reflect.Struct:
			et = et.Elem()
		case et.Kind() == reflect.Struct:
			isStruct = true
		default:
			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 !q.keysOnly {
			var ev reflect.Value
			if isMap {
				ev = reflect.ValueOf(make(Map))
			} else {
				ev = reflect.New(et)
			}
			if _, err = loadEntity(ev.Interface(), k, e); err != nil {
				return keys, err
			}
			if isStruct {
				ev = ev.Elem()
			}
			dv.Set(reflect.Append(dv, ev))
		}
		keys = append(keys, k)
	}
	return keys, nil
}
func (q *Query) Run(c appengine.Context) *Iterator {
	if q.err != nil {
		return &Iterator{err: q.err}
	}
	t := &Iterator{
		c:      c,
		offset: q.offset,
		limit:  q.limit,
	}
	var req pb.Query
	if err := q.toProto(&req, c.FullyQualifiedAppID(), zeroLimitMeansUnlimited); err != nil {
		t.err = err
		return t
	}
	if err := c.Call("datastore_v3", "RunQuery", &req, &t.res, nil); err != nil {
		t.err = err
		return t
	}
	return t
}
type Iterator struct {
	c      appengine.Context
	offset int32
	limit  int32
	res    pb.QueryResult
	err    error
}
var Done = errors.New("datastore: query has no more results")
func (t *Iterator) Next(dst interface{}) (*Key, error) {
	k, e, err := t.next()
	if err != nil || e == nil {
		return k, err
	}
	return loadEntity(dst, k, e)
}
func (t *Iterator) next() (*Key, *pb.EntityProto, error) {
	if t.err != nil {
		return nil, nil, t.err
	}
	for len(t.res.Result) == 0 {
		if !proto.GetBool(t.res.MoreResults) {
			t.err = Done
			return nil, nil, 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, zeroLimitMeansUnlimited); err != nil {
			t.err = err
			return nil, nil, t.err
		}
		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 nil, nil, t.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
}