| Index: service/datastore/dskey/key.go
|
| diff --git a/service/datastore/dskey/key.go b/service/datastore/dskey/key.go
|
| deleted file mode 100644
|
| index f700d518e35d2765899c0aac995961aa5b86c072..0000000000000000000000000000000000000000
|
| --- a/service/datastore/dskey/key.go
|
| +++ /dev/null
|
| @@ -1,244 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -// adapted from github.com/golang/appengine/datastore
|
| -
|
| -package dskey
|
| -
|
| -import (
|
| - "bytes"
|
| - "encoding/base64"
|
| - "errors"
|
| - "strconv"
|
| - "strings"
|
| -
|
| - "github.com/golang/protobuf/proto"
|
| - ds "github.com/luci/gae/service/datastore"
|
| - pb "github.com/luci/gae/service/datastore/internal/protos/datastore"
|
| -)
|
| -
|
| -// 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.
|
| -//
|
| -// 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++
|
| - }
|
| - e := make([]*pb.Path_Element, n)
|
| - for i := k; i != nil; i = i.Parent() {
|
| - n--
|
| - kind := i.Kind()
|
| - e[n] = &pb.Path_Element{
|
| - Type: &kind,
|
| - }
|
| - // At most one of {Name,Id} should be set.
|
| - // Neither will be set for incomplete keys.
|
| - if i.StringID() != "" {
|
| - sid := i.StringID()
|
| - e[n].Name = &sid
|
| - } else if i.IntID() != 0 {
|
| - iid := i.IntID()
|
| - e[n].Id = &iid
|
| - }
|
| - }
|
| - var namespace *string
|
| - if k.Namespace() != "" {
|
| - namespace = proto.String(k.Namespace())
|
| - }
|
| - r, err := proto.Marshal(&pb.Reference{
|
| - App: proto.String(k.AppID()),
|
| - NameSpace: namespace,
|
| - Path: &pb.Path{
|
| - Element: e,
|
| - },
|
| - })
|
| - if err != nil {
|
| - panic(err)
|
| - }
|
| -
|
| - // trim padding
|
| - return strings.TrimRight(base64.URLEncoding.EncodeToString(r), "=")
|
| -}
|
| -
|
| -// 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 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)
|
| - }
|
| - b, err := base64.URLEncoding.DecodeString(encoded)
|
| - if err != nil {
|
| - return
|
| - }
|
| -
|
| - r := &pb.Reference{}
|
| - if err = proto.Unmarshal(b, r); err != nil {
|
| - return
|
| - }
|
| -
|
| - appID = r.GetApp()
|
| - namespace = r.GetNameSpace()
|
| - toks = make([]ds.KeyTok, len(r.Path.Element))
|
| - for i, e := range r.Path.Element {
|
| - toks[i] = ds.KeyTok{
|
| - Kind: e.GetType(),
|
| - IntID: e.GetId(),
|
| - StringID: e.GetName(),
|
| - }
|
| - }
|
| - return
|
| -}
|
| -
|
| -// MarshalJSON returns a MarshalJSON-compatible serialization of a Key.
|
| -func MarshalJSON(k ds.Key) ([]byte, error) {
|
| - return []byte(`"` + Encode(k) + `"`), nil
|
| -}
|
| -
|
| -// 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 = ToksDecode(string(buf[1 : len(buf)-1]))
|
| - }
|
| - return
|
| -}
|
| -
|
| -// 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
|
| -}
|
| -
|
| -// 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 Valid(k ds.Key, allowSpecial bool, aid, ns string) bool {
|
| - if k == nil {
|
| - return false
|
| - }
|
| - if aid != k.AppID() || ns != k.Namespace() {
|
| - return false
|
| - }
|
| - for ; k != nil; k = k.Parent() {
|
| - if !allowSpecial && len(k.Kind()) >= 2 && k.Kind()[:2] == "__" {
|
| - return false
|
| - }
|
| - if k.Kind() == "" || k.AppID() == "" {
|
| - return false
|
| - }
|
| - if k.StringID() != "" && k.IntID() != 0 {
|
| - return false
|
| - }
|
| - if k.Parent() != nil {
|
| - if k.Parent().Incomplete() {
|
| - return false
|
| - }
|
| - if k.Parent().AppID() != k.AppID() || k.Parent().Namespace() != k.Namespace() {
|
| - return false
|
| - }
|
| - }
|
| - }
|
| - return true
|
| -}
|
| -
|
| -// 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
|
| -}
|
| -
|
| -// 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() &&
|
| - a.AppID() == b.AppID() &&
|
| - a.Namespace() == b.Namespace())
|
| - if !ret {
|
| - return
|
| - }
|
| - ap, bp := a.Parent(), b.Parent()
|
| - return (ap == nil && bp == nil) || Equal(ap, bp)
|
| -}
|
| -
|
| -func marshalDSKey(b *bytes.Buffer, k ds.Key) {
|
| - if k.Parent() != nil {
|
| - marshalDSKey(b, k.Parent())
|
| - }
|
| - b.WriteByte('/')
|
| - b.WriteString(k.Kind())
|
| - b.WriteByte(',')
|
| - if k.StringID() != "" {
|
| - b.WriteString(k.StringID())
|
| - } else {
|
| - b.WriteString(strconv.FormatInt(k.IntID(), 10))
|
| - }
|
| -}
|
| -
|
| -// 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 String(k ds.Key) string {
|
| - if k == nil {
|
| - return ""
|
| - }
|
| - b := bytes.NewBuffer(make([]byte, 0, 512))
|
| - marshalDSKey(b, k)
|
| - return b.String()
|
| -}
|
| -
|
| -// 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.(*Generic); ok {
|
| - if sk == nil {
|
| - return
|
| - }
|
| - return sk.appID, sk.namespace, sk.toks
|
| - }
|
| -
|
| - n := 0
|
| - for i := k; i != nil; i = i.Parent() {
|
| - n++
|
| - }
|
| - toks = make([]ds.KeyTok, n)
|
| - for i := k; i != nil; i = i.Parent() {
|
| - n--
|
| - toks[n].IntID = i.IntID()
|
| - toks[n].StringID = i.StringID()
|
| - toks[n].Kind = i.Kind()
|
| - }
|
| - appID = k.AppID()
|
| - namespace = k.Namespace()
|
| - return
|
| -}
|
|
|