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

Unified Diff: service/datastore/properties.go

Issue 1270113002: Re-add metadata passthrough on Get operations (Closed) Base URL: https://github.com/luci/gae.git@fix_other_interfaces
Patch Set: safer, add tests Created 5 years, 4 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « service/datastore/pls_test.go ('k') | service/datastore/properties_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
+}
« no previous file with comments | « service/datastore/pls_test.go ('k') | service/datastore/properties_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698