From 935a75eecca9b2bb9b76d4603f4f2c09e0f5da35 Mon Sep 17 00:00:00 2001
From: aligator
Date: Mon, 25 May 2020 20:25:24 +0200
Subject: [PATCH 1/2] bugfix: use the value from the correct section when using
non unique sections in some special cases
---
struct.go | 17 +++++++++++------
struct_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/struct.go b/struct.go
index 1df5471..a9c4f40 100644
--- a/struct.go
+++ b/struct.go
@@ -278,7 +278,9 @@ func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bo
return rawName, omitEmpty, allowShadow, allowNonUnique
}
-func (s *Section) mapToField(val reflect.Value, isStrict bool) error {
+// mapToField maps the given value to the matching field of the given section.
+// The sectionNumber is the index (if non unique sections are used) to which the value should be added.
+func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int) error {
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
@@ -307,13 +309,16 @@ func (s *Section) mapToField(val reflect.Value, isStrict bool) error {
}
if isAnonymous || isStruct || isStructPtr {
- if sec, err := s.f.GetSection(fieldName); err == nil {
+ if secs, err := s.f.SectionsByName(fieldName); err == nil {
+ if len(secs) < sectionIndex {
+ return fmt.Errorf("there are not enough sections with the name %s", fieldName)
+ }
// Only set the field to non-nil struct value if we have a section for it.
// Otherwise, we end up with a non-nil struct ptr even though there is no data.
if isStructPtr && field.IsNil() {
field.Set(reflect.New(tpField.Type.Elem()))
}
- if err = sec.mapToField(field, isStrict); err != nil {
+ if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex); err != nil {
return fmt.Errorf("map to field %q: %v", fieldName, err)
}
continue
@@ -350,9 +355,9 @@ func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (
}
typ := val.Type().Elem()
- for _, sec := range secs {
+ for i, sec := range secs {
elem := reflect.New(typ)
- if err = sec.mapToField(elem, isStrict); err != nil {
+ if err = sec.mapToField(elem, isStrict, i); err != nil {
return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
}
@@ -382,7 +387,7 @@ func (s *Section) mapTo(v interface{}, isStrict bool) error {
return nil
}
- return s.mapToField(val, isStrict)
+ return s.mapToField(val, isStrict, 0)
}
// MapTo maps section to given struct.
diff --git a/struct_test.go b/struct_test.go
index 75a7ebb..57f72c4 100644
--- a/struct_test.go
+++ b/struct_test.go
@@ -414,6 +414,50 @@ func Test_MapToStructNonUniqueSections(t *testing.T) {
So(newPeerSlice[1].AllowedIPs[0], ShouldEqual, "10.2.0.3/32")
So(newPeerSlice[1].AllowedIPs[1], ShouldEqual, "fd00:2::3/128")
})
+
+ Convey("Map non unique sections with subsections to struct", func() {
+ iniFile, err := ini.LoadSources(ini.LoadOptions{AllowNonUniqueSections: true}, strings.NewReader(`
+[Section]
+FieldInSubSection = 1
+FieldInSubSection2 = 2
+FieldInSection = 3
+
+[Section]
+FieldInSubSection = 4
+FieldInSubSection2 = 5
+FieldInSection = 6
+`))
+ So(err, ShouldBeNil)
+
+ type SubSection struct {
+ FieldInSubSection string `ini:"FieldInSubSection"`
+ }
+ type SubSection2 struct {
+ FieldInSubSection2 string `ini:"FieldInSubSection2"`
+ }
+
+ type Section struct {
+ SubSection `ini:"Section"`
+ SubSection2 `ini:"Section"`
+ FieldInSection string `ini:"FieldInSection"`
+ }
+
+ type File struct {
+ Sections []Section `ini:"Section,,,nonunique"`
+ }
+
+ f := new(File)
+ err = iniFile.MapTo(f)
+ So(err, ShouldBeNil)
+
+ So(f.Sections[0].FieldInSubSection, ShouldEqual, "1")
+ So(f.Sections[0].FieldInSubSection2, ShouldEqual, "2")
+ So(f.Sections[0].FieldInSection, ShouldEqual, "3")
+
+ So(f.Sections[1].FieldInSubSection, ShouldEqual, "4")
+ So(f.Sections[1].FieldInSubSection2, ShouldEqual, "5")
+ So(f.Sections[1].FieldInSection, ShouldEqual, "6")
+ })
})
}
From be065081485549a99de76ba808bb0a510ddd7e78 Mon Sep 17 00:00:00 2001
From: aligator
Date: Tue, 26 May 2020 21:51:19 +0200
Subject: [PATCH 2/2] refactor wording and small fix
---
struct.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/struct.go b/struct.go
index a9c4f40..9be40a9 100644
--- a/struct.go
+++ b/struct.go
@@ -279,7 +279,7 @@ func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bo
}
// mapToField maps the given value to the matching field of the given section.
-// The sectionNumber is the index (if non unique sections are used) to which the value should be added.
+// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int) error {
if val.Kind() == reflect.Ptr {
val = val.Elem()
@@ -310,8 +310,8 @@ func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int)
if isAnonymous || isStruct || isStructPtr {
if secs, err := s.f.SectionsByName(fieldName); err == nil {
- if len(secs) < sectionIndex {
- return fmt.Errorf("there are not enough sections with the name %s", fieldName)
+ if len(secs) <= sectionIndex {
+ return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName)
}
// Only set the field to non-nil struct value if we have a section for it.
// Otherwise, we end up with a non-nil struct ptr even though there is no data.