diff --git a/.github/workflows/codetests.yml b/.github/workflows/codetests.yml index c9a2866..367567a 100644 --- a/.github/workflows/codetests.yml +++ b/.github/workflows/codetests.yml @@ -14,9 +14,9 @@ jobs: runs-on: ${{ matrix.os }}-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: stable - name: go-test run: go test -race -covermode=atomic ./... # Runs golangci-lint on macos against freebsd and macos. @@ -31,12 +31,12 @@ jobs: steps: - uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: stable - uses: actions/checkout@v4 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: 'v1.52' + version: 'v1.53' # Runs golangci-lint on linux against linux and windows. golangci-linux: strategy: @@ -47,11 +47,11 @@ jobs: env: GOOS: ${{ matrix.os }} steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: stable - uses: actions/checkout@v4 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: 'v1.52' \ No newline at end of file + version: 'v1.53' \ No newline at end of file diff --git a/go.sum b/go.sum index 2d8d486..479781e 100644 --- a/go.sum +++ b/go.sum @@ -8,10 +8,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/parse_test.go b/parse_test.go index 392a8ec..a51fa55 100644 --- a/parse_test.go +++ b/parse_test.go @@ -17,7 +17,7 @@ func TestParseInt(t *testing.T) { i, err := parseInt(t, fmt.Sprintf("%d", t)) assert.EqualValues(t, i) - assert.Nil(err) + assert.NoError(err) } } @@ -34,7 +34,7 @@ func TestParseByteSlice(t *testing.T) { //nolint:paralleltest ok, err := UnmarshalENV(testStruct, "D") assert.True(ok) - assert.Nil(err) + assert.NoError(err) assert.Equal("byte slice incoming", string(testStruct.F)) } @@ -54,7 +54,7 @@ func TestParseUint(t *testing.T) { err := parseUint(theField, t, "1") assert.EqualValues(1, embeddedInt.F) - assert.Nil(err) + assert.NoError(err) } type test2 struct { diff --git a/unparse.go b/unparse.go index 0117a17..eca5d14 100644 --- a/unparse.go +++ b/unparse.go @@ -88,11 +88,12 @@ func (p *unparser) Anything(field reflect.Value, tag string, omitempty bool) (Pa } } -func (p *unparser) Interface(field reflect.Value, tag string, _ bool) (Pairs, bool, error) { +func (p *unparser) Interface(field reflect.Value, tag string, omitempty bool) (Pairs, bool, error) { output := Pairs{} if !field.CanAddr() || !field.Addr().CanInterface() { - return output, false, nil + pairs, err := p.Member(reflect.ValueOf(field.Interface()), tag, omitempty) + return pairs, true, err } if v, ok := field.Addr().Interface().(ENVMarshaler); ok { @@ -137,7 +138,7 @@ func (p *unparser) Interface(field reflect.Value, tag string, _ bool) (Pairs, bo } // Member parses non-struct, non-slice struct-member types. -func (p *unparser) Member(field reflect.Value, tag string, _ bool) (Pairs, error) { //nolint:cyclop +func (p *unparser) Member(field reflect.Value, tag string, omitempty bool) (Pairs, error) { //nolint:cyclop output := Pairs{} switch val := field.Interface().(type) { @@ -175,7 +176,34 @@ func (p *unparser) Member(field reflect.Value, tag string, _ bool) (Pairs, error case time.Duration: output.Set(tag, (time.Duration(field.Int()) * time.Nanosecond).String()) case bool: - output.Set(tag, fmt.Sprintf("%v", field.Bool())) + output.Set(tag, strconv.FormatBool(field.Bool())) + default: + return p.kindMember(field, tag, omitempty) + } + + return output, nil +} + +func (p *unparser) kindMember(field reflect.Value, tag string, _ bool) (Pairs, error) { + output := Pairs{} + + switch field.Kind() { + case reflect.String: + output.Set(tag, field.String()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + val, _ := field.Interface().(uint64) + output.Set(tag, strconv.FormatUint(val, base10)) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val, _ := field.Interface().(int64) + output.Set(tag, strconv.FormatInt(val, base10)) + case reflect.Float64: + val, _ := field.Interface().(float64) + output.Set(tag, strconv.FormatFloat(val, 'f', -1, bits64)) + case reflect.Float32: + val, _ := field.Interface().(float32) + output.Set(tag, strconv.FormatFloat(float64(val), 'f', -1, bits32)) + case reflect.Bool: + output.Set(tag, strconv.FormatBool(field.Bool())) } return output, nil diff --git a/unparse_test.go b/unparse_test.go index 6ae802d..f6e83b6 100644 --- a/unparse_test.go +++ b/unparse_test.go @@ -12,29 +12,30 @@ import ( ) type MarshalTest struct { - Name string `xml:"name,omitempty"` - Pass string `xml:"pass,omitempty"` - IP net.IP `xml:"ip,omitempty"` - Smap map[string]string `xml:"smap,omitempty"` - List []string `xml:"list,omitempty"` - Byte []byte `xml:"byte,omitempty"` - Dur time.Duration `xml:"dur,omitempty"` - Time time.Time `xml:"time,omitempty"` - Err error `xml:"err,omitempty"` - Bool bool `xml:"bool,omitempty"` - Uint uint8 `xml:"uint,omitempty"` - Un16 uint16 `xml:"un16,omitempty"` - Un32 uint32 `xml:"un32,omitempty"` - Un64 uint64 `xml:"un64,omitempty"` - Int int `xml:"int,omitempty"` - In8 int8 `xml:"in8,omitempty"` - In16 int16 `xml:"in16,omitempty"` - In32 int32 `xml:"in32,omitempty"` - In64 int64 `xml:"in64,omitempty"` - Fl32 float32 `xml:"fl32,omitempty"` - Fl64 float64 `xml:"fl64,omitempty"` - Test2 marshalTest2 `xml:"test2"` - Test *MarshalTest `xml:"test"` + Name string `xml:"name,omitempty"` + Pass string `xml:"pass,omitempty"` + IP net.IP `xml:"ip,omitempty"` + Smap map[string]string `xml:"smap,omitempty"` + Imap map[string]interface{} `xml:"imap,omitempty"` + List []string `xml:"list,omitempty"` + Byte []byte `xml:"byte,omitempty"` + Dur time.Duration `xml:"dur,omitempty"` + Time time.Time `xml:"time,omitempty"` + Err error `xml:"err,omitempty"` + Bool bool `xml:"bool,omitempty"` + Uint uint8 `xml:"uint,omitempty"` + Un16 uint16 `xml:"un16,omitempty"` + Un32 uint32 `xml:"un32,omitempty"` + Un64 uint64 `xml:"un64,omitempty"` + Int int `xml:"int,omitempty"` + In8 int8 `xml:"in8,omitempty"` + In16 int16 `xml:"in16,omitempty"` + In32 int32 `xml:"in32,omitempty"` + In64 int64 `xml:"in64,omitempty"` + Fl32 float32 `xml:"fl32,omitempty"` + Fl64 float64 `xml:"fl64,omitempty"` + Test2 marshalTest2 `xml:"test2"` + Test *MarshalTest `xml:"test"` } type marshalTest2 struct { @@ -70,8 +71,13 @@ func marshalTestData() (*MarshalTest, int) { Test: &MarshalTest{ Name: "subtest", // 24 Err: fmt.Errorf("this long error is here 2 line up the comments"), // 25 - }, // + 3 more from marshalTest2.Name2. That puts the total var count at 28 - }, 28 // set the count here. + }, Imap: map[string]interface{}{ + "orange": "sunset", // 26 + "pink": "sunrise", // 27 + "counter": 8967, // 28 + "floater": 3.1415926, // 29 + }, // + 3 more from marshalTest2.Name2. That puts the total var count at 32. + }, 32 // set the count here. } func TestDeconStruct(t *testing.T) { @@ -87,6 +93,10 @@ func TestDeconStruct(t *testing.T) { assert.Equal(data.IP.String(), pairs["PFX_IP"]) assert.Equal(data.Smap["blue"], pairs["PFX_SMAP_blue"]) assert.Equal(data.Smap["red"], pairs["PFX_SMAP_red"]) + assert.Equal(data.Imap["orange"], pairs["PFX_IMAP_orange"]) + assert.Equal(data.Imap["pink"], pairs["PFX_IMAP_pink"]) + assert.Equal(fmt.Sprint(data.Imap["counter"]), pairs["PFX_IMAP_counter"]) + assert.Equal(fmt.Sprint(data.Imap["floater"]), pairs["PFX_IMAP_floater"]) assert.Equal(data.List[0], pairs["PFX_LIST_0"]) assert.Equal(data.List[1], pairs["PFX_LIST_1"]) assert.Equal(string(data.Byte), pairs["PFX_BYTE"])