func newContextNode(v interface{}) (res contextNode) { switch t := v.(type) { case string: return &contextKey{key: t} case template.Context: return newContextMap(t) case map[string]interface{}: return newContextMap(template.Context(t)) } return &contextValue{value: v} }
func constructOptions(md *Middleware) (opts *middlewareOpts, err error) { opts = &middlewareOpts{ options: md.Options, context: make(map[string]contextNode), } opts.template, err = template.ParseMap(template.Context(md.Template)) if err != nil { return } for key, value := range md.Context { opts.context[key] = newContextNode(value) } return }
// CleanDeep - Cleans map deeply. Converting all map[interface{}]interface{} to map[string]interface{}. // OK is false when obtained invalid type in map key. func CleanDeep(v interface{}) (_ interface{}, err error) { var ok bool switch m := v.(type) { case template.Context: for k, v := range m { m[k], err = CleanDeep(v) if err != nil { err = fmt.Errorf("key %q: %v", k, err) return } } return m, nil case map[string]interface{}: return CleanDeep(template.Context(m)) case map[interface{}]interface{}: res := make(template.Context) for k, v := range m { var key string key, ok = k.(string) if !ok { err = fmt.Errorf("key %#v is of invalid type %T", k, k) return } res[key], err = CleanDeep(v) if err != nil { err = fmt.Errorf("key %q: %v", key, err) return } } return res, nil case []interface{}: for n, v := range m { m[n], err = CleanDeep(v) if err != nil { err = fmt.Errorf("slice key %d: %v", n, err) return } } return m, nil } return v, nil }
// mergeDefaults - Merges two maps. Both can be one of: // `map[string]interface{}` or `map[interface{}]interface{}` func mergeDefaults(dest, extra interface{}) interface{} { switch d := dest.(type) { case map[string]string: switch e := extra.(type) { case map[string]string: for k, v := range e { if _, ok := d[k]; !ok { d[k] = v } } return d case template.Context: for k, v := range e { if _, ok := d[k]; !ok { d[k] = v.(string) } } return d case map[string]interface{}: for k, v := range e { if _, ok := d[k]; !ok { d[k] = v.(string) } } return d default: return dest } case map[string]interface{}: return mergeDefaults(template.Context(d), extra) case template.Context: switch e := extra.(type) { case map[string]string: for k, v := range e { if _, ok := d[k]; !ok { d[k] = v } } return d case map[string]interface{}: var res template.Context if d == nil { res = make(template.Context) } else { res = template.Context(d) } for k, v := range e { d[k] = WithDefaults(d[k], v) } return res case template.Context: if d == nil { d = make(template.Context) } for k, v := range e { d[k] = WithDefaults(d[k], v) } return d default: return dest } case []interface{}: switch e := extra.(type) { case []string: for _, value := range e { d = append(d, value) } return d case []interface{}: return append(d, e...) default: return d } case []string: switch e := extra.(type) { case []interface{}: for _, value := range e { if v, ok := value.(string); ok { d = append(d, v) } } return d case []string: return append(d, e...) default: return d } default: return dest } }