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

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

Issue 1516173002: Fix error message from KeyForObj when passing an invalid struct. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: remove accidental extra test Created 5 years 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 package datastore 5 package datastore
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "reflect" 9 "reflect"
10 10
11 "github.com/luci/luci-go/common/errors" 11 "github.com/luci/luci-go/common/errors"
12 ) 12 )
13 13
14 type multiArgType struct { 14 type multiArgType struct {
15 valid bool
16
17 getKey func(aid, ns string, slot reflect.Value) (*Key, error) 15 getKey func(aid, ns string, slot reflect.Value) (*Key, error)
18 getPM func(slot reflect.Value) (PropertyMap, error) 16 getPM func(slot reflect.Value) (PropertyMap, error)
19 getMetaPM func(slot reflect.Value) PropertyMap 17 getMetaPM func(slot reflect.Value) PropertyMap
20 setPM func(slot reflect.Value, pm PropertyMap) error 18 setPM func(slot reflect.Value, pm PropertyMap) error
21 setKey func(slot reflect.Value, k *Key) 19 setKey func(slot reflect.Value, k *Key)
22 newElem func() reflect.Value 20 newElem func() reflect.Value
23 } 21 }
24 22
25 func (mat *multiArgType) GetKeysPMs(aid, ns string, slice reflect.Value, meta bo ol) ([]*Key, []PropertyMap, error) { 23 func (mat *multiArgType) GetKeysPMs(aid, ns string, slice reflect.Value, meta bo ol) ([]*Key, []PropertyMap, error) {
26 retKey := make([]*Key, slice.Len()) 24 retKey := make([]*Key, slice.Len())
(...skipping 16 matching lines...) Expand all
43 } 41 }
44 } 42 }
45 return retKey, retPM, lme.Get() 43 return retKey, retPM, lme.Get()
46 } 44 }
47 45
48 // parseMultiArg checks that v has type []S, []*S, []I, []P or []*P, for some 46 // parseMultiArg checks that v has type []S, []*S, []I, []P or []*P, for some
49 // struct type S, for some interface type I, or some non-interface non-pointer 47 // struct type S, for some interface type I, or some non-interface non-pointer
50 // type P such that P or *P implements PropertyLoadSaver. 48 // type P such that P or *P implements PropertyLoadSaver.
51 func parseMultiArg(e reflect.Type) multiArgType { 49 func parseMultiArg(e reflect.Type) multiArgType {
52 if e.Kind() != reflect.Slice { 50 if e.Kind() != reflect.Slice {
53 » » return multiArgTypeInvalid() 51 » » panic(fmt.Errorf("invalid argument type: expected slice, got %s" , e))
54 } 52 }
55 » return parseArg(e.Elem()) 53 » return parseArg(e.Elem(), true)
56 } 54 }
57 55
58 // parseArg checks that et is of type S, *S, I, P or *P, for some 56 // parseArg checks that et is of type S, *S, I, P or *P, for some
59 // struct type S, for some interface type I, or some non-interface non-pointer 57 // struct type S, for some interface type I, or some non-interface non-pointer
60 // type P such that P or *P implements PropertyLoadSaver. 58 // type P such that P or *P implements PropertyLoadSaver.
61 func parseArg(et reflect.Type) multiArgType { 59 func parseArg(et reflect.Type, multi bool) multiArgType {
62 if reflect.PtrTo(et).Implements(typeOfPropertyLoadSaver) { 60 if reflect.PtrTo(et).Implements(typeOfPropertyLoadSaver) {
63 return multiArgTypePLS(et) 61 return multiArgTypePLS(et)
64 } 62 }
65 if et.Implements(typeOfPropertyLoadSaver) && et.Kind() != reflect.Interf ace { 63 if et.Implements(typeOfPropertyLoadSaver) && et.Kind() != reflect.Interf ace {
66 return multiArgTypePLSPtr(et.Elem()) 64 return multiArgTypePLSPtr(et.Elem())
67 } 65 }
68 switch et.Kind() { 66 switch et.Kind() {
69 case reflect.Struct: 67 case reflect.Struct:
70 return multiArgTypeStruct(et) 68 return multiArgTypeStruct(et)
71 case reflect.Interface: 69 case reflect.Interface:
72 return multiArgTypeInterface() 70 return multiArgTypeInterface()
73 case reflect.Ptr: 71 case reflect.Ptr:
74 et = et.Elem() 72 et = et.Elem()
75 if et.Kind() == reflect.Struct { 73 if et.Kind() == reflect.Struct {
76 return multiArgTypeStructPtr(et) 74 return multiArgTypeStructPtr(et)
77 } 75 }
78 } 76 }
79 » return multiArgTypeInvalid() 77 » if multi {
78 » » panic(fmt.Errorf("invalid argument type: []%s", et))
79 » }
80 » panic(fmt.Errorf("invalid argument type: %s", et))
80 } 81 }
81 82
82 type newKeyFunc func(kind, sid string, iid int64, par Key) Key 83 type newKeyFunc func(kind, sid string, iid int64, par Key) Key
83 84
84 func multiArgTypeInvalid() multiArgType {
85 return multiArgType{}
86 }
87
88 // multiArgTypePLS == []P 85 // multiArgTypePLS == []P
89 // *P implements PropertyLoadSaver 86 // *P implements PropertyLoadSaver
90 func multiArgTypePLS(et reflect.Type) multiArgType { 87 func multiArgTypePLS(et reflect.Type) multiArgType {
91 ret := multiArgType{ 88 ret := multiArgType{
92 valid: true,
93
94 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { 89 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) {
95 return newKeyObjErr(aid, ns, slot.Addr().Interface()) 90 return newKeyObjErr(aid, ns, slot.Addr().Interface())
96 }, 91 },
97 getPM: func(slot reflect.Value) (PropertyMap, error) { 92 getPM: func(slot reflect.Value) (PropertyMap, error) {
98 return slot.Addr().Interface().(PropertyLoadSaver).Save( true) 93 return slot.Addr().Interface().(PropertyLoadSaver).Save( true)
99 }, 94 },
100 getMetaPM: func(slot reflect.Value) PropertyMap { 95 getMetaPM: func(slot reflect.Value) PropertyMap {
101 return getMGS(slot.Addr().Interface()).GetAllMeta() 96 return getMGS(slot.Addr().Interface()).GetAllMeta()
102 }, 97 },
103 setPM: func(slot reflect.Value, pm PropertyMap) error { 98 setPM: func(slot reflect.Value, pm PropertyMap) error {
(...skipping 17 matching lines...) Expand all
121 return reflect.New(et).Elem() 116 return reflect.New(et).Elem()
122 } 117 }
123 } 118 }
124 return ret 119 return ret
125 } 120 }
126 121
127 // multiArgTypePLSPtr == []*P 122 // multiArgTypePLSPtr == []*P
128 // *P implements PropertyLoadSaver 123 // *P implements PropertyLoadSaver
129 func multiArgTypePLSPtr(et reflect.Type) multiArgType { 124 func multiArgTypePLSPtr(et reflect.Type) multiArgType {
130 ret := multiArgType{ 125 ret := multiArgType{
131 valid: true,
132
133 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { 126 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) {
134 return newKeyObjErr(aid, ns, slot.Interface()) 127 return newKeyObjErr(aid, ns, slot.Interface())
135 }, 128 },
136 getPM: func(slot reflect.Value) (PropertyMap, error) { 129 getPM: func(slot reflect.Value) (PropertyMap, error) {
137 return slot.Interface().(PropertyLoadSaver).Save(true) 130 return slot.Interface().(PropertyLoadSaver).Save(true)
138 }, 131 },
139 getMetaPM: func(slot reflect.Value) PropertyMap { 132 getMetaPM: func(slot reflect.Value) PropertyMap {
140 return getMGS(slot.Interface()).GetAllMeta() 133 return getMGS(slot.Interface()).GetAllMeta()
141 }, 134 },
142 setPM: func(slot reflect.Value, pm PropertyMap) error { 135 setPM: func(slot reflect.Value, pm PropertyMap) error {
(...skipping 11 matching lines...) Expand all
154 } 147 }
155 } else { 148 } else {
156 ret.newElem = func() reflect.Value { return reflect.New(et) } 149 ret.newElem = func() reflect.Value { return reflect.New(et) }
157 } 150 }
158 return ret 151 return ret
159 } 152 }
160 153
161 // multiArgTypeStruct == []S 154 // multiArgTypeStruct == []S
162 func multiArgTypeStruct(et reflect.Type) multiArgType { 155 func multiArgTypeStruct(et reflect.Type) multiArgType {
163 cdc := getCodec(et) 156 cdc := getCodec(et)
164 if cdc.problem != nil {
165 return multiArgTypeInvalid()
166 }
167 toPLS := func(slot reflect.Value) *structPLS { 157 toPLS := func(slot reflect.Value) *structPLS {
168 return &structPLS{slot, cdc} 158 return &structPLS{slot, cdc}
169 } 159 }
170 return multiArgType{ 160 return multiArgType{
171 valid: true,
172
173 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { 161 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) {
174 return newKeyObjErr(aid, ns, toPLS(slot)) 162 return newKeyObjErr(aid, ns, toPLS(slot))
175 }, 163 },
176 getPM: func(slot reflect.Value) (PropertyMap, error) { 164 getPM: func(slot reflect.Value) (PropertyMap, error) {
177 return toPLS(slot).Save(true) 165 return toPLS(slot).Save(true)
178 }, 166 },
179 getMetaPM: func(slot reflect.Value) PropertyMap { 167 getMetaPM: func(slot reflect.Value) PropertyMap {
180 if slot.Type().Implements(typeOfMGS) { 168 if slot.Type().Implements(typeOfMGS) {
181 return slot.Interface().(MetaGetterSetter).GetAl lMeta() 169 return slot.Interface().(MetaGetterSetter).GetAl lMeta()
182 } 170 }
183 return toPLS(slot).GetAllMeta() 171 return toPLS(slot).GetAllMeta()
184 }, 172 },
185 setPM: func(slot reflect.Value, pm PropertyMap) error { 173 setPM: func(slot reflect.Value, pm PropertyMap) error {
186 return toPLS(slot).Load(pm) 174 return toPLS(slot).Load(pm)
187 }, 175 },
188 setKey: func(slot reflect.Value, k *Key) { 176 setKey: func(slot reflect.Value, k *Key) {
189 setKey(toPLS(slot), k) 177 setKey(toPLS(slot), k)
190 }, 178 },
191 newElem: func() reflect.Value { 179 newElem: func() reflect.Value {
192 return reflect.New(et).Elem() 180 return reflect.New(et).Elem()
193 }, 181 },
194 } 182 }
195 } 183 }
196 184
197 // multiArgTypeStructPtr == []*S 185 // multiArgTypeStructPtr == []*S
198 func multiArgTypeStructPtr(et reflect.Type) multiArgType { 186 func multiArgTypeStructPtr(et reflect.Type) multiArgType {
199 cdc := getCodec(et) 187 cdc := getCodec(et)
200 if cdc.problem != nil {
201 return multiArgTypeInvalid()
202 }
203 toPLS := func(slot reflect.Value) *structPLS { 188 toPLS := func(slot reflect.Value) *structPLS {
204 return &structPLS{slot.Elem(), cdc} 189 return &structPLS{slot.Elem(), cdc}
205 } 190 }
206 return multiArgType{ 191 return multiArgType{
207 valid: true,
208
209 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { 192 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) {
210 return newKeyObjErr(aid, ns, toPLS(slot)) 193 return newKeyObjErr(aid, ns, toPLS(slot))
211 }, 194 },
212 getPM: func(slot reflect.Value) (PropertyMap, error) { 195 getPM: func(slot reflect.Value) (PropertyMap, error) {
213 return toPLS(slot).Save(true) 196 return toPLS(slot).Save(true)
214 }, 197 },
215 getMetaPM: func(slot reflect.Value) PropertyMap { 198 getMetaPM: func(slot reflect.Value) PropertyMap {
216 if slot.Elem().Type().Implements(typeOfMGS) { 199 if slot.Elem().Type().Implements(typeOfMGS) {
217 return getMGS(slot.Interface()).GetAllMeta() 200 return getMGS(slot.Interface()).GetAllMeta()
218 } 201 }
219 return toPLS(slot).GetAllMeta() 202 return toPLS(slot).GetAllMeta()
220 }, 203 },
221 setPM: func(slot reflect.Value, pm PropertyMap) error { 204 setPM: func(slot reflect.Value, pm PropertyMap) error {
222 return toPLS(slot).Load(pm) 205 return toPLS(slot).Load(pm)
223 }, 206 },
224 setKey: func(slot reflect.Value, k *Key) { 207 setKey: func(slot reflect.Value, k *Key) {
225 setKey(toPLS(slot), k) 208 setKey(toPLS(slot), k)
226 }, 209 },
227 newElem: func() reflect.Value { 210 newElem: func() reflect.Value {
228 return reflect.New(et) 211 return reflect.New(et)
229 }, 212 },
230 } 213 }
231 } 214 }
232 215
233 // multiArgTypeInterface == []I 216 // multiArgTypeInterface == []I
234 func multiArgTypeInterface() multiArgType { 217 func multiArgTypeInterface() multiArgType {
235 return multiArgType{ 218 return multiArgType{
236 valid: true,
237
238 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { 219 getKey: func(aid, ns string, slot reflect.Value) (*Key, error) {
239 return newKeyObjErr(aid, ns, slot.Elem().Interface()) 220 return newKeyObjErr(aid, ns, slot.Elem().Interface())
240 }, 221 },
241 getPM: func(slot reflect.Value) (PropertyMap, error) { 222 getPM: func(slot reflect.Value) (PropertyMap, error) {
242 » » » pls := mkPLS(slot.Elem().Interface()) 223 » » » return mkPLS(slot.Elem().Interface()).Save(true)
243 » » » return pls.Save(true)
244 }, 224 },
245 getMetaPM: func(slot reflect.Value) PropertyMap { 225 getMetaPM: func(slot reflect.Value) PropertyMap {
246 » » » pls := getMGS(slot.Elem().Interface()) 226 » » » return getMGS(slot.Elem().Interface()).GetAllMeta()
247 » » » return pls.GetAllMeta()
248 }, 227 },
249 setPM: func(slot reflect.Value, pm PropertyMap) error { 228 setPM: func(slot reflect.Value, pm PropertyMap) error {
250 » » » pls := mkPLS(slot.Elem().Interface()) 229 » » » return mkPLS(slot.Elem().Interface()).Load(pm)
251 » » » return pls.Load(pm)
252 }, 230 },
253 setKey: func(slot reflect.Value, k *Key) { 231 setKey: func(slot reflect.Value, k *Key) {
254 setKey(slot.Elem().Interface(), k) 232 setKey(slot.Elem().Interface(), k)
255 }, 233 },
256 } 234 }
257 } 235 }
258 236
259 func newKeyObjErr(aid, ns string, src interface{}) (*Key, error) { 237 func newKeyObjErr(aid, ns string, src interface{}) (*Key, error) {
260 pls := getMGS(src) 238 pls := getMGS(src)
261 » if key, _ := pls.GetMetaDefault("key", nil).(*Key); key != nil { 239 » if key, _ := GetMetaDefault(pls, "key", nil).(*Key); key != nil {
262 return key, nil 240 return key, nil
263 } 241 }
264 242
265 // get kind 243 // get kind
266 » kind := pls.GetMetaDefault("kind", "").(string) 244 » kind := GetMetaDefault(pls, "kind", "").(string)
267 if kind == "" { 245 if kind == "" {
268 return nil, fmt.Errorf("unable to extract $kind from %T", src) 246 return nil, fmt.Errorf("unable to extract $kind from %T", src)
269 } 247 }
270 248
271 // get id - allow both to be default for default keys 249 // get id - allow both to be default for default keys
272 » sid := pls.GetMetaDefault("id", "").(string) 250 » sid := GetMetaDefault(pls, "id", "").(string)
273 » iid := pls.GetMetaDefault("id", 0).(int64) 251 » iid := GetMetaDefault(pls, "id", 0).(int64)
274 252
275 // get parent 253 // get parent
276 » par, _ := pls.GetMetaDefault("parent", nil).(*Key) 254 » par, _ := GetMetaDefault(pls, "parent", nil).(*Key)
277 255
278 return NewKey(aid, ns, kind, sid, iid, par), nil 256 return NewKey(aid, ns, kind, sid, iid, par), nil
279 } 257 }
280 258
281 func setKey(src interface{}, key *Key) { 259 func setKey(src interface{}, key *Key) {
282 pls := getMGS(src) 260 pls := getMGS(src)
283 » if pls.SetMeta("key", key) == ErrMetaFieldUnset { 261 » if !pls.SetMeta("key", key) {
284 lst := key.LastTok() 262 lst := key.LastTok()
285 if lst.StringID != "" { 263 if lst.StringID != "" {
286 » » » _ = pls.SetMeta("id", lst.StringID) 264 » » » pls.SetMeta("id", lst.StringID)
287 } else { 265 } else {
288 » » » _ = pls.SetMeta("id", lst.IntID) 266 » » » pls.SetMeta("id", lst.IntID)
289 } 267 }
290 » » _ = pls.SetMeta("kind", lst.Kind) 268 » » pls.SetMeta("kind", lst.Kind)
291 » » _ = pls.SetMeta("parent", key.Parent()) 269 » » pls.SetMeta("parent", key.Parent())
292 } 270 }
293 } 271 }
294 272
295 func mkPLS(o interface{}) PropertyLoadSaver { 273 func mkPLS(o interface{}) PropertyLoadSaver {
296 if pls, ok := o.(PropertyLoadSaver); ok { 274 if pls, ok := o.(PropertyLoadSaver); ok {
297 return pls 275 return pls
298 } 276 }
299 return GetPLS(o) 277 return GetPLS(o)
300 } 278 }
OLDNEW
« no previous file with comments | « service/datastore/errors.go ('k') | service/datastore/pls.go » ('j') | service/datastore/pls.go » ('J')

Powered by Google App Engine
This is Rietveld 408576698