Skip to content

Commit 7e31fa0

Browse files
committed
rework Get* methods with assertValue
1 parent 7d8c8c5 commit 7e31fa0

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ func main() {
108108
}
109109
```
110110
Those functions triggered inside `ConfigParser.Get*` methods if presented and wraps the return value.
111-
> NOTE: Since `ConvertFunc` returns `any`, the caller should guarantee type assertion to the requested type after custom processing!
112111
```go
113112
type Converter map[string]ConvertFunc
114113
```

methods.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (p *ConfigParser) Get(section, option string) (string, error) {
9393
return "", err
9494
}
9595

96-
return value.(string), nil
96+
return assertValue[string](value)
9797
}
9898

9999
func (p *ConfigParser) get(section, option string) (string, error) {
@@ -193,7 +193,7 @@ func (p *ConfigParser) GetInt64(section, option string) (int64, error) {
193193
return 0, err
194194
}
195195

196-
return value.(int64), nil
196+
return assertValue[int64](value)
197197
}
198198

199199
// GetFloat64 returns float64 representation of the named option.
@@ -212,7 +212,7 @@ func (p *ConfigParser) GetFloat64(section, option string) (float64, error) {
212212
return 0, err
213213
}
214214

215-
return value.(float64), nil
215+
return assertValue[float64](value)
216216
}
217217

218218
// GetBool returns bool representation of the named option.
@@ -231,7 +231,7 @@ func (p *ConfigParser) GetBool(section, option string) (bool, error) {
231231
return false, err
232232
}
233233

234-
return value.(bool), nil
234+
return assertValue[bool](value)
235235
}
236236

237237
// RemoveSection removes given section from the ConfigParser.
@@ -324,3 +324,16 @@ func defaultGetBool(value string) (any, error) {
324324

325325
return booleanValue, nil
326326
}
327+
328+
// assertValue tries vakue assertuon to the given type, returns error if unsuccessful.
329+
func assertValue[T ~string | ~int64 | ~float64 | ~bool](value any) (T, error) {
330+
v, ok := value.(T)
331+
if ok {
332+
return v, nil
333+
}
334+
335+
// Default value of the type.
336+
var d T
337+
338+
return d, fmt.Errorf("assertion to %T failed: incorrect value %q", d, value)
339+
}

methods_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package configparser_test
22

33
import (
4+
"strings"
5+
46
"github.com/bigkevmcd/go-configparser"
57

68
gc "gopkg.in/check.v1"
@@ -368,3 +370,27 @@ func (s *ConfigParserSuite) TestOptionsWithSectionStripsWhitespaceFromKeys(c *gc
368370
c.Assert(err, gc.IsNil)
369371
c.Assert(result, gc.DeepEquals, []string{"base_dir", "bin_dir", "foo"})
370372
}
373+
374+
func brokenConv(_ string) (any, error) { return nil, nil }
375+
376+
// Get* methods must fail with a proper error instead of a panic if type assertion has failed.
377+
func (s *ConfigParserSuite) TestGetWithAssertionError(c *gc.C) {
378+
parser, err := configparser.ParseReaderWithOptions(
379+
strings.NewReader("[testing]\nstring=new string\nint=200\nfloat=3.14159265\nbool=TRUE"),
380+
configparser.Converters(configparser.Converter{
381+
configparser.StringConv: brokenConv,
382+
configparser.IntConv: brokenConv,
383+
configparser.FloatConv: brokenConv,
384+
configparser.BoolConv: brokenConv,
385+
}),
386+
)
387+
c.Assert(err, gc.IsNil)
388+
_, err = parser.Get("testing", "string")
389+
c.Assert(err, gc.ErrorMatches, ".*assertion to string failed.*")
390+
_, err = parser.GetInt64("testing", "int")
391+
c.Assert(err, gc.ErrorMatches, ".*assertion to int64 failed.*")
392+
_, err = parser.GetFloat64("testing", "float")
393+
c.Assert(err, gc.ErrorMatches, ".*assertion to float64 failed.*")
394+
_, err = parser.GetBool("testing", "bool")
395+
c.Assert(err, gc.ErrorMatches, ".*assertion to bool failed.*")
396+
}

options.go

-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ type options struct {
2323
}
2424

2525
// Converter contains custom convert functions for available types.
26-
// The caller should guarantee type assertion to the requested type
27-
// after custom processing!
2826
type Converter map[int]ConvertFunc
2927

3028
// Predefined types for Converter.

0 commit comments

Comments
 (0)