-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.go
103 lines (85 loc) · 3.23 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package cnfg
import (
"encoding"
"encoding/json"
"fmt"
"time"
)
// ENVTag is the tag to look for on struct members. You may choose to use a custom
// tag by creating an &ENV{} struct with a different Tag. "env" is popular, but I
// chose "xml" because the nouns are generally singular, and those look good as
// env variables. "xml" is also convenient because it's brief and doesn't add yet
// another struct tag. Those lines can get long quickly.
const ENVTag = "xml"
// LevelSeparator is used to separate the names from different struct levels.
// This is hard coded here and cannot be changed or modified.
const LevelSeparator = "_"
// ENVUnmarshaler allows custom unmarshaling on a custom type.
// If your type implements this, it will be called and the logic stops there.
type ENVUnmarshaler interface {
UnmarshalENV(tag, envval string) error
}
// ENVMarshaler allows marshaling custom types into env variables.
type ENVMarshaler interface {
MarshalENV(tag string) (map[string]string, error)
}
// ENV allows you to parse environment variables using an object instead
// of global state. This package allows using the default ENVTag from global
// state, or you can pass in your own using this struct. See the UnmarshalENV
// function (it's 1 line) for an example of how to use this.
type ENV struct {
Tag string // Struct tag name.
Pfx string // ENV var prefix.
Low bool // Set this false to avoid capitalizing variables.
}
// Satify goconst.
const (
base10 = 10
bits8 = 8
bits16 = 16
bits32 = 32
bits64 = 64
)
// The following is only used in tests, and perhaps externally.
// Duration is useful if you need to load a time Duration from a config file into
// your application. Use the config.Duration type to support automatic unmarshal
// from all sources. If you do not use a config file, do not use this type because
// the environment unmarshaler supports time.Duration natively.
type Duration struct{ time.Duration }
// UnmarshalText parses a duration type from a config file. This method works
// with the Duration type to allow unmarshaling of durations from files and
// env variables in the same struct. You won't generally call this directly.
func (d *Duration) UnmarshalText(b []byte) error {
dur, err := time.ParseDuration(string(b))
if err != nil {
return fmt.Errorf("parsing duration '%s': %w", b, err)
}
d.Duration = dur
return nil
}
// MarshalText returns the string representation of a Duration. ie. 1m32s.
func (d Duration) MarshalText() ([]byte, error) {
return []byte(d.Duration.String()), nil
}
// MarshalJSON returns the string representation of a Duration for JSON. ie. "1m32s".
func (d Duration) MarshalJSON() ([]byte, error) {
return []byte(`"` + d.Duration.String() + `"`), nil
}
// String returns a Duration as string without trailing zero units.
func (d Duration) String() string {
dur := d.Duration.String()
if len(dur) > 3 && dur[len(dur)-3:] == "m0s" {
dur = dur[:len(dur)-2]
}
if len(dur) > 3 && dur[len(dur)-3:] == "h0m" {
dur = dur[:len(dur)-2]
}
return dur
}
// Make sure our struct satisfies the interface it's for.
var (
_ encoding.TextUnmarshaler = (*Duration)(nil)
_ encoding.TextMarshaler = (*Duration)(nil)
_ json.Marshaler = (*Duration)(nil)
_ fmt.Stringer = (*Duration)(nil)
)