Skip to content

Commit

Permalink
Merge 2eec4b5 into f1d6c5f
Browse files Browse the repository at this point in the history
  • Loading branch information
jparise committed May 17, 2021
2 parents f1d6c5f + 2eec4b5 commit 8bae03d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fig is a tiny library for loading an application's config file and its environme
- Define your **configuration**, **validations** and **defaults** in a single location
- Optionally **load from the environment** as well
- Only **3** external dependencies
- Full support for`time.Time` & `time.Duration`
- Full support for`time.Time`, `time.Duration` & `regexp.Regexp`
- Tiny API
- Decoders for `.yaml`, `.json` and `.toml` files

Expand Down Expand Up @@ -64,8 +64,9 @@ type Config struct {
Cleanup time.Duration `fig:"cleanup" default:"30m"`
}
Logger struct {
Level string `fig:"level" default:"info"`
Trace bool `fig:"trace"`
Level string `fig:"level" default:"info"`
Pattern *regexp.Regexp `fig:"pattern" default:".*"`
Trace bool `fig:"trace"`
}
}

Expand Down
7 changes: 7 additions & 0 deletions fig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"reflect"
"regexp"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -289,6 +290,12 @@ func (f *fig) setValue(fv reflect.Value, val string) error {
return err
}
fv.Set(reflect.ValueOf(t))
} else if _, ok := fv.Interface().(regexp.Regexp); ok {
re, err := regexp.Compile(val)
if err != nil {
return err
}
fv.Set(reflect.ValueOf(*re))
} else {
return fmt.Errorf("unsupported type %s", fv.Kind())
}
Expand Down
45 changes: 43 additions & 2 deletions fig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"reflect"
"regexp"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -221,8 +222,9 @@ func Test_fig_Load_Defaults(t *testing.T) {
Host string `fig:"host" default:"127.0.0.1"`
Ports []int `fig:"ports" default:"[80,443]"`
Logger struct {
LogLevel string `fig:"log_level" default:"info"`
Production bool `fig:"production"`
LogLevel string `fig:"log_level" default:"info"`
Pattern *regexp.Regexp `fig:"pattern" default:".*"`
Production bool `fig:"production"`
Metadata struct {
Keys []string `fig:"keys" default:"[ts]"`
}
Expand All @@ -236,6 +238,7 @@ func Test_fig_Load_Defaults(t *testing.T) {
want.Host = "0.0.0.0"
want.Ports = []int{80, 443}
want.Logger.LogLevel = "debug"
want.Logger.Pattern = regexp.MustCompile(".*")
want.Logger.Production = false
want.Logger.Metadata.Keys = []string{"ts"}
want.Application.BuildDate = time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC)
Expand Down Expand Up @@ -1014,6 +1017,35 @@ func Test_fig_setValue(t *testing.T) {
}
})

t.Run("regexp", func(t *testing.T) {
var re regexp.Regexp
fv := reflect.ValueOf(&re).Elem()

err := fig.setValue(fv, "[a-z]+")
if err != nil {
t.Fatalf("unexpected err: %v", err)
}

want, err := regexp.Compile("[a-z]+")
if err != nil {
t.Fatalf("error parsing time: %v", err)
}

if re.String() != want.String() {
t.Fatalf("want %v, got %v", want, re)
}
})

t.Run("bad regexp", func(t *testing.T) {
var re regexp.Regexp
fv := reflect.ValueOf(&re).Elem()

err := fig.setValue(fv, "[a-")
if err == nil {
t.Fatalf("expected err")
}
})

t.Run("interface returns error", func(t *testing.T) {
var i interface{}
fv := reflect.ValueOf(i)
Expand Down Expand Up @@ -1089,6 +1121,15 @@ func Test_fig_setSlice(t *testing.T) {
},
Val: "[2019-12-25T10:30:30Z,2020-01-01T00:00:00Z]",
},
{
Name: "regexps",
InSlice: &[]*regexp.Regexp{},
WantSlice: &[]*regexp.Regexp{
regexp.MustCompile("[a-z]+"),
regexp.MustCompile(".*"),
},
Val: "[[a-z]+,.*]",
},
} {
t.Run(tc.Val, func(t *testing.T) {
in := reflect.ValueOf(tc.InSlice).Elem()
Expand Down

0 comments on commit 8bae03d

Please sign in to comment.