From 65a6292f0157eff210d03ed1bf6c59b190b8b906 Mon Sep 17 00:00:00 2001 From: "Phillip T. George" Date: Thu, 6 Sep 2018 13:38:39 -0500 Subject: [PATCH] Allow strings "true", "false", "1" and "0" to be used where booleans are expected There is precedent for allowing strings containing digits where numbers are expected, and so this extends that to also allow for boolean values to be given as strings. This applies only to callers going through the decoder API. Direct access via the AST will reflect exactly what was given in the input configuration. --- decoder.go | 15 +++++++--- decoder_test.go | 45 +++++++++++++++++++++++++++++ test-fixtures/basic_bool.hcl | 1 + test-fixtures/basic_bool_int.hcl | 1 + test-fixtures/basic_bool_string.hcl | 1 + 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 test-fixtures/basic_bool.hcl create mode 100644 test-fixtures/basic_bool_int.hcl create mode 100644 test-fixtures/basic_bool_string.hcl diff --git a/decoder.go b/decoder.go index bed9ebb..dc9d45a 100644 --- a/decoder.go +++ b/decoder.go @@ -117,10 +117,17 @@ func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error { switch n := node.(type) { case *ast.LiteralType: - if n.Token.Type == token.BOOL { - v, err := strconv.ParseBool(n.Token.Text) - if err != nil { - return err + switch n.Token.Type { + case token.BOOL, token.STRING, token.NUMBER: + var v bool + s := strings.ToLower(strings.Replace(n.Token.Text, "\"", "", -1)) + switch s { + case "1", "true": + v = true + case "0", "false": + v = false + default: + return fmt.Errorf("decodeBool: Unknown value for boolean: %s", n.Token.Text) } result.Set(reflect.ValueOf(v)) diff --git a/decoder_test.go b/decoder_test.go index 8682f47..3ffdcfd 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -794,6 +794,51 @@ func TestDecode_interfaceNonPointer(t *testing.T) { } } +func TestDecode_boolString(t *testing.T) { + var value struct { + Boolean bool + } + + err := Decode(&value, testReadFile(t, "basic_bool_string.hcl")) + if err != nil { + t.Fatalf("err: %s", err) + } + + if value.Boolean != true { + t.Fatalf("bad: %#v", value.Boolean) + } +} + +func TestDecode_boolInt(t *testing.T) { + var value struct { + Boolean bool + } + + err := Decode(&value, testReadFile(t, "basic_bool_int.hcl")) + if err != nil { + t.Fatalf("err: %s", err) + } + + if value.Boolean != true { + t.Fatalf("bad: %#v", value.Boolean) + } +} + +func TestDecode_bool(t *testing.T) { + var value struct { + Boolean bool + } + + err := Decode(&value, testReadFile(t, "basic_bool.hcl")) + if err != nil { + t.Fatalf("err: %s", err) + } + + if value.Boolean != true { + t.Fatalf("bad: %#v", value.Boolean) + } +} + func TestDecode_intString(t *testing.T) { var value struct { Count int diff --git a/test-fixtures/basic_bool.hcl b/test-fixtures/basic_bool.hcl new file mode 100644 index 0000000..024c06c --- /dev/null +++ b/test-fixtures/basic_bool.hcl @@ -0,0 +1 @@ +boolean = true diff --git a/test-fixtures/basic_bool_int.hcl b/test-fixtures/basic_bool_int.hcl new file mode 100644 index 0000000..9e1b45e --- /dev/null +++ b/test-fixtures/basic_bool_int.hcl @@ -0,0 +1 @@ +boolean = 1 diff --git a/test-fixtures/basic_bool_string.hcl b/test-fixtures/basic_bool_string.hcl new file mode 100644 index 0000000..4b805de --- /dev/null +++ b/test-fixtures/basic_bool_string.hcl @@ -0,0 +1 @@ +boolean = "trUe"