Index: service/datastore/pls_impl.go |
diff --git a/service/datastore/pls_impl.go b/service/datastore/pls_impl.go |
index b5e945ccfb5224e545889feca88084247123f8a5..d0f67488fa15f75a881451010a205a2e60bfa36c 100644 |
--- a/service/datastore/pls_impl.go |
+++ b/service/datastore/pls_impl.go |
@@ -298,7 +298,7 @@ func (p *structPLS) GetMeta(key string) (interface{}, error) { |
} |
if idx, ok := p.c.byMeta[key]; ok { |
- return p.getMetaFor(idx), nil |
+ return p.getMetaFor(idx) |
} |
if key == "kind" { |
@@ -307,11 +307,19 @@ func (p *structPLS) GetMeta(key string) (interface{}, error) { |
return nil, ErrMetaFieldUnset |
} |
-func (p *structPLS) getMetaFor(idx int) interface{} { |
+func (p *structPLS) getMetaFor(idx int) (interface{}, error) { |
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 { |
dnj
2015/11/03 01:18:10
nit: Handle err != nil (more standard).
|
+ return prop.value, err |
+ } |
+ return nil, err |
+ } |
+ |
if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Interface()) { |
val = f.Interface() |
if bf, ok := val.(Toggle); ok { |
@@ -319,19 +327,21 @@ func (p *structPLS) getMetaFor(idx int) interface{} { |
} |
} |
} |
- return val |
+ return val, nil |
} |
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 |
+ val, err := p.getMetaFor(idx) |
dnj
2015/11/03 01:18:10
Do we care about non-nil errors? If not, have getM
iannucci
2015/11/03 01:29:12
eh, returning an error is standarder
dnj
2015/11/03 03:11:25
Gah I I don't like the feel of returning an error
iannucci
2015/11/03 20:29:32
done
|
+ if err == nil { |
+ 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 +363,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 +459,17 @@ 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 |
+ if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { |
dnj
2015/11/03 01:18:10
nit: st.convert = reflect.PtrTo(ft)....
iannucci
2015/11/03 01:29:12
DERP
|
+ st.convert = true |
+ } |
switch { |
case name == "": |
if !f.Anonymous { |
@@ -461,12 +482,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, f.Type) |
dnj
2015/11/03 01:18:10
nit: f.Type => ft
iannucci
2015/11/03 01:29:13
done (and others)
|
+ 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,10 +506,7 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) { |
} |
substructType := reflect.Type(nil) |
- ft := f.Type |
- if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { |
- st.convert = true |
- } else { |
+ if !st.convert { |
switch f.Type.Kind() { |
case reflect.Struct: |
if ft != typeOfTime && ft != typeOfGeoPoint { |