Skip to content

Commit 7f3cd5b

Browse files
- removed dependency of fmt and net.
- deprecate HydrateX functions
1 parent 9d80271 commit 7f3cd5b

File tree

5 files changed

+1416
-7
lines changed

5 files changed

+1416
-7
lines changed

forks/mapstructure/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2013 Mitchell Hashimoto
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

forks/mapstructure/decode_hooks.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package mapstructure
2+
3+
import (
4+
"errors"
5+
"reflect"
6+
"strconv"
7+
"strings"
8+
"time"
9+
)
10+
11+
// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
12+
// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
13+
func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
14+
// Create variables here so we can reference them with the reflect pkg
15+
var f1 DecodeHookFuncType
16+
var f2 DecodeHookFuncKind
17+
18+
// Fill in the variables into this interface and the rest is done
19+
// automatically using the reflect package.
20+
potential := []interface{}{f1, f2}
21+
22+
v := reflect.ValueOf(h)
23+
vt := v.Type()
24+
for _, raw := range potential {
25+
pt := reflect.ValueOf(raw).Type()
26+
if vt.ConvertibleTo(pt) {
27+
return v.Convert(pt).Interface()
28+
}
29+
}
30+
31+
return nil
32+
}
33+
34+
// DecodeHookExec executes the given decode hook. This should be used
35+
// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
36+
// that took reflect.Kind instead of reflect.Type.
37+
func DecodeHookExec(
38+
raw DecodeHookFunc,
39+
from reflect.Type, to reflect.Type,
40+
data interface{}) (interface{}, error) {
41+
switch f := typedDecodeHook(raw).(type) {
42+
case DecodeHookFuncType:
43+
return f(from, to, data)
44+
case DecodeHookFuncKind:
45+
return f(from.Kind(), to.Kind(), data)
46+
default:
47+
return nil, errors.New("invalid decode hook signature")
48+
}
49+
}
50+
51+
// ComposeDecodeHookFunc creates a single DecodeHookFunc that
52+
// automatically composes multiple DecodeHookFuncs.
53+
//
54+
// The composed funcs are called in order, with the result of the
55+
// previous transformation.
56+
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
57+
return func(
58+
f reflect.Type,
59+
t reflect.Type,
60+
data interface{}) (interface{}, error) {
61+
var err error
62+
for _, f1 := range fs {
63+
data, err = DecodeHookExec(f1, f, t, data)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
// Modify the from kind to be correct with the new data
69+
f = nil
70+
if val := reflect.ValueOf(data); val.IsValid() {
71+
f = val.Type()
72+
}
73+
}
74+
75+
return data, nil
76+
}
77+
}
78+
79+
// StringToSliceHookFunc returns a DecodeHookFunc that converts
80+
// string to []string by splitting on the given sep.
81+
func StringToSliceHookFunc(sep string) DecodeHookFunc {
82+
return func(
83+
f reflect.Kind,
84+
t reflect.Kind,
85+
data interface{}) (interface{}, error) {
86+
if f != reflect.String || t != reflect.Slice {
87+
return data, nil
88+
}
89+
90+
raw := data.(string)
91+
if raw == "" {
92+
return []string{}, nil
93+
}
94+
95+
return strings.Split(raw, sep), nil
96+
}
97+
}
98+
99+
// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
100+
// strings to time.Duration.
101+
func StringToTimeDurationHookFunc() DecodeHookFunc {
102+
return func(
103+
f reflect.Type,
104+
t reflect.Type,
105+
data interface{}) (interface{}, error) {
106+
if f.Kind() != reflect.String {
107+
return data, nil
108+
}
109+
if t != reflect.TypeOf(time.Duration(5)) {
110+
return data, nil
111+
}
112+
113+
// Convert it by parsing
114+
return time.ParseDuration(data.(string))
115+
}
116+
}
117+
118+
// StringToTimeHookFunc returns a DecodeHookFunc that converts
119+
// strings to time.Time.
120+
func StringToTimeHookFunc(layout string) DecodeHookFunc {
121+
return func(
122+
f reflect.Type,
123+
t reflect.Type,
124+
data interface{}) (interface{}, error) {
125+
if f.Kind() != reflect.String {
126+
return data, nil
127+
}
128+
if t != reflect.TypeOf(time.Time{}) {
129+
return data, nil
130+
}
131+
132+
// Convert it by parsing
133+
return time.Parse(layout, data.(string))
134+
}
135+
}
136+
137+
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
138+
// the decoder.
139+
//
140+
// Note that this is significantly different from the WeaklyTypedInput option
141+
// of the DecoderConfig.
142+
func WeaklyTypedHook(
143+
f reflect.Kind,
144+
t reflect.Kind,
145+
data interface{}) (interface{}, error) {
146+
dataVal := reflect.ValueOf(data)
147+
switch t {
148+
case reflect.String:
149+
switch f {
150+
case reflect.Bool:
151+
if dataVal.Bool() {
152+
return "1", nil
153+
}
154+
return "0", nil
155+
case reflect.Float32:
156+
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
157+
case reflect.Int:
158+
return strconv.FormatInt(dataVal.Int(), 10), nil
159+
case reflect.Slice:
160+
dataType := dataVal.Type()
161+
elemKind := dataType.Elem().Kind()
162+
if elemKind == reflect.Uint8 {
163+
return string(dataVal.Interface().([]uint8)), nil
164+
}
165+
case reflect.Uint:
166+
return strconv.FormatUint(dataVal.Uint(), 10), nil
167+
}
168+
}
169+
170+
return data, nil
171+
}

forks/mapstructure/error.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package mapstructure
2+
3+
import (
4+
"errors"
5+
"github.com/cathalgarvey/fmtless"
6+
"sort"
7+
"strings"
8+
)
9+
10+
// Error implements the error interface and can represents multiple
11+
// errors that occur in the course of a single decode.
12+
type Error struct {
13+
Errors []string
14+
}
15+
16+
func (e *Error) Error() string {
17+
points := make([]string, len(e.Errors))
18+
for i, err := range e.Errors {
19+
points[i] = fmt.Sprintf("* %s", err)
20+
}
21+
22+
sort.Strings(points)
23+
return fmt.Sprintf(
24+
"%d error(s) decoding:\n\n%s",
25+
len(e.Errors), strings.Join(points, "\n"))
26+
}
27+
28+
// WrappedErrors implements the errwrap.Wrapper interface to make this
29+
// return value more useful with the errwrap and go-multierror libraries.
30+
func (e *Error) WrappedErrors() []error {
31+
if e == nil {
32+
return nil
33+
}
34+
35+
result := make([]error, len(e.Errors))
36+
for i, e := range e.Errors {
37+
result[i] = errors.New(e)
38+
}
39+
40+
return result
41+
}
42+
43+
func appendErrors(errors []string, err error) []string {
44+
switch e := err.(type) {
45+
case *Error:
46+
return append(errors, e.Errors...)
47+
default:
48+
return append(errors, e.Error())
49+
}
50+
}

0 commit comments

Comments
 (0)