Chromium Code Reviews| 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 |