OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be 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/serialize" | 14 "github.com/luci/gae/service/datastore/serialize" |
15 "github.com/luci/luci-go/common/data/cmpbin" | 15 "github.com/luci/luci-go/common/data/cmpbin" |
16 ) | 16 ) |
17 | 17 |
18 func init() { | 18 func init() { |
19 serializationDeterministic = true | 19 serializationDeterministic = true |
20 serialize.WritePropertyMapDeterministic = true | 20 serialize.WritePropertyMapDeterministic = true |
21 } | 21 } |
22 | 22 |
23 var nextMarker = "NEXT MARKER" | 23 var nextMarker = "NEXT MARKER" |
24 var Next = &nextMarker | 24 var Next = &nextMarker |
25 | 25 |
26 // Use like: | 26 var multiMarker = "MULTI MARKER" |
| 27 var Multi = &multiMarker |
| 28 |
| 29 // If you want an entry that is single to be treated as multi-, prepend it |
| 30 // with Multi. Terminate each set of property tokens with Next. |
27 // pmap( | 31 // pmap( |
28 // "prop", "val", 0, 100, Next, | 32 // "prop", "val", 0, 100, Next, |
29 // "other", "val", 0, 100, Next, | 33 // "other", "val", 0, 100, Next, |
| 34 // "name", Multi, "value", Next, |
30 // ) | 35 // ) |
31 // | 36 // |
| 37 // |
| 38 // |
32 func pmap(stuff ...interface{}) ds.PropertyMap { | 39 func pmap(stuff ...interface{}) ds.PropertyMap { |
33 ret := ds.PropertyMap{} | 40 ret := ds.PropertyMap{} |
34 | 41 |
35 » nom := func() interface{} { | 42 » nom := func() (name string, toks []interface{}, multi bool) { |
36 » » if len(stuff) > 0 { | 43 » » var i int |
37 » » » ret := stuff[0] | 44 |
38 » » » stuff = stuff[1:] | 45 » » for i = 0; i < len(stuff); i++ { |
39 » » » return ret | 46 » » » e := stuff[i] |
| 47 » » » switch { |
| 48 » » » case e == Next: |
| 49 » » » » stuff = stuff[i+1:] |
| 50 » » » » return |
| 51 » » » case e == Multi: |
| 52 » » » » multi = true |
| 53 » » » case i == 0: |
| 54 » » » » name = e.(string) |
| 55 » » » default: |
| 56 » » » » toks = append(toks, e) |
| 57 » » » } |
40 } | 58 } |
41 » » return nil | 59 |
| 60 » » stuff = nil |
| 61 » » return |
42 } | 62 } |
43 | 63 |
44 for len(stuff) > 0 { | 64 for len(stuff) > 0 { |
45 » » pname := nom().(string) | 65 » » pname, toks, multi := nom() |
| 66 |
| 67 » » var mp func(interface{}) ds.Property |
46 if pname[0] == '$' || (strings.HasPrefix(pname, "__") && strings
.HasSuffix(pname, "__")) { | 68 if pname[0] == '$' || (strings.HasPrefix(pname, "__") && strings
.HasSuffix(pname, "__")) { |
47 » » » for len(stuff) > 0 && stuff[0] != Next { | 69 » » » mp = propNI |
48 » » » » ret[pname] = append(ret[pname], propNI(nom())) | 70 » » } else { |
| 71 » » » mp = prop |
| 72 » » } |
| 73 |
| 74 » » if len(toks) == 1 && !multi { |
| 75 » » » ret[pname] = mp(toks[0]) |
| 76 » » } else { |
| 77 » » » pslice := make(ds.PropertySlice, len(toks)) |
| 78 » » » for i, tok := range toks { |
| 79 » » » » pslice[i] = mp(tok) |
49 } | 80 } |
50 » » } else { | 81 » » » ret[pname] = pslice |
51 » » » for len(stuff) > 0 && stuff[0] != Next { | |
52 » » » » ret[pname] = append(ret[pname], prop(nom())) | |
53 » » » } | |
54 } | 82 } |
55 nom() | |
56 } | 83 } |
57 | 84 |
58 return ret | 85 return ret |
59 } | 86 } |
60 | 87 |
61 func nq(kindMaybe ...string) *ds.Query { | 88 func nq(kindMaybe ...string) *ds.Query { |
62 kind := "Foo" | 89 kind := "Foo" |
63 if len(kindMaybe) == 1 { | 90 if len(kindMaybe) == 1 { |
64 kind = kindMaybe[0] | 91 kind = kindMaybe[0] |
65 } | 92 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 ret := cat(bytethings...) | 174 ret := cat(bytethings...) |
148 for i := range ret { | 175 for i := range ret { |
149 ret[i] ^= 0xFF | 176 ret[i] ^= 0xFF |
150 } | 177 } |
151 return ret | 178 return ret |
152 } | 179 } |
153 | 180 |
154 func sat(bytethings ...interface{}) string { | 181 func sat(bytethings ...interface{}) string { |
155 return string(cat(bytethings...)) | 182 return string(cat(bytethings...)) |
156 } | 183 } |
OLD | NEW |