Index: service/datastore/serialize/serialize.go |
diff --git a/service/datastore/serialize/serialize.go b/service/datastore/serialize/serialize.go |
index baea9b328207cebe69a55f879ce7b0e97c41e71c..736010820f222499212728ca30154029a905cc4f 100644 |
--- a/service/datastore/serialize/serialize.go |
+++ b/service/datastore/serialize/serialize.go |
@@ -14,6 +14,7 @@ import ( |
"github.com/luci/gae/service/blobstore" |
ds "github.com/luci/gae/service/datastore" |
"github.com/luci/luci-go/common/cmpbin" |
+ "github.com/luci/luci-go/common/stringset" |
) |
// MaxIndexColumns is the maximum number of sort columns (e.g. sort orders) that |
@@ -450,6 +451,58 @@ func ReadIndexDefinition(buf Buffer) (i ds.IndexDefinition, err error) { |
return |
} |
+// SerializedPslice is all of the serialized DSProperty values in qASC order. |
+type SerializedPslice [][]byte |
+ |
+func (s SerializedPslice) Len() int { return len(s) } |
+func (s SerializedPslice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
+func (s SerializedPslice) Less(i, j int) bool { return bytes.Compare(s[i], s[j]) < 0 } |
+ |
+// PropertySlice serializes a single row of a DSProperty map. |
+func PropertySlice(vals ds.PropertySlice) SerializedPslice { |
+ dups := stringset.New(0) |
+ ret := make(SerializedPslice, 0, len(vals)) |
+ for _, v := range vals { |
+ if v.IndexSetting() == ds.NoIndex { |
+ continue |
+ } |
+ data := ToBytes(v.ForIndex()) |
+ dataS := string(data) |
+ if !dups.Add(dataS) { |
+ continue |
+ } |
+ ret = append(ret, data) |
+ } |
+ return ret |
+} |
+ |
+// SerializedPmap maps from |
+// prop name -> [<serialized DSProperty>, ...] |
+// includes special values '__key__' and '__ancestor__' which contains all of |
+// the ancestor entries for this key. |
+type SerializedPmap map[string]SerializedPslice |
+ |
+// PropertyMapPartially turns a regular PropertyMap into a SerializedPmap. |
+// Essentially all the []Property's become SerializedPslice, using cmpbin and |
+// datastore/serialize's encodings. |
+func PropertyMapPartially(k *ds.Key, pm ds.PropertyMap) (ret SerializedPmap) { |
+ ret = make(SerializedPmap, len(pm)+2) |
+ if k != nil { |
+ ret["__key__"] = [][]byte{ToBytes(ds.MkProperty(k))} |
+ for k != nil { |
+ ret["__ancestor__"] = append(ret["__ancestor__"], ToBytes(ds.MkProperty(k))) |
+ k = k.Parent() |
+ } |
+ } |
+ for k, vals := range pm { |
+ newVals := PropertySlice(vals) |
+ if len(newVals) > 0 { |
+ ret[k] = newVals |
+ } |
+ } |
+ return |
+} |
+ |
func toBytesErr(i interface{}, ctx KeyContext) (ret []byte, err error) { |
buf := &bytes.Buffer{} |
switch x := i.(type) { |