| Index: service/datastore/dskey/key.go
|
| diff --git a/service/datastore/key.go b/service/datastore/dskey/key.go
|
| similarity index 66%
|
| rename from service/datastore/key.go
|
| rename to service/datastore/dskey/key.go
|
| index 0e588754b8af7f2af8fbf6601d28f60d28282282..f700d518e35d2765899c0aac995961aa5b86c072 100644
|
| --- a/service/datastore/key.go
|
| +++ b/service/datastore/dskey/key.go
|
| @@ -4,7 +4,7 @@
|
|
|
| // adapted from github.com/golang/appengine/datastore
|
|
|
| -package datastore
|
| +package dskey
|
|
|
| import (
|
| "bytes"
|
| @@ -13,16 +13,18 @@ import (
|
| "strconv"
|
| "strings"
|
|
|
| - pb "github.com/luci/gae/service/datastore/internal/protos/datastore"
|
| -
|
| "github.com/golang/protobuf/proto"
|
| + ds "github.com/luci/gae/service/datastore"
|
| + pb "github.com/luci/gae/service/datastore/internal/protos/datastore"
|
| )
|
|
|
| -// KeyEncode encodes the provided key as a base64-encoded protobuf.
|
| +// Encode encodes the provided key as a base64-encoded protobuf.
|
| //
|
| // This encoding is compatible with the SDK-provided encoding and is agnostic
|
| // to the underlying implementation of the Key.
|
| -func KeyEncode(k Key) string {
|
| +//
|
| +// It's encoded with the urlsafe base64 table.
|
| +func Encode(k ds.Key) string {
|
| n := 0
|
| for i := k; i != nil; i = i.Parent() {
|
| n++
|
| @@ -63,13 +65,13 @@ func KeyEncode(k Key) string {
|
| return strings.TrimRight(base64.URLEncoding.EncodeToString(r), "=")
|
| }
|
|
|
| -// KeyToksDecode decodes a base64-encoded protobuf representation of a Key
|
| +// ToksDecode decodes a base64-encoded protobuf representation of a Key
|
| // into a tokenized form. This is so that implementations of the gae wrapper
|
| // can decode to their own implementation of Key.
|
| //
|
| // This encoding is compatible with the SDK-provided encoding and is agnostic
|
| // to the underlying implementation of the Key.
|
| -func KeyToksDecode(encoded string) (appID, namespace string, toks []KeyTok, err error) {
|
| +func ToksDecode(encoded string) (appID, namespace string, toks []ds.KeyTok, err error) {
|
| // Re-add padding
|
| if m := len(encoded) % 4; m != 0 {
|
| encoded += strings.Repeat("=", 4-m)
|
| @@ -86,9 +88,9 @@ func KeyToksDecode(encoded string) (appID, namespace string, toks []KeyTok, err
|
|
|
| appID = r.GetApp()
|
| namespace = r.GetNameSpace()
|
| - toks = make([]KeyTok, len(r.Path.Element))
|
| + toks = make([]ds.KeyTok, len(r.Path.Element))
|
| for i, e := range r.Path.Element {
|
| - toks[i] = KeyTok{
|
| + toks[i] = ds.KeyTok{
|
| Kind: e.GetType(),
|
| IntID: e.GetId(),
|
| StringID: e.GetName(),
|
| @@ -97,35 +99,35 @@ func KeyToksDecode(encoded string) (appID, namespace string, toks []KeyTok, err
|
| return
|
| }
|
|
|
| -// KeyMarshalJSON returns a MarshalJSON-compatible serialization of a Key.
|
| -func KeyMarshalJSON(k Key) ([]byte, error) {
|
| - return []byte(`"` + KeyEncode(k) + `"`), nil
|
| +// MarshalJSON returns a MarshalJSON-compatible serialization of a Key.
|
| +func MarshalJSON(k ds.Key) ([]byte, error) {
|
| + return []byte(`"` + Encode(k) + `"`), nil
|
| }
|
|
|
| -// KeyUnmarshalJSON returns the tokenized version of a Key as encoded by
|
| -// KeyMarshalJSON.
|
| -func KeyUnmarshalJSON(buf []byte) (appID, namespace string, toks []KeyTok, err error) {
|
| +// UnmarshalJSON returns the tokenized version of a ds.Key as encoded by
|
| +// MarshalJSON.
|
| +func UnmarshalJSON(buf []byte) (appID, namespace string, toks []ds.KeyTok, err error) {
|
| if len(buf) < 2 || buf[0] != '"' || buf[len(buf)-1] != '"' {
|
| err = errors.New("datastore: bad JSON key")
|
| } else {
|
| - appID, namespace, toks, err = KeyToksDecode(string(buf[1 : len(buf)-1]))
|
| + appID, namespace, toks, err = ToksDecode(string(buf[1 : len(buf)-1]))
|
| }
|
| return
|
| }
|
|
|
| -// KeyIncomplete returns true iff k doesn't have an id yet.
|
| -func KeyIncomplete(k Key) bool {
|
| +// Incomplete returns true iff k doesn't have an id yet.
|
| +func Incomplete(k ds.Key) bool {
|
| return k != nil && k.StringID() == "" && k.IntID() == 0
|
| }
|
|
|
| -// KeyValid determines if a key is valid, according to a couple rules:
|
| +// Valid determines if a key is valid, according to a couple rules:
|
| // - k is not nil
|
| // - every token of k:
|
| // - (if !allowSpecial) token's kind doesn't start with '__'
|
| // - token's kind and appid are non-blank
|
| // - token is not incomplete
|
| // - all tokens have the same namespace and appid
|
| -func KeyValid(k Key, allowSpecial bool, aid, ns string) bool {
|
| +func Valid(k ds.Key, allowSpecial bool, aid, ns string) bool {
|
| if k == nil {
|
| return false
|
| }
|
| @@ -143,7 +145,7 @@ func KeyValid(k Key, allowSpecial bool, aid, ns string) bool {
|
| return false
|
| }
|
| if k.Parent() != nil {
|
| - if KeyIncomplete(k.Parent()) {
|
| + if k.Parent().Incomplete() {
|
| return false
|
| }
|
| if k.Parent().AppID() != k.AppID() || k.Parent().Namespace() != k.Namespace() {
|
| @@ -154,16 +156,26 @@ func KeyValid(k Key, allowSpecial bool, aid, ns string) bool {
|
| return true
|
| }
|
|
|
| -// KeyRoot returns the entity root for the given key.
|
| -func KeyRoot(k Key) Key {
|
| +// PartialValid returns true iff this key is suitable for use in a Put
|
| +// operation. This is the same as Valid(k, false, ...), but also allowing k to
|
| +// be Incomplete().
|
| +func PartialValid(k ds.Key, aid, ns string) bool {
|
| + if k.Incomplete() {
|
| + k = New(k.AppID(), k.Namespace(), k.Kind(), "", 1, k.Parent())
|
| + }
|
| + return Valid(k, false, aid, ns)
|
| +}
|
| +
|
| +// Root returns the entity root for the given key.
|
| +func Root(k ds.Key) ds.Key {
|
| for k != nil && k.Parent() != nil {
|
| k = k.Parent()
|
| }
|
| return k
|
| }
|
|
|
| -// KeysEqual returns true iff the two keys represent identical key values.
|
| -func KeysEqual(a, b Key) (ret bool) {
|
| +// Equal returns true iff the two keys represent identical key values.
|
| +func Equal(a, b ds.Key) (ret bool) {
|
| ret = (a.Kind() == b.Kind() &&
|
| a.StringID() == b.StringID() &&
|
| a.IntID() == b.IntID() &&
|
| @@ -173,10 +185,10 @@ func KeysEqual(a, b Key) (ret bool) {
|
| return
|
| }
|
| ap, bp := a.Parent(), b.Parent()
|
| - return (ap == nil && bp == nil) || KeysEqual(ap, bp)
|
| + return (ap == nil && bp == nil) || Equal(ap, bp)
|
| }
|
|
|
| -func marshalDSKey(b *bytes.Buffer, k Key) {
|
| +func marshalDSKey(b *bytes.Buffer, k ds.Key) {
|
| if k.Parent() != nil {
|
| marshalDSKey(b, k.Parent())
|
| }
|
| @@ -190,9 +202,9 @@ func marshalDSKey(b *bytes.Buffer, k Key) {
|
| }
|
| }
|
|
|
| -// KeyString returns a human-readable representation of the key, and is the
|
| +// String returns a human-readable representation of the key, and is the
|
| // typical implementation of Key.String() (though it isn't guaranteed to be)
|
| -func KeyString(k Key) string {
|
| +func String(k ds.Key) string {
|
| if k == nil {
|
| return ""
|
| }
|
| @@ -201,14 +213,14 @@ func KeyString(k Key) string {
|
| return b.String()
|
| }
|
|
|
| -// KeySplit splits the key into its constituent parts. Note that if the key is
|
| -// not KeyValid, this method may not provide a round-trip for k.
|
| -func KeySplit(k Key) (appID, namespace string, toks []KeyTok) {
|
| +// Split splits the key into its constituent parts. Note that if the key is
|
| +// not Valid, this method may not provide a round-trip for k.
|
| +func Split(k ds.Key) (appID, namespace string, toks []ds.KeyTok) {
|
| if k == nil {
|
| return
|
| }
|
|
|
| - if sk, ok := k.(*GenericKey); ok {
|
| + if sk, ok := k.(*Generic); ok {
|
| if sk == nil {
|
| return
|
| }
|
| @@ -219,7 +231,7 @@ func KeySplit(k Key) (appID, namespace string, toks []KeyTok) {
|
| for i := k; i != nil; i = i.Parent() {
|
| n++
|
| }
|
| - toks = make([]KeyTok, n)
|
| + toks = make([]ds.KeyTok, n)
|
| for i := k; i != nil; i = i.Parent() {
|
| n--
|
| toks[n].IntID = i.IntID()
|
|
|