diff options
author | Wim <wim@42.be> | 2019-06-16 23:33:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-16 23:33:25 +0200 |
commit | cb712ff37d3c20a21695e00c52fff213a6fd40b4 (patch) | |
tree | 0ba0ee4f55bf6ace2656562465cc82d807e741b9 /vendor/github.com/gorilla/schema/decoder.go | |
parent | f4ae61044888f591830e6c1be9a2bdb14f88943e (diff) | |
download | matterbridge-msglm-cb712ff37d3c20a21695e00c52fff213a6fd40b4.tar.gz matterbridge-msglm-cb712ff37d3c20a21695e00c52fff213a6fd40b4.tar.bz2 matterbridge-msglm-cb712ff37d3c20a21695e00c52fff213a6fd40b4.zip |
Update vendor (#852)
Diffstat (limited to 'vendor/github.com/gorilla/schema/decoder.go')
-rw-r--r-- | vendor/github.com/gorilla/schema/decoder.go | 99 |
1 files changed, 78 insertions, 21 deletions
diff --git a/vendor/github.com/gorilla/schema/decoder.go b/vendor/github.com/gorilla/schema/decoder.go index 5352a908..5afbd921 100644 --- a/vendor/github.com/gorilla/schema/decoder.go +++ b/vendor/github.com/gorilla/schema/decoder.go @@ -81,52 +81,83 @@ func (d *Decoder) Decode(dst interface{}, src map[string][]string) error { errors[path] = err } } else if !d.ignoreUnknownKeys { - errors[path] = fmt.Errorf("schema: invalid path %q", path) + errors[path] = UnknownKeyError{Key: path} } } + errors.merge(d.checkRequired(t, src)) if len(errors) > 0 { return errors } - return d.checkRequired(t, src, "") + return nil } // checkRequired checks whether required fields are empty // -// check type t recursively if t has struct fields, and prefix is same as parsePath: in dotted notation +// check type t recursively if t has struct fields. // // src is the source map for decoding, we use it here to see if those required fields are included in src -func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix string) error { +func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string) MultiError { + m, errs := d.findRequiredFields(t, "", "") + for key, fields := range m { + if isEmptyFields(fields, src) { + errs[key] = EmptyFieldError{Key: key} + } + } + return errs +} + +// findRequiredFields recursively searches the struct type t for required fields. +// +// canonicalPrefix and searchPrefix are used to resolve full paths in dotted notation +// for nested struct fields. canonicalPrefix is a complete path which never omits +// any embedded struct fields. searchPrefix is a user-friendly path which may omit +// some embedded struct fields to point promoted fields. +func (d *Decoder) findRequiredFields(t reflect.Type, canonicalPrefix, searchPrefix string) (map[string][]fieldWithPrefix, MultiError) { struc := d.cache.get(t) if struc == nil { // unexpect, cache.get never return nil - return errors.New("cache fail") + return nil, MultiError{canonicalPrefix + "*": errors.New("cache fail")} } + m := map[string][]fieldWithPrefix{} + errs := MultiError{} for _, f := range struc.fields { if f.typ.Kind() == reflect.Struct { - err := d.checkRequired(f.typ, src, prefix+f.alias+".") - if err != nil { - if !f.isAnonymous { - return err - } - // check embedded parent field. - err2 := d.checkRequired(f.typ, src, prefix) - if err2 != nil { - return err + fcprefix := canonicalPrefix + f.canonicalAlias + "." + for _, fspath := range f.paths(searchPrefix) { + fm, ferrs := d.findRequiredFields(f.typ, fcprefix, fspath+".") + for key, fields := range fm { + m[key] = append(m[key], fields...) } + errs.merge(ferrs) } } if f.isRequired { - key := f.alias - if prefix != "" { - key = prefix + key - } - if isEmpty(f.typ, src[key]) { - return fmt.Errorf("%v is empty", key) + key := canonicalPrefix + f.canonicalAlias + m[key] = append(m[key], fieldWithPrefix{ + fieldInfo: f, + prefix: searchPrefix, + }) + } + } + return m, errs +} + +type fieldWithPrefix struct { + *fieldInfo + prefix string +} + +// isEmptyFields returns true if all of specified fields are empty. +func isEmptyFields(fields []fieldWithPrefix, src map[string][]string) bool { + for _, f := range fields { + for _, path := range f.paths(f.prefix) { + if !isEmpty(f.typ, src[path]) { + return false } } } - return nil + return true } // isEmpty returns true if value is empty for specific type @@ -424,6 +455,24 @@ func (e ConversionError) Error() string { return output } +// UnknownKeyError stores information about an unknown key in the source map. +type UnknownKeyError struct { + Key string // key from the source map. +} + +func (e UnknownKeyError) Error() string { + return fmt.Sprintf("schema: invalid path %q", e.Key) +} + +// EmptyFieldError stores information about an empty required field. +type EmptyFieldError struct { + Key string // required key in the source map. +} + +func (e EmptyFieldError) Error() string { + return fmt.Sprintf("%v is empty", e.Key) +} + // MultiError stores multiple decoding errors. // // Borrowed from the App Engine SDK. @@ -445,3 +494,11 @@ func (e MultiError) Error() string { } return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1) } + +func (e MultiError) merge(errors MultiError) { + for key, err := range errors { + if e[key] == nil { + e[key] = err + } + } +} |