Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
test:
strategy:
matrix:
go-version: [ stable, oldstable ]
go-version: [ 1.17.x, stable, oldstable ]
runs-on: ubuntu-latest
steps:
- name: Install Go
Expand Down
56 changes: 56 additions & 0 deletions value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package vars

import (
"encoding/json"
"fmt"
"strconv"
)

// Infer parses a value from a string into a suitable type.
// If s only contains digits, int64 is returned.
// If s is parsed as float, float64 is returned.
// If s has unquoted values of true or false, bool is returned.
// If s is equal to unquoted null, nil is returned.
// If s starts with double quote ", string decoded from JSON is returned (mind JSON escaping rules).
// If s starts with [ or {, any decoded from JSON is returned.
// Otherwise, s is returned as is.
func Infer(s string) interface{} {
switch s {
case "":
return ""
case "true":
return true
case "false":
return false
case "null":
return nil
}

if s[0] == '"' {
var v string
if err := json.Unmarshal([]byte(s), &v); err != nil {
return fmt.Errorf("infer string value %s: %w", s, err)
}

return v
}

if s[0] == '[' || s[0] == '{' {
var v interface{}
if err := json.Unmarshal([]byte(s), &v); err != nil {
return fmt.Errorf("infer JSON value %s: %w", s, err)
}

return v
}

if i, err := strconv.ParseInt(s, 10, 64); err == nil {
return i
}

if f, err := strconv.ParseFloat(s, 64); err == nil {
return f
}

return s

Check notice on line 55 in value.go

View workflow job for this annotation

GitHub Actions / test (stable)

1 statement(s) are not covered by tests.
}
36 changes: 36 additions & 0 deletions value_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package vars_test

import (
"testing"

"github.com/godogx/vars"
"github.com/stretchr/testify/assert"
)

func TestInfer(t *testing.T) {
for _, tc := range []struct {
s string
v interface{}
}{
{"", ""},
{"123", int64(123)},
{"123.45", 123.45},
{"true", true},
{"false", false},
{"null", nil},
{`"bla\nbla"`, "bla\nbla"},
{`"bla\nbl...`, "infer string value \"bla\\nbl...: unexpected end of JSON input"},
{`{"foo":"bar"}`, map[string]interface{}{"foo": "bar"}},
{`["abc", 1, false, null]`, []interface{}{"abc", 1.0, false, nil}},
{`{"foo":"ba....`, "infer JSON value {\"foo\":\"ba....: unexpected end of JSON input"},
} {
t.Run(tc.s, func(t *testing.T) {
v := vars.Infer(tc.s)
if err, ok := v.(error); ok {
v = err.Error()
}

assert.Equal(t, tc.v, v)
})
}
}
Loading