8000 struct: map slices of struct pointers by team-humaki · Pull Request #396 · go-ini/ini · GitHub
[go: up one dir, main page]

Skip to content
Open
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
22 changes: 17 additions & 5 deletions struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,21 +358,33 @@ func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int,
}

// mapToSlice maps all sections with the same name and returns the new value.
// The type of the Value must be a slice.
// The type of the Value must be a slice of structs or pointers to structs.
func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) {
secs, err := s.f.SectionsByName(secName)
if err != nil {
return reflect.Value{}, err
}

typ := val.Type().Elem()
elemType := val.Type().Elem()
isPtr := elemType.Kind() == reflect.Pointer
structType := elemType
if isPtr {
if elemType.Elem().Kind() != reflect.Struct {
return reflect.Value{}, fmt.Errorf("slice of pointers to non-struct type %s", elemType)
}
structType = elemType.Elem()
}

for i, sec := range secs {
elem := reflect.New(typ)
elem := reflect.New(structType)
if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil {
return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
}

val = reflect.Append(val, elem.Elem())
if isPtr {
val = reflect.Append(val, elem)
} else {
val = reflect.Append(val, elem.Elem())
}
}
return val, nil
}
Expand Down
32 changes: 32 additions & 0 deletions struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,38 @@ func Test_MapToStructNonUniqueSections(t *testing.T) {
assert.Equal(t, "fd00:2::3/128", newPeerSlice[1].AllowedIPs[1])
})

t.Run("map non unique section to slice of struct pointers", func(t *testing.T) {
type Config struct {
Peers []*testPeer `ini:"Peer,nonunique"`
}

f, err := LoadSources(LoadOptions{AllowNonUniqueSections: true}, []byte(confNonUniqueSectionDataStruct))
require.NoError(t, err)

cfg := new(Config)
require.NoError(t, f.MapTo(cfg))
require.Len(t, cfg.Peers, 2)
require.NotNil(t, cfg.Peers[0])
require.NotNil(t, cfg.Peers[1])

assert.Equal(t, "pubClientKey", cfg.Peers[0].PublicKey)
assert.Equal(t, "psKey", cfg.Peers[0].PresharedKey)
assert.Equal(t, "10.2.0.2/32", cfg.Peers[0].AllowedIPs[0])
assert.Equal(t, "fd00:2::2/128", cfg.Peers[0].AllowedIPs[1])

assert.Equal(t, "pubClientKey2", cfg.Peers[1].PublicKey)
assert.Equal(t, "psKey2", cfg.Peers[1].PresharedKey)
assert.Equal(t, "10.2.0.3/32", cfg.Peers[1].AllowedIPs[0])
assert.Equal(t, "fd00:2::3/128", cfg.Peers[1].AllowedIPs[1])

ptrSlice := make([]*testPeer, 0)
require.NoError(t, f.Section("Peer").MapTo(&ptrSlice))
require.Len(t, ptrSlice, 2)
require.NotNil(t, ptrSlice[0])
assert.Equal(t, "pubClientKey", ptrSlice[0].PublicKey)
assert.Equal(t, "pubClientKey2", ptrSlice[1].PublicKey)
})

t.Run("map non unique sections with subsections to struct", func(t *testing.T) {
iniFile, err := LoadSources(LoadOptions{AllowNonUniqueSections: true}, strings.NewReader(`
[Section]
Expand Down
0