| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package memory | 5 package memory |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "fmt" | 9 "fmt" |
| 10 "strings" | 10 "strings" |
| 11 "time" | 11 "time" |
| 12 | 12 |
| 13 ds "github.com/luci/gae/service/datastore" | 13 ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/gae/service/datastore/dskey" | |
| 15 "github.com/luci/gae/service/datastore/serialize" | 14 "github.com/luci/gae/service/datastore/serialize" |
| 16 "github.com/luci/luci-go/common/cmpbin" | 15 "github.com/luci/luci-go/common/cmpbin" |
| 17 ) | 16 ) |
| 18 | 17 |
| 19 func init() { | 18 func init() { |
| 20 serializationDeterministic = true | 19 serializationDeterministic = true |
| 21 serialize.WritePropertyMapDeterministic = true | 20 serialize.WritePropertyMapDeterministic = true |
| 22 } | 21 } |
| 23 | 22 |
| 24 var NEXT_STR = "NEXT MARKER" | 23 var nextMarker = "NEXT MARKER" |
| 25 var NEXT = &NEXT_STR | 24 var Next = &nextMarker |
| 26 | 25 |
| 27 // Use like: | 26 // Use like: |
| 28 // pmap( | 27 // pmap( |
| 29 // "prop", "val", 0, 100, NEXT, | 28 // "prop", "val", 0, 100, Next, |
| 30 // "other", "val", 0, 100, NEXT, | 29 // "other", "val", 0, 100, Next, |
| 31 // ) | 30 // ) |
| 32 // | 31 // |
| 33 func pmap(stuff ...interface{}) ds.PropertyMap { | 32 func pmap(stuff ...interface{}) ds.PropertyMap { |
| 34 ret := ds.PropertyMap{} | 33 ret := ds.PropertyMap{} |
| 35 | 34 |
| 36 nom := func() interface{} { | 35 nom := func() interface{} { |
| 37 if len(stuff) > 0 { | 36 if len(stuff) > 0 { |
| 38 ret := stuff[0] | 37 ret := stuff[0] |
| 39 stuff = stuff[1:] | 38 stuff = stuff[1:] |
| 40 return ret | 39 return ret |
| 41 } | 40 } |
| 42 return nil | 41 return nil |
| 43 } | 42 } |
| 44 | 43 |
| 45 for len(stuff) > 0 { | 44 for len(stuff) > 0 { |
| 46 pname := nom().(string) | 45 pname := nom().(string) |
| 47 if pname[0] == '$' || (strings.HasPrefix(pname, "__") && strings
.HasSuffix(pname, "__")) { | 46 if pname[0] == '$' || (strings.HasPrefix(pname, "__") && strings
.HasSuffix(pname, "__")) { |
| 48 » » » for len(stuff) > 0 && stuff[0] != NEXT { | 47 » » » for len(stuff) > 0 && stuff[0] != Next { |
| 49 ret[pname] = append(ret[pname], propNI(nom())) | 48 ret[pname] = append(ret[pname], propNI(nom())) |
| 50 } | 49 } |
| 51 } else { | 50 } else { |
| 52 » » » for len(stuff) > 0 && stuff[0] != NEXT { | 51 » » » for len(stuff) > 0 && stuff[0] != Next { |
| 53 ret[pname] = append(ret[pname], prop(nom())) | 52 ret[pname] = append(ret[pname], prop(nom())) |
| 54 } | 53 } |
| 55 } | 54 } |
| 56 nom() | 55 nom() |
| 57 } | 56 } |
| 58 | 57 |
| 59 return ret | 58 return ret |
| 60 } | 59 } |
| 61 | 60 |
| 62 func nq(kind_ns ...string) ds.Query { | 61 func nq(kindMaybe ...string) *ds.Query { |
| 63 » if len(kind_ns) == 2 { | 62 » kind := "Foo" |
| 64 » » return &queryImpl{kind: kind_ns[0], ns: kind_ns[1]} | 63 » if len(kindMaybe) == 1 { |
| 65 » } else if len(kind_ns) == 1 { | 64 » » kind = kindMaybe[0] |
| 66 » » return &queryImpl{kind: kind_ns[0], ns: "ns"} | |
| 67 } | 65 } |
| 68 » return &queryImpl{kind: "Foo", ns: "ns"} | 66 » return ds.NewQuery(kind) |
| 69 } | 67 } |
| 70 | 68 |
| 71 func indx(kind string, orders ...string) *ds.IndexDefinition { | 69 func indx(kind string, orders ...string) *ds.IndexDefinition { |
| 72 ancestor := false | 70 ancestor := false |
| 73 if kind[len(kind)-1] == '!' { | 71 if kind[len(kind)-1] == '!' { |
| 74 ancestor = true | 72 ancestor = true |
| 75 kind = kind[:len(kind)-1] | 73 kind = kind[:len(kind)-1] |
| 76 } | 74 } |
| 77 ret := &ds.IndexDefinition{Kind: kind, Ancestor: ancestor} | 75 ret := &ds.IndexDefinition{Kind: kind, Ancestor: ancestor} |
| 78 for _, o := range orders { | 76 for _, o := range orders { |
| 79 » » dir := ds.ASCENDING | 77 » » col, err := ds.ParseIndexColumn(o) |
| 80 » » if o[0] == '-' { | 78 » » if err != nil { |
| 81 » » » dir = ds.DESCENDING | 79 » » » panic(err) |
| 82 » » » o = o[1:] | |
| 83 } | 80 } |
| 84 » » ret.SortBy = append(ret.SortBy, ds.IndexColumn{Property: o, Dire
ction: dir}) | 81 » » ret.SortBy = append(ret.SortBy, col) |
| 85 } | 82 } |
| 86 return ret | 83 return ret |
| 87 } | 84 } |
| 88 | 85 |
| 89 var ( | 86 var ( |
| 90 prop = ds.MkProperty | 87 prop = ds.MkProperty |
| 91 propNI = ds.MkPropertyNI | 88 propNI = ds.MkPropertyNI |
| 92 ) | 89 ) |
| 93 | 90 |
| 94 func key(kind string, id interface{}, parent ...ds.Key) ds.Key { | 91 func key(elems ...interface{}) *ds.Key { |
| 95 » p := ds.Key(nil) | 92 » return ds.MakeKey(globalAppID, "ns", elems...) |
| 96 » if len(parent) > 0 { | 93 } |
| 97 » » p = parent[0] | 94 |
| 98 » } | 95 func die(err error) { |
| 99 » switch x := id.(type) { | 96 » if err != nil { |
| 100 » case string: | 97 » » panic(err) |
| 101 » » return dskey.New(globalAppID, "ns", kind, x, 0, p) | |
| 102 » case int: | |
| 103 » » return dskey.New(globalAppID, "ns", kind, "", int64(x), p) | |
| 104 » default: | |
| 105 » » return dskey.New(globalAppID, "ns", kind, "invalid", 100, p) | |
| 106 } | 98 } |
| 107 } | 99 } |
| 108 | 100 |
| 109 // cat is a convenience method for concatenating anything with an underlying | 101 // cat is a convenience method for concatenating anything with an underlying |
| 110 // byte representation into a single []byte. | 102 // byte representation into a single []byte. |
| 111 func cat(bytethings ...interface{}) []byte { | 103 func cat(bytethings ...interface{}) []byte { |
| 104 err := error(nil) |
| 112 buf := &bytes.Buffer{} | 105 buf := &bytes.Buffer{} |
| 113 for _, thing := range bytethings { | 106 for _, thing := range bytethings { |
| 114 switch x := thing.(type) { | 107 switch x := thing.(type) { |
| 115 case int64: | 108 case int64: |
| 116 » » » cmpbin.WriteInt(buf, x) | 109 » » » _, err = cmpbin.WriteInt(buf, x) |
| 117 case int: | 110 case int: |
| 118 » » » cmpbin.WriteInt(buf, int64(x)) | 111 » » » _, err = cmpbin.WriteInt(buf, int64(x)) |
| 119 case uint64: | 112 case uint64: |
| 120 » » » cmpbin.WriteUint(buf, x) | 113 » » » _, err = cmpbin.WriteUint(buf, x) |
| 121 case uint: | 114 case uint: |
| 122 » » » cmpbin.WriteUint(buf, uint64(x)) | 115 » » » _, err = cmpbin.WriteUint(buf, uint64(x)) |
| 123 case float64: | 116 case float64: |
| 124 » » » cmpbin.WriteFloat64(buf, x) | 117 » » » _, err = cmpbin.WriteFloat64(buf, x) |
| 125 case byte: | 118 case byte: |
| 126 » » » buf.WriteByte(x) | 119 » » » err = buf.WriteByte(x) |
| 127 case ds.PropertyType: | 120 case ds.PropertyType: |
| 128 » » » buf.WriteByte(byte(x)) | 121 » » » err = buf.WriteByte(byte(x)) |
| 129 case string: | 122 case string: |
| 130 » » » cmpbin.WriteString(buf, x) | 123 » » » _, err = cmpbin.WriteString(buf, x) |
| 131 case []byte: | 124 case []byte: |
| 132 » » » buf.Write(x) | 125 » » » _, err = buf.Write(x) |
| 133 case time.Time: | 126 case time.Time: |
| 134 » » » serialize.WriteTime(buf, x) | 127 » » » err = serialize.WriteTime(buf, x) |
| 135 » » case ds.Key: | 128 » » case *ds.Key: |
| 136 » » » serialize.WriteKey(buf, serialize.WithoutContext, x) | 129 » » » err = serialize.WriteKey(buf, serialize.WithoutContext,
x) |
| 137 case *ds.IndexDefinition: | 130 case *ds.IndexDefinition: |
| 138 » » » serialize.WriteIndexDefinition(buf, *x) | 131 » » » err = serialize.WriteIndexDefinition(buf, *x) |
| 139 case ds.Property: | 132 case ds.Property: |
| 140 » » » serialize.WriteProperty(buf, serialize.WithoutContext, x
) | 133 » » » err = serialize.WriteProperty(buf, serialize.WithoutCont
ext, x) |
| 141 default: | 134 default: |
| 142 panic(fmt.Errorf("I don't know how to deal with %T: %#v"
, thing, thing)) | 135 panic(fmt.Errorf("I don't know how to deal with %T: %#v"
, thing, thing)) |
| 143 } | 136 } |
| 137 die(err) |
| 144 } | 138 } |
| 145 ret := buf.Bytes() | 139 ret := buf.Bytes() |
| 146 if ret == nil { | 140 if ret == nil { |
| 147 ret = []byte{} | 141 ret = []byte{} |
| 148 } | 142 } |
| 149 return ret | 143 return ret |
| 150 } | 144 } |
| 151 | 145 |
| 152 func icat(bytethings ...interface{}) []byte { | 146 func icat(bytethings ...interface{}) []byte { |
| 153 ret := cat(bytethings...) | 147 ret := cat(bytethings...) |
| 154 for i := range ret { | 148 for i := range ret { |
| 155 ret[i] ^= 0xFF | 149 ret[i] ^= 0xFF |
| 156 } | 150 } |
| 157 return ret | 151 return ret |
| 158 } | 152 } |
| 159 | 153 |
| 160 func sat(bytethings ...interface{}) string { | 154 func sat(bytethings ...interface{}) string { |
| 161 return string(cat(bytethings...)) | 155 return string(cat(bytethings...)) |
| 162 } | 156 } |
| OLD | NEW |