Index: service/datastore/properties.go |
diff --git a/service/datastore/properties.go b/service/datastore/properties.go |
index dfa91515cca6432f38b102d2a119ca230e3655b5..6b4d1ba1a64236066dc9ff3ff3c731112ac6106e 100644 |
--- a/service/datastore/properties.go |
+++ b/service/datastore/properties.go |
@@ -225,6 +225,10 @@ func PropertyTypeOf(v interface{}, checkValid bool) (PropertyType, error) { |
// its native datastore-compatible type. e.g. int16 will convert to int64, and |
// `type Foo string` will convert to `string`. |
func UpconvertUnderlyingType(o interface{}, t reflect.Type) (interface{}, reflect.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
|
+ if o == nil { |
+ return o, t |
+ } |
+ |
v := reflect.ValueOf(o) |
switch t.Kind() { |
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
@@ -314,22 +318,9 @@ func (p *Property) SetValue(value interface{}, is IndexSetting) (err error) { |
return |
} |
-// PropertyLoadSaver may be implemented by a user type, and Interface will |
-// use this interface to serialize the type instead of trying to automatically |
-// create a serialization codec for it with helper.GetPLS. |
-type PropertyLoadSaver interface { |
- // Load takes the values from the given map and attempts to save them into |
- // the underlying object (usually a struct or a PropertyMap). If a fatal |
- // error occurs, it's returned via error. If non-fatal conversion errors |
- // occur, error will be a MultiError containing one or more ErrFieldMismatch |
- // objects. |
- Load(PropertyMap) error |
- |
- // Save returns the current property as a PropertyMap. if withMeta is true, |
- // then the PropertyMap contains all the metadata (e.g. '$meta' fields) |
- // which was held by this PropertyLoadSaver. |
- Save(withMeta bool) (PropertyMap, error) |
- |
+// MetaGetter is a subinterface of PropertyLoadSaver, but is also used to |
+// abstract the meta argument for RawInterface.GetMulti. |
+type MetaGetter interface { |
// GetMeta will get information about the field which has the struct tag in |
// the form of `gae:"$<key>[,<default>]?"`. |
// |
@@ -362,6 +353,38 @@ type PropertyLoadSaver interface { |
// } |
GetMeta(key string) (interface{}, error) |
+ // GetMetaDefault is GetMeta, but with a default. |
+ // |
+ // If the metadata key is not available, or its type doesn't equal the |
+ // homogenized type of dflt, then dflt will be returned. |
+ // |
+ // Type homogenization: |
+ // signed integer types -> int64 |
+ // bool -> Toggle fields (bool) |
+ // |
+ // Example: |
+ // pls.GetMetaDefault("foo", 100).(int64) |
+ GetMetaDefault(key string, dflt interface{}) interface{} |
+} |
+ |
+// PropertyLoadSaver may be implemented by a user type, and Interface will |
+// use this interface to serialize the type instead of trying to automatically |
+// create a serialization codec for it with helper.GetPLS. |
+type PropertyLoadSaver interface { |
+ // Load takes the values from the given map and attempts to save them into |
+ // the underlying object (usually a struct or a PropertyMap). If a fatal |
+ // error occurs, it's returned via error. If non-fatal conversion errors |
+ // occur, error will be a MultiError containing one or more ErrFieldMismatch |
+ // objects. |
+ Load(PropertyMap) error |
+ |
+ // Save returns the current property as a PropertyMap. if withMeta is true, |
+ // then the PropertyMap contains all the metadata (e.g. '$meta' fields) |
+ // which was held by this PropertyLoadSaver. |
+ Save(withMeta bool) (PropertyMap, error) |
+ |
+ MetaGetter |
+ |
// SetMeta allows you to set the current value of the meta-keyed field. |
SetMeta(key string, val interface{}) error |
@@ -435,6 +458,10 @@ func (pm PropertyMap) GetMeta(key string) (interface{}, error) { |
return v[0].Value(), nil |
} |
+func (pm PropertyMap) GetMetaDefault(key string, dflt interface{}) interface{} { |
+ return GetMetaDefaultImpl(pm.GetMeta, key, dflt) |
+} |
+ |
// SetMeta implements PropertyLoadSaver.SetMeta. It will only return an error |
// if `val` has an invalid type (e.g. not one supported by Property). |
func (pm PropertyMap) SetMeta(key string, val interface{}) error { |
@@ -450,3 +477,19 @@ func (pm PropertyMap) SetMeta(key string, val interface{}) error { |
func (pm PropertyMap) Problem() error { |
return nil |
} |
+ |
+// GetMetaDefaultImpl is the implementation of PropertyLoadSaver.GetMetaDefault. |
+// |
+// It takes the normal GetMeta function, the key and the default, and returns |
+// the value according to PropertyLoadSaver.GetMetaDefault. |
+func GetMetaDefaultImpl(gm func(string) (interface{}, error), key string, dflt interface{}) interface{} { |
+ cur, err := gm(key) |
+ 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.
|
+ if err != nil { |
+ return dflt |
+ } |
+ if dflt != nil && reflect.TypeOf(cur) != typ { |
+ return dflt |
+ } |
+ return cur |
+} |