Index: service/datastore/pls_impl.go |
diff --git a/service/datastore/pls_impl.go b/service/datastore/pls_impl.go |
index b5e945ccfb5224e545889feca88084247123f8a5..0831f77c748907122678789536aa69fd8ce1866d 100644 |
--- a/service/datastore/pls_impl.go |
+++ b/service/datastore/pls_impl.go |
@@ -298,20 +298,28 @@ func (p *structPLS) GetMeta(key string) (interface{}, error) { |
} |
if idx, ok := p.c.byMeta[key]; ok { |
- return p.getMetaFor(idx), nil |
- } |
- |
- if key == "kind" { |
+ if val, ok := p.getMetaFor(idx); ok { |
+ return val, nil |
+ } |
+ } else if key == "kind" { |
return p.getDefaultKind(), nil |
} |
return nil, ErrMetaFieldUnset |
} |
-func (p *structPLS) getMetaFor(idx int) interface{} { |
+func (p *structPLS) getMetaFor(idx int) (interface{}, bool) { |
st := p.c.byIndex[idx] |
val := st.metaVal |
- f := p.o.Field(idx) |
if st.canSet { |
+ f := p.o.Field(idx) |
+ if st.convert { |
+ prop, err := f.Addr().Interface().(PropertyConverter).ToProperty() |
+ if err != nil { |
+ return nil, false |
+ } |
+ return prop.value, true |
+ } |
+ |
if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Interface()) { |
val = f.Interface() |
if bf, ok := val.(Toggle); ok { |
@@ -319,19 +327,20 @@ func (p *structPLS) getMetaFor(idx int) interface{} { |
} |
} |
} |
- return val |
+ return val, true |
} |
func (p *structPLS) GetAllMeta() PropertyMap { |
needKind := true |
ret := make(PropertyMap, len(p.c.byMeta)+1) |
for k, idx := range p.c.byMeta { |
- val := p.getMetaFor(idx) |
- p := Property{} |
- if err := p.SetValue(val, NoIndex); err != nil { |
- continue |
+ if val, ok := p.getMetaFor(idx); ok { |
+ p := Property{} |
+ if err := p.SetValue(val, NoIndex); err != nil { |
+ continue |
+ } |
+ ret["$"+k] = []Property{p} |
} |
- ret["$"+k] = []Property{p} |
} |
if needKind { |
if _, ok := p.c.byMeta["kind"]; !ok { |
@@ -353,9 +362,15 @@ func (p *structPLS) SetMeta(key string, val interface{}) (err error) { |
if !ok { |
return ErrMetaFieldUnset |
} |
- if !p.c.byIndex[idx].canSet { |
+ st := p.c.byIndex[idx] |
+ if !st.canSet { |
return fmt.Errorf("gae/helper: cannot set meta %q: unexported field", key) |
} |
+ if st.convert { |
+ return p.o.Field(idx).Addr().Interface().(PropertyConverter).FromProperty( |
+ MkPropertyNI(val)) |
+ } |
+ |
// setting a BoolField |
if b, ok := val.(bool); ok { |
if b { |
@@ -443,12 +458,15 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) { |
for i := range c.byIndex { |
st := &c.byIndex[i] |
f := t.Field(i) |
+ ft := f.Type |
+ |
name := f.Tag.Get("gae") |
opts := "" |
if i := strings.Index(name, ","); i != -1 { |
name, opts = name[:i], name[i+1:] |
} |
st.canSet = f.PkgPath == "" // blank == exported |
+ st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverter) |
switch { |
case name == "": |
if !f.Anonymous { |
@@ -461,12 +479,14 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) { |
return |
} |
c.byMeta[name] = i |
- mv, err := convertMeta(opts, f.Type) |
- if err != nil { |
- c.problem = me("meta field %q has bad type: %s", "$"+name, err) |
- return |
+ if !st.convert { |
+ mv, err := convertMeta(opts, ft) |
+ if err != nil { |
+ c.problem = me("meta field %q has bad type: %s", "$"+name, err) |
+ return |
+ } |
+ st.metaVal = mv |
} |
- st.metaVal = mv |
fallthrough |
case name == "-": |
st.name = "-" |
@@ -483,11 +503,8 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) { |
} |
substructType := reflect.Type(nil) |
- ft := f.Type |
- if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { |
- st.convert = true |
- } else { |
- switch f.Type.Kind() { |
+ if !st.convert { |
+ switch ft.Kind() { |
case reflect.Struct: |
if ft != typeOfTime && ft != typeOfGeoPoint { |
substructType = ft |
@@ -502,7 +519,7 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) { |
c.hasSlice = c.hasSlice || st.isSlice |
case reflect.Interface: |
c.problem = me("field %q has non-concrete interface type %s", |
- f.Name, f.Type) |
+ f.Name, ft) |
return |
} |
} |