| 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 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 | 15 valid bool |
| 16 | 16 |
| 17 » getKey func(nk newKeyFunc, slot reflect.Value) (Key, error) | 17 » getKey func(aid, ns string, slot reflect.Value) (*Key, error) |
| 18 getPM func(slot reflect.Value) (PropertyMap, error) | 18 getPM func(slot reflect.Value) (PropertyMap, error) |
| 19 setPM func(slot reflect.Value, pm PropertyMap) error | 19 setPM func(slot reflect.Value, pm PropertyMap) error |
| 20 » setKey func(slot reflect.Value, k Key) | 20 » setKey func(slot reflect.Value, k *Key) |
| 21 newElem func() reflect.Value | 21 newElem func() reflect.Value |
| 22 } | 22 } |
| 23 | 23 |
| 24 func (mat *multiArgType) GetKeysPMs(nk newKeyFunc, slice reflect.Value) ([]Key,
[]PropertyMap, error) { | 24 func (mat *multiArgType) GetKeysPMs(aid, ns string, slice reflect.Value) ([]*Key
, []PropertyMap, error) { |
| 25 » retKey := make([]Key, slice.Len()) | 25 » retKey := make([]*Key, slice.Len()) |
| 26 retPM := make([]PropertyMap, slice.Len()) | 26 retPM := make([]PropertyMap, slice.Len()) |
| 27 lme := errors.NewLazyMultiError(len(retKey)) | 27 lme := errors.NewLazyMultiError(len(retKey)) |
| 28 for i := range retKey { | 28 for i := range retKey { |
| 29 » » key, err := mat.getKey(nk, slice.Index(i)) | 29 » » key, err := mat.getKey(aid, ns, slice.Index(i)) |
| 30 if !lme.Assign(i, err) { | 30 if !lme.Assign(i, err) { |
| 31 retKey[i] = key | 31 retKey[i] = key |
| 32 pm, err := mat.getPM(slice.Index(i)) | 32 pm, err := mat.getPM(slice.Index(i)) |
| 33 if !lme.Assign(i, err) { | 33 if !lme.Assign(i, err) { |
| 34 retPM[i] = pm | 34 retPM[i] = pm |
| 35 } | 35 } |
| 36 } | 36 } |
| 37 } | 37 } |
| 38 return retKey, retPM, lme.Get() | 38 return retKey, retPM, lme.Get() |
| 39 } | 39 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 func multiArgTypeInvalid() multiArgType { | 77 func multiArgTypeInvalid() multiArgType { |
| 78 return multiArgType{} | 78 return multiArgType{} |
| 79 } | 79 } |
| 80 | 80 |
| 81 // multiArgTypePLS == []P | 81 // multiArgTypePLS == []P |
| 82 // *P implements PropertyLoadSaver | 82 // *P implements PropertyLoadSaver |
| 83 func multiArgTypePLS(et reflect.Type) multiArgType { | 83 func multiArgTypePLS(et reflect.Type) multiArgType { |
| 84 ret := multiArgType{ | 84 ret := multiArgType{ |
| 85 valid: true, | 85 valid: true, |
| 86 | 86 |
| 87 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 87 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
| 88 » » » return newKeyObjErr(nk, slot.Addr().Interface()) | 88 » » » return newKeyObjErr(aid, ns, slot.Addr().Interface()) |
| 89 }, | 89 }, |
| 90 getPM: func(slot reflect.Value) (PropertyMap, error) { | 90 getPM: func(slot reflect.Value) (PropertyMap, error) { |
| 91 return slot.Addr().Interface().(PropertyLoadSaver).Save(
true) | 91 return slot.Addr().Interface().(PropertyLoadSaver).Save(
true) |
| 92 }, | 92 }, |
| 93 setPM: func(slot reflect.Value, pm PropertyMap) error { | 93 setPM: func(slot reflect.Value, pm PropertyMap) error { |
| 94 return slot.Addr().Interface().(PropertyLoadSaver).Load(
pm) | 94 return slot.Addr().Interface().(PropertyLoadSaver).Load(
pm) |
| 95 }, | 95 }, |
| 96 » » setKey: func(slot reflect.Value, k Key) { | 96 » » setKey: func(slot reflect.Value, k *Key) { |
| 97 setKey(slot.Addr().Interface(), k) | 97 setKey(slot.Addr().Interface(), k) |
| 98 }, | 98 }, |
| 99 } | 99 } |
| 100 if et.Kind() == reflect.Map { | 100 if et.Kind() == reflect.Map { |
| 101 ret.newElem = func() reflect.Value { | 101 ret.newElem = func() reflect.Value { |
| 102 // Create a *map so that way slot.Addr() works above whe
n this is | 102 // Create a *map so that way slot.Addr() works above whe
n this is |
| 103 // called from Run(). Otherwise the map is 'unaddressabl
e' according | 103 // called from Run(). Otherwise the map is 'unaddressabl
e' according |
| 104 // to reflect. ¯\_(ツ)_/¯ | 104 // to reflect. ¯\_(ツ)_/¯ |
| 105 ptr := reflect.New(et) | 105 ptr := reflect.New(et) |
| 106 ptr.Elem().Set(reflect.MakeMap(et)) | 106 ptr.Elem().Set(reflect.MakeMap(et)) |
| 107 return ptr.Elem() | 107 return ptr.Elem() |
| 108 } | 108 } |
| 109 } else { | 109 } else { |
| 110 ret.newElem = func() reflect.Value { | 110 ret.newElem = func() reflect.Value { |
| 111 return reflect.New(et).Elem() | 111 return reflect.New(et).Elem() |
| 112 } | 112 } |
| 113 } | 113 } |
| 114 return ret | 114 return ret |
| 115 } | 115 } |
| 116 | 116 |
| 117 // multiArgTypePLSPtr == []*P | 117 // multiArgTypePLSPtr == []*P |
| 118 // *P implements PropertyLoadSaver | 118 // *P implements PropertyLoadSaver |
| 119 func multiArgTypePLSPtr(et reflect.Type) multiArgType { | 119 func multiArgTypePLSPtr(et reflect.Type) multiArgType { |
| 120 ret := multiArgType{ | 120 ret := multiArgType{ |
| 121 valid: true, | 121 valid: true, |
| 122 | 122 |
| 123 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 123 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
| 124 » » » return newKeyObjErr(nk, slot.Interface()) | 124 » » » return newKeyObjErr(aid, ns, slot.Interface()) |
| 125 }, | 125 }, |
| 126 getPM: func(slot reflect.Value) (PropertyMap, error) { | 126 getPM: func(slot reflect.Value) (PropertyMap, error) { |
| 127 return slot.Interface().(PropertyLoadSaver).Save(true) | 127 return slot.Interface().(PropertyLoadSaver).Save(true) |
| 128 }, | 128 }, |
| 129 setPM: func(slot reflect.Value, pm PropertyMap) error { | 129 setPM: func(slot reflect.Value, pm PropertyMap) error { |
| 130 return slot.Interface().(PropertyLoadSaver).Load(pm) | 130 return slot.Interface().(PropertyLoadSaver).Load(pm) |
| 131 }, | 131 }, |
| 132 » » setKey: func(slot reflect.Value, k Key) { | 132 » » setKey: func(slot reflect.Value, k *Key) { |
| 133 setKey(slot.Interface(), k) | 133 setKey(slot.Interface(), k) |
| 134 }, | 134 }, |
| 135 } | 135 } |
| 136 if et.Kind() == reflect.Map { | 136 if et.Kind() == reflect.Map { |
| 137 ret.newElem = func() reflect.Value { | 137 ret.newElem = func() reflect.Value { |
| 138 ptr := reflect.New(et) | 138 ptr := reflect.New(et) |
| 139 ptr.Elem().Set(reflect.MakeMap(et)) | 139 ptr.Elem().Set(reflect.MakeMap(et)) |
| 140 return ptr | 140 return ptr |
| 141 } | 141 } |
| 142 } else { | 142 } else { |
| 143 ret.newElem = func() reflect.Value { return reflect.New(et) } | 143 ret.newElem = func() reflect.Value { return reflect.New(et) } |
| 144 } | 144 } |
| 145 return ret | 145 return ret |
| 146 } | 146 } |
| 147 | 147 |
| 148 // multiArgTypeStruct == []S | 148 // multiArgTypeStruct == []S |
| 149 func multiArgTypeStruct(et reflect.Type) multiArgType { | 149 func multiArgTypeStruct(et reflect.Type) multiArgType { |
| 150 cdc := getCodec(et) | 150 cdc := getCodec(et) |
| 151 if cdc.problem != nil { | 151 if cdc.problem != nil { |
| 152 return multiArgTypeInvalid() | 152 return multiArgTypeInvalid() |
| 153 } | 153 } |
| 154 toPLS := func(slot reflect.Value) PropertyLoadSaver { | 154 toPLS := func(slot reflect.Value) PropertyLoadSaver { |
| 155 return &structPLS{slot, cdc} | 155 return &structPLS{slot, cdc} |
| 156 } | 156 } |
| 157 return multiArgType{ | 157 return multiArgType{ |
| 158 valid: true, | 158 valid: true, |
| 159 | 159 |
| 160 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 160 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
| 161 » » » return newKeyObjErr(nk, toPLS(slot)) | 161 » » » return newKeyObjErr(aid, ns, toPLS(slot)) |
| 162 }, | 162 }, |
| 163 getPM: func(slot reflect.Value) (PropertyMap, error) { | 163 getPM: func(slot reflect.Value) (PropertyMap, error) { |
| 164 return toPLS(slot).(PropertyLoadSaver).Save(true) | 164 return toPLS(slot).(PropertyLoadSaver).Save(true) |
| 165 }, | 165 }, |
| 166 setPM: func(slot reflect.Value, pm PropertyMap) error { | 166 setPM: func(slot reflect.Value, pm PropertyMap) error { |
| 167 return toPLS(slot).(PropertyLoadSaver).Load(pm) | 167 return toPLS(slot).(PropertyLoadSaver).Load(pm) |
| 168 }, | 168 }, |
| 169 » » setKey: func(slot reflect.Value, k Key) { | 169 » » setKey: func(slot reflect.Value, k *Key) { |
| 170 setKey(toPLS(slot), k) | 170 setKey(toPLS(slot), k) |
| 171 }, | 171 }, |
| 172 newElem: func() reflect.Value { | 172 newElem: func() reflect.Value { |
| 173 return reflect.New(et).Elem() | 173 return reflect.New(et).Elem() |
| 174 }, | 174 }, |
| 175 } | 175 } |
| 176 } | 176 } |
| 177 | 177 |
| 178 // multiArgTypeStructPtr == []*S | 178 // multiArgTypeStructPtr == []*S |
| 179 func multiArgTypeStructPtr(et reflect.Type) multiArgType { | 179 func multiArgTypeStructPtr(et reflect.Type) multiArgType { |
| 180 cdc := getCodec(et) | 180 cdc := getCodec(et) |
| 181 if cdc.problem != nil { | 181 if cdc.problem != nil { |
| 182 return multiArgTypeInvalid() | 182 return multiArgTypeInvalid() |
| 183 } | 183 } |
| 184 toPLS := func(slot reflect.Value) PropertyLoadSaver { | 184 toPLS := func(slot reflect.Value) PropertyLoadSaver { |
| 185 return &structPLS{slot.Elem(), cdc} | 185 return &structPLS{slot.Elem(), cdc} |
| 186 } | 186 } |
| 187 return multiArgType{ | 187 return multiArgType{ |
| 188 valid: true, | 188 valid: true, |
| 189 | 189 |
| 190 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 190 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
| 191 » » » return newKeyObjErr(nk, toPLS(slot)) | 191 » » » return newKeyObjErr(aid, ns, toPLS(slot)) |
| 192 }, | 192 }, |
| 193 getPM: func(slot reflect.Value) (PropertyMap, error) { | 193 getPM: func(slot reflect.Value) (PropertyMap, error) { |
| 194 return toPLS(slot).(PropertyLoadSaver).Save(true) | 194 return toPLS(slot).(PropertyLoadSaver).Save(true) |
| 195 }, | 195 }, |
| 196 setPM: func(slot reflect.Value, pm PropertyMap) error { | 196 setPM: func(slot reflect.Value, pm PropertyMap) error { |
| 197 return toPLS(slot).(PropertyLoadSaver).Load(pm) | 197 return toPLS(slot).(PropertyLoadSaver).Load(pm) |
| 198 }, | 198 }, |
| 199 » » setKey: func(slot reflect.Value, k Key) { | 199 » » setKey: func(slot reflect.Value, k *Key) { |
| 200 setKey(toPLS(slot), k) | 200 setKey(toPLS(slot), k) |
| 201 }, | 201 }, |
| 202 newElem: func() reflect.Value { | 202 newElem: func() reflect.Value { |
| 203 return reflect.New(et) | 203 return reflect.New(et) |
| 204 }, | 204 }, |
| 205 } | 205 } |
| 206 } | 206 } |
| 207 | 207 |
| 208 // multiArgTypeInterface == []I | 208 // multiArgTypeInterface == []I |
| 209 func multiArgTypeInterface() multiArgType { | 209 func multiArgTypeInterface() multiArgType { |
| 210 return multiArgType{ | 210 return multiArgType{ |
| 211 valid: true, | 211 valid: true, |
| 212 | 212 |
| 213 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 213 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
| 214 » » » return newKeyObjErr(nk, slot.Elem().Interface()) | 214 » » » return newKeyObjErr(aid, ns, slot.Elem().Interface()) |
| 215 }, | 215 }, |
| 216 getPM: func(slot reflect.Value) (PropertyMap, error) { | 216 getPM: func(slot reflect.Value) (PropertyMap, error) { |
| 217 pls := mkPLS(slot.Elem().Interface()) | 217 pls := mkPLS(slot.Elem().Interface()) |
| 218 return pls.Save(true) | 218 return pls.Save(true) |
| 219 }, | 219 }, |
| 220 setPM: func(slot reflect.Value, pm PropertyMap) error { | 220 setPM: func(slot reflect.Value, pm PropertyMap) error { |
| 221 pls := mkPLS(slot.Elem().Interface()) | 221 pls := mkPLS(slot.Elem().Interface()) |
| 222 return pls.Load(pm) | 222 return pls.Load(pm) |
| 223 }, | 223 }, |
| 224 » » setKey: func(slot reflect.Value, k Key) { | 224 » » setKey: func(slot reflect.Value, k *Key) { |
| 225 setKey(slot.Elem().Interface(), k) | 225 setKey(slot.Elem().Interface(), k) |
| 226 }, | 226 }, |
| 227 } | 227 } |
| 228 } | 228 } |
| 229 | 229 |
| 230 func newKeyObjErr(nk newKeyFunc, src interface{}) (Key, error) { | 230 func newKeyObjErr(aid, ns string, src interface{}) (*Key, error) { |
| 231 pls := mkPLS(src) | 231 pls := mkPLS(src) |
| 232 » if key, _ := pls.GetMetaDefault("key", nil).(Key); key != nil { | 232 » if key, _ := pls.GetMetaDefault("key", nil).(*Key); key != nil { |
| 233 return key, nil | 233 return key, nil |
| 234 } | 234 } |
| 235 | 235 |
| 236 // get kind | 236 // get kind |
| 237 kind := pls.GetMetaDefault("kind", "").(string) | 237 kind := pls.GetMetaDefault("kind", "").(string) |
| 238 if kind == "" { | 238 if kind == "" { |
| 239 return nil, fmt.Errorf("unable to extract $kind from %T", src) | 239 return nil, fmt.Errorf("unable to extract $kind from %T", src) |
| 240 } | 240 } |
| 241 | 241 |
| 242 // get id - allow both to be default for default keys | 242 // get id - allow both to be default for default keys |
| 243 sid := pls.GetMetaDefault("id", "").(string) | 243 sid := pls.GetMetaDefault("id", "").(string) |
| 244 iid := pls.GetMetaDefault("id", 0).(int64) | 244 iid := pls.GetMetaDefault("id", 0).(int64) |
| 245 | 245 |
| 246 // get parent | 246 // get parent |
| 247 » par, _ := pls.GetMetaDefault("parent", nil).(Key) | 247 » par, _ := pls.GetMetaDefault("parent", nil).(*Key) |
| 248 | 248 |
| 249 » return nk(kind, sid, iid, par), nil | 249 » return NewKey(aid, ns, kind, sid, iid, par), nil |
| 250 } | 250 } |
| 251 | 251 |
| 252 func setKey(src interface{}, key Key) { | 252 func setKey(src interface{}, key *Key) { |
| 253 pls := mkPLS(src) | 253 pls := mkPLS(src) |
| 254 if pls.SetMeta("key", key) == ErrMetaFieldUnset { | 254 if pls.SetMeta("key", key) == ErrMetaFieldUnset { |
| 255 » » if key.StringID() != "" { | 255 » » lst := key.Last() |
| 256 » » » pls.SetMeta("id", key.StringID()) | 256 » » if lst.StringID != "" { |
| 257 » » » _ = pls.SetMeta("id", lst.StringID) |
| 257 } else { | 258 } else { |
| 258 » » » pls.SetMeta("id", key.IntID()) | 259 » » » _ = pls.SetMeta("id", lst.IntID) |
| 259 } | 260 } |
| 260 » » pls.SetMeta("kind", key.Kind()) | 261 » » _ = pls.SetMeta("kind", lst.Kind) |
| 261 » » pls.SetMeta("parent", key.Parent()) | 262 » » _ = pls.SetMeta("parent", key.Parent()) |
| 262 } | 263 } |
| 263 } | 264 } |
| 264 | 265 |
| 265 func mkPLS(o interface{}) PropertyLoadSaver { | 266 func mkPLS(o interface{}) PropertyLoadSaver { |
| 266 if pls, ok := o.(PropertyLoadSaver); ok { | 267 if pls, ok := o.(PropertyLoadSaver); ok { |
| 267 return pls | 268 return pls |
| 268 } | 269 } |
| 269 return GetPLS(o) | 270 return GetPLS(o) |
| 270 } | 271 } |
| OLD | NEW |