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

Unified Diff: service/datastore/pls_impl.go

Issue 1525453002: Handle unexpected entity fields gracefully. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix nit Created 5 years 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.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/pls_impl.go
diff --git a/service/datastore/pls_impl.go b/service/datastore/pls_impl.go
index 9fab74f59e6a18364acbca48238867a03d0ff12c..5f7fe4740d06b5dd585f3444435340cdec8841bd 100644
--- a/service/datastore/pls_impl.go
+++ b/service/datastore/pls_impl.go
@@ -27,12 +27,15 @@ type structTag struct {
substructCodec *structCodec
convert bool
metaVal interface{}
+ isExtra bool
canSet bool
}
type structCodec struct {
- byMeta map[string]int
- byName map[string]int
+ byMeta map[string]int
+ byName map[string]int
+ bySpecial map[string]int
+
byIndex []structTag
hasSlice bool
problem error
@@ -55,19 +58,38 @@ func typeMismatchReason(val interface{}, v reflect.Value) string {
func (p *structPLS) Load(propMap PropertyMap) error {
convFailures := errors.MultiError(nil)
+ useExtra := false
+ extra := (*PropertyMap)(nil)
+ if i, ok := p.c.bySpecial["extra"]; ok {
+ useExtra = true
+ f := p.c.byIndex[i]
+ if f.canSet {
+ extra = p.o.Field(i).Addr().Interface().(*PropertyMap)
+ }
+ }
t := reflect.Type(nil)
for name, props := range propMap {
multiple := len(props) > 1
for i, prop := range props {
if reason := loadInner(p.c, p.o, i, name, prop, multiple); reason != "" {
- if t == nil {
- t = p.o.Type()
+ if useExtra {
+ if extra != nil {
+ if *extra == nil {
+ *extra = make(PropertyMap, 1)
+ }
+ (*extra)[name] = props
+ }
+ break // go to the next property in propMap
+ } else {
+ if t == nil {
+ t = p.o.Type()
+ }
+ convFailures = append(convFailures, &ErrFieldMismatch{
+ StructType: t,
+ FieldName: name,
+ Reason: reason,
+ })
}
- convFailures = append(convFailures, &ErrFieldMismatch{
- StructType: t,
- FieldName: name,
- Reason: reason,
- })
}
}
}
@@ -253,7 +275,7 @@ func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
}
for i, st := range p.c.byIndex {
- if st.name == "-" {
+ if st.name == "-" || st.isExtra {
continue
}
name := st.name
@@ -277,6 +299,17 @@ func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
}
}
}
+
+ if i, ok := p.c.bySpecial["extra"]; ok {
+ if p.c.byIndex[i].name != "-" {
+ for fullName, vals := range p.o.Field(i).Interface().(PropertyMap) {
+ if _, ok := propMap[fullName]; !ok {
+ propMap[fullName] = vals
+ }
+ }
+ }
+ }
+
return
}
@@ -419,9 +452,10 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) {
}
c = &structCodec{
- byIndex: make([]structTag, t.NumField()),
- byName: make(map[string]int, t.NumField()),
- byMeta: make(map[string]int, t.NumField()),
+ byIndex: make([]structTag, t.NumField()),
+ byName: make(map[string]int, t.NumField()),
+ byMeta: make(map[string]int, t.NumField()),
+ bySpecial: make(map[string]int, 1),
problem: errRecursiveStruct, // we'll clear this later if it's not recursive
}
@@ -446,6 +480,24 @@ func getStructCodecLocked(t reflect.Type) (c *structCodec) {
name, opts = name[:i], name[i+1:]
}
st.canSet = f.PkgPath == "" // blank == exported
+ if opts == "extra" {
+ if _, ok := c.bySpecial["extra"]; ok {
+ c.problem = me("struct has multiple fields tagged as 'extra'")
+ return
+ }
+ if name != "" && name != "-" {
+ c.problem = me("struct 'extra' field has invalid name %s, expecing `` or `-`", name)
+ return
+ }
+ if ft != typeOfPropertyMap {
+ c.problem = me("struct 'extra' field has invalid type %s, expecing PropertyMap", ft)
+ return
+ }
+ st.isExtra = true
+ st.name = name
+ c.bySpecial["extra"] = i
+ continue
+ }
st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverter)
switch {
case name == "":
« no previous file with comments | « service/datastore/pls.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698