go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gae/impl/prod/datastore_key.go (about)

     1  // Copyright 2015 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package prod
    16  
    17  import (
    18  	"context"
    19  
    20  	"google.golang.org/appengine"
    21  	"google.golang.org/appengine/datastore"
    22  
    23  	"go.chromium.org/luci/common/errors"
    24  
    25  	ds "go.chromium.org/luci/gae/service/datastore"
    26  )
    27  
    28  // dsR2F (DS real-to-fake) converts an SDK Key to a ds.Key
    29  func dsR2F(k *datastore.Key) *ds.Key {
    30  	if k == nil {
    31  		return nil
    32  	}
    33  	kc := ds.MkKeyContext(k.AppID(), k.Namespace())
    34  
    35  	count := 0
    36  	for nk := k; nk != nil; nk = nk.Parent() {
    37  		count++
    38  	}
    39  
    40  	toks := make([]ds.KeyTok, count)
    41  
    42  	for ; k != nil; k = k.Parent() {
    43  		count--
    44  		toks[count].Kind = k.Kind()
    45  		toks[count].StringID = k.StringID()
    46  		toks[count].IntID = k.IntID()
    47  	}
    48  	return kc.NewKeyToks(toks)
    49  }
    50  
    51  // dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key.
    52  func dsF2R(aeCtx context.Context, k *ds.Key) (*datastore.Key, error) {
    53  	if k == nil {
    54  		return nil, nil
    55  	}
    56  
    57  	// drop aid.
    58  	_, ns, toks := k.Split()
    59  	err := error(nil)
    60  	aeCtx, err = appengine.Namespace(aeCtx, ns)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	ret := datastore.NewKey(aeCtx, toks[0].Kind, toks[0].StringID, toks[0].IntID, nil)
    66  	for _, t := range toks[1:] {
    67  		ret = datastore.NewKey(aeCtx, t.Kind, t.StringID, t.IntID, ret)
    68  	}
    69  
    70  	return ret, nil
    71  }
    72  
    73  // dsMF2R (DS multi-fake-to-fake) converts a slice of wrapped keys to SDK keys.
    74  func dsMF2R(aeCtx context.Context, ks []*ds.Key) ([]*datastore.Key, error) {
    75  	lme := errors.NewLazyMultiError(len(ks))
    76  	ret := make([]*datastore.Key, len(ks))
    77  	err := error(nil)
    78  	for i, k := range ks {
    79  		ret[i], err = dsF2R(aeCtx, k)
    80  		lme.Assign(i, err)
    81  	}
    82  	return ret, lme.Get()
    83  }