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
4 changes: 2 additions & 2 deletions examples/exceptions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type applicationForm struct {
Country string `smname:"Country"`
Location string `smname:"Location (City)"`
CanTravel bool `smname:"Travel" smdes:"Can you travel for work?"`
BlacklistedField string `bl:""` //
BlacklistMe int
BlacklistedField string `bl:""` // field blacklisted at the type level
BlacklistMe int // field to be blacklisted with an exception list
}

func main() {
Expand Down
19 changes: 15 additions & 4 deletions menu/idx.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
// If the first non-blacklisted field is found to have an `idx` tag,
// all others will be expected to have one as well. Likewise, if it
// does not have the tag, all others will be expected not to have the tag.
// When no `idx` tags are used, the map keys and values will match.
// When no `idx` tags are used, the map keys and values will match, unless
// offset by 1 after and for each instance where a field is found to be
// blacklisted with the `bl` tag.
//
// Where validation fails, a nil map and error are returned.
func getOrderedFields(t reflect.Type) (map[int]int, error) {
Expand All @@ -30,6 +32,7 @@ func getOrderedFields(t reflect.Type) (map[int]int, error) {
}{val: false, isSet: false}

idxTagVals := map[int]int{}
blacklistCount := 0
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)

Expand All @@ -40,6 +43,7 @@ func getOrderedFields(t reflect.Type) (map[int]int, error) {
if isIndexed {
return nil, fmt.Errorf("incompatible struct tags; unexpected `idx` tag found on `bl`-tagged field %s", field.Name)
}
blacklistCount++
continue
}

Expand All @@ -57,19 +61,26 @@ func getOrderedFields(t reflect.Type) (map[int]int, error) {
if err != nil || idx < 0 {
return nil, fmt.Errorf("value for `idx` tag on field %s must be an integer >= 0", field.Name)
}
if val, ok := idxTagVals[idx]; ok {
return nil, fmt.Errorf("value %d for `idx` tag on field %s already assigned to another field", val, field.Name)
if _, ok := idxTagVals[idx]; ok {
return nil, fmt.Errorf("value %d for `idx` tag on field %s already assigned to another field", idx, field.Name)
}
idxTagVals[idx] = i

} else if isIndexed {
return nil, fmt.Errorf("unexpected `idx` tag found on field %s", field.Name)
} else {
idxTagVals[i-blacklistCount] = i
}

}

for i := 0; i < len(idxTagVals); i++ {
if _, ok := idxTagVals[i]; !ok {
return nil, fmt.Errorf("expected to find idx value of %d on some field, but found none", i)
if wantIdx.val {
return nil, fmt.Errorf("expected to find idx value of %d on some field, but found none", i)
}
return nil, fmt.Errorf("expected sequential indeces for map, but index %d is missing", i)

}
}

Expand Down
23 changes: 20 additions & 3 deletions menu/idx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ func TestGetOrderedFields(t *testing.T) {

idxTestsIsolated := []idxTest{
{
name: "no idx validation returns empty with no error",
name: "no idx validation returns matching key-value pairs",
input: struct {
s string
i int
b bool
}{},
expected: map[int]int{},
wantErr: false,
expected: map[int]int{
0: 0,
1: 1,
2: 2,
},
wantErr: false,
},
{
name: "idx validation returns indeces as specified per field",
Expand Down Expand Up @@ -81,6 +85,19 @@ func TestGetOrderedFields(t *testing.T) {
},
}
idxTestsWithBlacklistTag := []idxTest{
{
name: "no idx validation returns only bl-offset key-value pairs",
input: struct {
s string
i int `bl:""`
b bool
}{},
expected: map[int]int{
0: 0,
1: 2,
},
wantErr: false,
},
{
name: "idx validation skips bl-tagged field (first)",
input: struct {
Expand Down