Add GetSep to simplify Tag initialisation

Factor out some repetition from `parseTag()` into a `GetSep()` method so
as to simplify `parseTag()` and formalise the semantics of a separator.

The existing behaviour in corner/error cases has been preserved, but an
appropriate error is returned (currently ignored) so a future breaking
change could be made to handle these conditions.

Tests have not been added as the test files are in a separate package to
the unit under test, making direct `Tag` construction difficult. Testing
through the exported APIs is already performed in the
`FormatPlaceHolder()` tests.
This commit is contained in:
Cam Hutchison
2020-06-02 11:19:45 +10:00
committed by Alec Thomas
parent f19f1031c0
commit d4822839a2
+22 -16
View File
@@ -151,26 +151,12 @@ func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
t.Short, _ = t.GetRune("short")
t.Hidden = t.Has("hidden")
t.Format = t.Get("format")
t.Sep, _ = t.GetSep("sep", ',')
t.MapSep, _ = t.GetSep("mapsep", ';')
t.Group = t.Get("group")
t.Xor = t.Get("xor")
t.Prefix = t.Get("prefix")
t.Embed = t.Has("embed")
if t.Get("sep") == "none" {
t.Sep = -1
} else {
t.Sep, _ = t.GetRune("sep")
if t.Sep == 0 {
t.Sep = ','
}
}
if t.Get("mapsep") == "none" {
t.MapSep = -1
} else {
t.MapSep, _ = t.GetRune("mapsep")
if t.MapSep == 0 {
t.MapSep = ';'
}
}
t.Vars = Vars{}
for _, set := range t.GetAll("set") {
parts := strings.SplitN(set, "=", 2)
@@ -232,3 +218,23 @@ func (t *Tag) GetRune(k string) (rune, error) {
}
return r, nil
}
// GetSep parses the given tag as a rune separator, allowing for a default or none.
// The separator is returned, or -1 if "none" is specified. If the tag value is an
// invalid utf8 sequence, the default rune is returned as well as an error. If the
// tag value is more than one rune, the first rune is returned as well as an error.
func (t *Tag) GetSep(k string, dflt rune) (rune, error) {
tv := t.Get(k)
if tv == "none" {
return -1, nil
} else if tv == "" {
return dflt, nil
}
r, size := utf8.DecodeRuneInString(tv)
if r == utf8.RuneError {
return dflt, fmt.Errorf(`%v:"%v" has a rune error`, k, tv)
} else if size != len(tv) {
return r, fmt.Errorf(`%v:"%v" is more than a single rune`, k, tv)
}
return r, nil
}