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 "errors" | 8 "errors" |
9 "fmt" | 9 "fmt" |
10 "math" | 10 "math" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 } | 217 } |
218 return PTGeoPoint, err | 218 return PTGeoPoint, err |
219 default: | 219 default: |
220 return PTUnknown, fmt.Errorf("gae: Property has bad type %T", v) | 220 return PTUnknown, fmt.Errorf("gae: Property has bad type %T", v) |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 // UpconvertUnderlyingType takes an object o, and attempts to convert it to | 224 // UpconvertUnderlyingType takes an object o, and attempts to convert it to |
225 // its native datastore-compatible type. e.g. int16 will convert to int64, and | 225 // its native datastore-compatible type. e.g. int16 will convert to int64, and |
226 // `type Foo string` will convert to `string`. | 226 // `type Foo string` will convert to `string`. |
227 func UpconvertUnderlyingType(o interface{}, t reflect.Type) (interface{}, reflec t.Type) { | 227 func UpconvertUnderlyingType(o interface{}, t reflect.Type) (interface{}, reflec t.Type) { |
dnj
2015/08/05 00:38:41
Is this used elsewhere? What's the point of taking
iannucci
2015/08/05 00:58:14
Yes, it's used in Property.SetValue. That said, th
| |
228 if o == nil { | |
229 return o, t | |
230 } | |
231 | |
228 v := reflect.ValueOf(o) | 232 v := reflect.ValueOf(o) |
229 switch t.Kind() { | 233 switch t.Kind() { |
230 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64: | 234 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64: |
231 o = v.Int() | 235 o = v.Int() |
232 t = typeOfInt64 | 236 t = typeOfInt64 |
233 case reflect.Bool: | 237 case reflect.Bool: |
234 o = v.Bool() | 238 o = v.Bool() |
235 t = typeOfBool | 239 t = typeOfBool |
236 case reflect.String: | 240 case reflect.String: |
237 if t != typeOfBSKey { | 241 if t != typeOfBSKey { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 } | 311 } |
308 p.propType = pt | 312 p.propType = pt |
309 p.value = value | 313 p.value = value |
310 p.indexSetting = is | 314 p.indexSetting = is |
311 if t == typeOfByteSlice { | 315 if t == typeOfByteSlice { |
312 p.indexSetting = NoIndex | 316 p.indexSetting = NoIndex |
313 } | 317 } |
314 return | 318 return |
315 } | 319 } |
316 | 320 |
317 // PropertyLoadSaver may be implemented by a user type, and Interface will | 321 // MetaGetter is a subinterface of PropertyLoadSaver, but is also used to |
318 // use this interface to serialize the type instead of trying to automatically | 322 // abstract the meta argument for RawInterface.GetMulti. |
319 // create a serialization codec for it with helper.GetPLS. | 323 type MetaGetter interface { |
320 type PropertyLoadSaver interface { | |
321 » // Load takes the values from the given map and attempts to save them in to | |
322 » // the underlying object (usually a struct or a PropertyMap). If a fatal | |
323 » // error occurs, it's returned via error. If non-fatal conversion errors | |
324 » // occur, error will be a MultiError containing one or more ErrFieldMism atch | |
325 » // objects. | |
326 » Load(PropertyMap) error | |
327 | |
328 » // Save returns the current property as a PropertyMap. if withMeta is tr ue, | |
329 » // then the PropertyMap contains all the metadata (e.g. '$meta' fields) | |
330 » // which was held by this PropertyLoadSaver. | |
331 » Save(withMeta bool) (PropertyMap, error) | |
332 | |
333 // GetMeta will get information about the field which has the struct tag in | 324 // GetMeta will get information about the field which has the struct tag in |
334 // the form of `gae:"$<key>[,<default>]?"`. | 325 // the form of `gae:"$<key>[,<default>]?"`. |
335 // | 326 // |
336 // Supported metadata types are: | 327 // Supported metadata types are: |
337 // int64 - may have default (ascii encoded base-10) | 328 // int64 - may have default (ascii encoded base-10) |
338 // string - may have default | 329 // string - may have default |
339 // Toggle - MUST have default ("true" or "false") | 330 // Toggle - MUST have default ("true" or "false") |
340 // Key - NO default allowed | 331 // Key - NO default allowed |
341 // | 332 // |
342 // Struct fields of type Toggle (which is an Auto/On/Off) require you to | 333 // Struct fields of type Toggle (which is an Auto/On/Off) require you to |
(...skipping 12 matching lines...) Expand all Loading... | |
355 // // val == 10 | 346 // // val == 10 |
356 // // err == nil | 347 // // err == nil |
357 // | 348 // |
358 // type MyStruct struct { | 349 // type MyStruct struct { |
359 // TFlag Toggle `gae:"$flag1,true"` // defaults to true | 350 // TFlag Toggle `gae:"$flag1,true"` // defaults to true |
360 // FFlag Toggle `gae:"$flag2,false"` // defaults to false | 351 // FFlag Toggle `gae:"$flag2,false"` // defaults to false |
361 // // BadFlag Toggle `gae:"$flag3"` // ILLEGAL | 352 // // BadFlag Toggle `gae:"$flag3"` // ILLEGAL |
362 // } | 353 // } |
363 GetMeta(key string) (interface{}, error) | 354 GetMeta(key string) (interface{}, error) |
364 | 355 |
356 // GetMetaDefault is GetMeta, but with a default. | |
357 // | |
358 // If the metadata key is not available, or its type doesn't equal the | |
359 // homogenized type of dflt, then dflt will be returned. | |
360 // | |
361 // Type homogenization: | |
362 // signed integer types -> int64 | |
363 // bool -> Toggle fields (bool) | |
364 // | |
365 // Example: | |
366 // pls.GetMetaDefault("foo", 100).(int64) | |
367 GetMetaDefault(key string, dflt interface{}) interface{} | |
368 } | |
369 | |
370 // PropertyLoadSaver may be implemented by a user type, and Interface will | |
371 // use this interface to serialize the type instead of trying to automatically | |
372 // create a serialization codec for it with helper.GetPLS. | |
373 type PropertyLoadSaver interface { | |
374 // Load takes the values from the given map and attempts to save them in to | |
375 // the underlying object (usually a struct or a PropertyMap). If a fatal | |
376 // error occurs, it's returned via error. If non-fatal conversion errors | |
377 // occur, error will be a MultiError containing one or more ErrFieldMism atch | |
378 // objects. | |
379 Load(PropertyMap) error | |
380 | |
381 // Save returns the current property as a PropertyMap. if withMeta is tr ue, | |
382 // then the PropertyMap contains all the metadata (e.g. '$meta' fields) | |
383 // which was held by this PropertyLoadSaver. | |
384 Save(withMeta bool) (PropertyMap, error) | |
385 | |
386 MetaGetter | |
387 | |
365 // SetMeta allows you to set the current value of the meta-keyed field. | 388 // SetMeta allows you to set the current value of the meta-keyed field. |
366 SetMeta(key string, val interface{}) error | 389 SetMeta(key string, val interface{}) error |
367 | 390 |
368 // Problem indicates that this PLS has a fatal problem. Usually this is | 391 // Problem indicates that this PLS has a fatal problem. Usually this is |
369 // set when the underlying struct has recursion, invalid field types, ne sted | 392 // set when the underlying struct has recursion, invalid field types, ne sted |
370 // slices, etc. | 393 // slices, etc. |
371 Problem() error | 394 Problem() error |
372 } | 395 } |
373 | 396 |
374 // PropertyMap represents the contents of a datastore entity in a generic way. | 397 // PropertyMap represents the contents of a datastore entity in a generic way. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
428 v, ok := pm["$"+key] | 451 v, ok := pm["$"+key] |
429 if !ok || len(v) == 0 { | 452 if !ok || len(v) == 0 { |
430 return nil, ErrMetaFieldUnset | 453 return nil, ErrMetaFieldUnset |
431 } | 454 } |
432 if len(v) > 1 { | 455 if len(v) > 1 { |
433 return nil, errors.New("gae: too many values for Meta key") | 456 return nil, errors.New("gae: too many values for Meta key") |
434 } | 457 } |
435 return v[0].Value(), nil | 458 return v[0].Value(), nil |
436 } | 459 } |
437 | 460 |
461 func (pm PropertyMap) GetMetaDefault(key string, dflt interface{}) interface{} { | |
462 return GetMetaDefaultImpl(pm.GetMeta, key, dflt) | |
463 } | |
464 | |
438 // SetMeta implements PropertyLoadSaver.SetMeta. It will only return an error | 465 // SetMeta implements PropertyLoadSaver.SetMeta. It will only return an error |
439 // if `val` has an invalid type (e.g. not one supported by Property). | 466 // if `val` has an invalid type (e.g. not one supported by Property). |
440 func (pm PropertyMap) SetMeta(key string, val interface{}) error { | 467 func (pm PropertyMap) SetMeta(key string, val interface{}) error { |
441 prop := Property{} | 468 prop := Property{} |
442 if err := prop.SetValue(val, NoIndex); err != nil { | 469 if err := prop.SetValue(val, NoIndex); err != nil { |
443 return err | 470 return err |
444 } | 471 } |
445 pm["$"+key] = []Property{prop} | 472 pm["$"+key] = []Property{prop} |
446 return nil | 473 return nil |
447 } | 474 } |
448 | 475 |
449 // Problem implements PropertyLoadSaver.Problem. It ALWAYS returns nil. | 476 // Problem implements PropertyLoadSaver.Problem. It ALWAYS returns nil. |
450 func (pm PropertyMap) Problem() error { | 477 func (pm PropertyMap) Problem() error { |
451 return nil | 478 return nil |
452 } | 479 } |
480 | |
481 // GetMetaDefaultImpl is the implementation of PropertyLoadSaver.GetMetaDefault. | |
482 // | |
483 // It takes the normal GetMeta function, the key and the default, and returns | |
484 // the value according to PropertyLoadSaver.GetMetaDefault. | |
485 func GetMetaDefaultImpl(gm func(string) (interface{}, error), key string, dflt i nterface{}) interface{} { | |
486 cur, err := gm(key) | |
487 dflt, typ := UpconvertUnderlyingType(dflt, reflect.TypeOf(dflt)) | |
dnj
2015/08/05 00:38:41
Since you're always calling this anyway, do it abo
iannucci
2015/08/05 00:58:14
Done.
| |
488 if err != nil { | |
489 return dflt | |
490 } | |
491 if dflt != nil && reflect.TypeOf(cur) != typ { | |
492 return dflt | |
493 } | |
494 return cur | |
495 } | |
OLD | NEW |