Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: service/datastore/types.go

Issue 2011773002: datastore: variadic Get, Put, Exists, Delete. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gae@master
Patch Set: Update documentation and fix/clarify behavior on ExistsResult. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 //go:generate stringer -type=Toggle 5 //go:generate stringer -type=Toggle
6 6
7 package datastore 7 package datastore
8 8
9 // GeoPoint represents a location as latitude/longitude in degrees. 9 // GeoPoint represents a location as latitude/longitude in degrees.
10 // 10 //
(...skipping 29 matching lines...) Expand all
40 // Toggle is a tri-state boolean (Auto/True/False), which allows structs 40 // Toggle is a tri-state boolean (Auto/True/False), which allows structs
41 // to control boolean flags for metadata in a non-ambiguous way. 41 // to control boolean flags for metadata in a non-ambiguous way.
42 type Toggle byte 42 type Toggle byte
43 43
44 // These are the allowed values for Toggle. Any other values are invalid. 44 // These are the allowed values for Toggle. Any other values are invalid.
45 const ( 45 const (
46 Auto Toggle = iota 46 Auto Toggle = iota
47 On 47 On
48 Off 48 Off
49 ) 49 )
50
51 // BoolList is a convenience wrapper for []bool that provides summary methods
52 // for working with the list in aggregate.
53 type BoolList []bool
54
55 // All returns true iff all of the booleans in this list are true.
56 func (bl BoolList) All() bool {
57 for _, b := range bl {
58 if !b {
59 return false
60 }
61 }
62 return true
63 }
64
65 // Any returns true iff any of the booleans in this list are true.
66 func (bl BoolList) Any() bool {
67 for _, b := range bl {
68 if b {
69 return true
70 }
71 }
72 return false
73 }
74
75 // ExistsResult is a 2-dimensional boolean array that represents the existence
76 // of entries in the datastore. It is returned by the datastore Exists method.
77 // It is designed to accommodate the potentially-nested variadic arguments that
78 // can be passed to Exists.
79 //
80 // The first dimension contains one entry for each Exists input index. If the
81 // argument is a single entry, the boolean value at this index will be true if
82 // that argument was present in the datastore and false otherwise. If the
83 // argument is a slice, it will contain an aggregate value that is true iff no
84 // values in that slice were missing from the datastore.
85 //
86 // The second dimension presents a boolean slice for each input argument. Single
87 // arguments will have a slice of size 1 whose value corresponds to the first
88 // dimension value for that argument. Slice arguments have a slice of the same
89 // size. A given index in the second dimension slice is true iff the element at
90 // that index was present.
91 type ExistsResult struct {
92 // values is the first dimension aggregate values.
93 values BoolList
94 // slices is the set of second dimension positional values.
95 slices []BoolList
iannucci 2016/05/28 02:50:53 bitfield?
dnj 2016/05/28 17:47:21 IMO BoolList is more Go-friendly, since it actuall
96 }
97
98 func (r *ExistsResult) init(sizes ...int) {
99 // In order to reduce allocations, we allocate a single continuous boole an
100 // slice and then partition it up into first- and second-dimension slice s.
101 //
102 // To determine the size of the continuous slize, count the number of el ements
103 // that we'll need:
104 // - Single arguments and slice arguments with size 1 will have their
105 // second-dimension slice just point to their element in the first-dim ension
106 // slice.
107 // - Slice elements of size >1 will have their second-dimension slice ad ded to
108 // the end of the continuous slice. Their slice will be carved off in the
109 // subsequent loop.
110 //
111 // Consequently, we need one element for each argument, plus len(slice)
112 // additional elements for each slice argument of size >1.
113 count := len(sizes) // [0..n)
114 for _, s := range sizes {
115 if s > 1 {
116 count += s
117 }
118 }
119
120 // Allocate our continuous array and partition it into first- and
121 // second-dimension slices.
122 entries := make(BoolList, count)
123 r.values, entries = entries[:len(sizes)], entries[len(sizes):]
124 r.slices = make([]BoolList, len(sizes))
125 for i, s := range sizes {
126 switch {
127 case s <= 0:
128 break
129
130 case s == 1:
131 // Single-entry slice out of "entries".
132 r.slices[i] = r.values[i : i+1]
133
134 default:
135 r.slices[i], entries = entries[:s], entries[s:]
136 }
137 }
138 }
139
140 func (r *ExistsResult) set(i, j int) { r.slices[i][j] = true }
141
142 // updateSlices updates the top-level value for multi-dimensional elements based
143 // on their current values.
144 func (r *ExistsResult) updateSlices() {
145 for i, s := range r.slices {
146 // Zero-length slices will have a first-dimension true value, si nce they
147 // have no entries and first-dimension is true when there are no false
148 // entries.
149 r.values[i] = (len(s) == 0 || s.All())
150 }
151 }
152
153 // All returns true if all of the available boolean slots are true.
154 func (r *ExistsResult) All() bool { return r.values.All() }
155
156 // Any returns true if any of the boolean slots are true.
157 func (r *ExistsResult) Any() bool {
158 // We have to implement our own Any so zero-length slices don't count to wards
159 // our result.
160 for i, b := range r.values {
161 if b && len(r.slices[i]) > 0 {
162 return true
163 }
164 }
165 return false
166 }
167
168 // Get returns the boolean value at the specified index.
169 //
170 // The one-argument form returns the first-dimension boolean. If i is a slice
171 // argument, this will be true iff all of the slice's booleans are true.
172 //
173 // An optional second argument can be passed to access a specific boolean value
174 // in slice i. If the argument at i is a single argument, the only valid index,
175 // 0, will be the same as calling the single-argument Get.
176 //
177 // Passing more than one additional argument will result in a panic.
178 func (r *ExistsResult) Get(i int, j ...int) bool {
179 switch len(j) {
180 case 0:
181 return r.values[i]
182 case 1:
183 return r.slices[i][j[0]]
184 default:
185 panic("this method takes one or two arguments")
186 }
187 }
188
189 // List returns the BoolList for the given argument index.
190 //
191 // The zero-argument form returns the first-dimension boolean list.
192 //
193 // An optional argument can be passed to access a specific argument's boolean
194 // slice. If the argument at i is a non-slice argument, the list will be a slice
195 // of size 1 containing i's first-dimension value.
196 //
197 // Passing more than one argument will result in a panic.
198 func (r *ExistsResult) List(i ...int) BoolList {
199 switch len(i) {
200 case 0:
201 return r.values
202 case 1:
203 return r.slices[i[0]]
204 default:
205 panic("this method takes zero or one arguments")
206 }
207 }
208
209 // Len returns the number of boolean results available.
210 //
211 // The zero-argument form returns the first-dimension size, which will equal the
212 // total number of arguments passed to Exists.
213 //
214 // The one-argument form returns the number of booleans in the slice for
215 // argument i.
216 //
217 // Passing more than one argument will result in a panic.
218 func (r *ExistsResult) Len(i ...int) int {
219 switch len(i) {
220 case 0:
221 return len(r.values)
222 case 1:
223 return len(r.slices[i[0]])
224 default:
225 panic("this method takes zero or one arguments")
226 }
227 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698