Skip to content

Commit

Permalink
Merge pull request #20 from caledhwa/add-float
Browse files Browse the repository at this point in the history
Added float types and float slices
  • Loading branch information
caarlos0 authored Oct 13, 2016
2 parents 8030fe5 + 91a9c06 commit d0de832
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 5 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,13 @@ The library has support for the following types:
* `string`
* `int`
* `bool`
* `float32`
* `float64`
* `[]string`
* `[]int`
* `[]bool`
* `[]float32`
* `[]float64`

If you set the `envDefault` tag for something, this value will be used in the
case of absence of it in the environment. If you don't do that AND the
Expand Down
58 changes: 55 additions & 3 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ var (
// ErrUnsupportedSliceType if the slice element type is not supported by env
ErrUnsupportedSliceType = errors.New("Unsupported slice type")
// Friendly names for reflect types
sliceOfInts = reflect.TypeOf([]int(nil))
sliceOfStrings = reflect.TypeOf([]string(nil))
sliceOfBools = reflect.TypeOf([]bool(nil))
sliceOfInts = reflect.TypeOf([]int(nil))
sliceOfStrings = reflect.TypeOf([]string(nil))
sliceOfBools = reflect.TypeOf([]bool(nil))
sliceOfFloat32s = reflect.TypeOf([]float32(nil))
sliceOfFloat64s = reflect.TypeOf([]float64(nil))
)

// Parse parses a struct containing `env` tags and loads its values from
Expand Down Expand Up @@ -123,6 +125,18 @@ func set(field reflect.Value, refType reflect.StructField, value string) error {
return err
}
field.SetInt(intValue)
case reflect.Float32:
v, err := strconv.ParseFloat(value, 32)
if err != nil {
return err
}
field.SetFloat(v)
case reflect.Float64:
v, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
field.Set(reflect.ValueOf(v))
case reflect.Int64:
if refType.Type.String() == "time.Duration" {
dValue, err := time.ParseDuration(value)
Expand Down Expand Up @@ -155,6 +169,18 @@ func handleSlice(field reflect.Value, value, separator string) error {
return err
}
field.Set(reflect.ValueOf(intData))
case sliceOfFloat32s:
data, err := parseFloat32s(splitData)
if err != nil {
return err
}
field.Set(reflect.ValueOf(data))
case sliceOfFloat64s:
data, err := parseFloat64s(splitData)
if err != nil {
return err
}
field.Set(reflect.ValueOf(data))
case sliceOfBools:
boolData, err := parseBools(splitData)
if err != nil {
Expand All @@ -180,6 +206,32 @@ func parseInts(data []string) ([]int, error) {
return intSlice, nil
}

func parseFloat32s(data []string) ([]float32, error) {
var float32Slice []float32

for _, v := range data {
data, err := strconv.ParseFloat(v, 32)
if err != nil {
return nil, err
}
float32Slice = append(float32Slice, float32(data))
}
return float32Slice, nil
}

func parseFloat64s(data []string) ([]float64, error) {
var float64Slice []float64

for _, v := range data {
data, err := strconv.ParseFloat(v, 64)
if err != nil {
return nil, err
}
float64Slice = append(float64Slice, float64(data))
}
return float64Slice, nil
}

func parseBools(data []string) ([]bool, error) {
var boolSlice []bool

Expand Down
22 changes: 20 additions & 2 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ type Config struct {
Numbers []int `env:"NUMBERS"`
Bools []bool `env:"BOOLS"`
Duration time.Duration `env:"DURATION"`
Float32 float32 `env:"FLOAT32"`
Float64 float64 `env:"FLOAT64"`
Float32s []float32 `env:"FLOAT32S"`
Float64s []float64 `env:"FLOAT64S"`
}

func TestParsesEnv(t *testing.T) {
Expand All @@ -32,6 +36,10 @@ func TestParsesEnv(t *testing.T) {
os.Setenv("NUMBERS", "1,2,3,4")
os.Setenv("BOOLS", "t,TRUE,0,1")
os.Setenv("DURATION", "1s")
os.Setenv("FLOAT32", "3.40282346638528859811704183484516925440e+38")
os.Setenv("FLOAT64", "1.797693134862315708145274237317043567981e+308")
os.Setenv("FLOAT32S", "1.0,2.0,3.0")
os.Setenv("FLOAT64S", "1.0,2.0,3.0")

defer os.Setenv("somevar", "")
defer os.Setenv("othervar", "")
Expand All @@ -41,6 +49,10 @@ func TestParsesEnv(t *testing.T) {
defer os.Setenv("NUMBERS", "")
defer os.Setenv("BOOLS", "")
defer os.Setenv("DURATION", "")
defer os.Setenv("FLOAT32", "")
defer os.Setenv("FLOAT64", "")
defer os.Setenv("FLOAT32S", "")
defer os.Setenv("FLOAT64S", "")

cfg := Config{}
assert.NoError(t, env.Parse(&cfg))
Expand All @@ -53,6 +65,12 @@ func TestParsesEnv(t *testing.T) {
assert.Equal(t, []bool{true, true, false, true}, cfg.Bools)
d, _ := time.ParseDuration("1s")
assert.Equal(t, d, cfg.Duration)
f32 := float32(3.40282346638528859811704183484516925440e+38)
assert.Equal(t, f32, cfg.Float32)
f64 := float64(1.797693134862315708145274237317043567981e+308)
assert.Equal(t, f64, cfg.Float64)
assert.Equal(t, []float32{float32(1.0), float32(2.0), float32(3.0)}, cfg.Float32s)
assert.Equal(t, []float64{float64(1.0), float64(2.0), float64(3.0)}, cfg.Float64s)
}

func TestEmptyVars(t *testing.T) {
Expand Down Expand Up @@ -134,9 +152,9 @@ func TestParseStructWithInvalidFieldKindInt64(t *testing.T) {

func TestParseStructWithInvalidFieldKind(t *testing.T) {
type config struct {
WontWorkFloat float32 `env:"BLAH"`
WontWorkByte byte `env:"BLAH"`
}
os.Setenv("BLAH", "10.0")
os.Setenv("BLAH", "a")
cfg := config{}
assert.Error(t, env.Parse(&cfg))
}
Expand Down

0 comments on commit d0de832

Please sign in to comment.