Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: respect nil values #11

Merged
merged 5 commits into from
Mar 17, 2021
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
22 changes: 22 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Description

## Problem
A short description of the problem this PR is addressing.

## Solution
A short description of the chosen method to resolve the problem
with an overview of the logic and implementation details when needed.

## Notes
Other notes that you want to share but do not fit into _Problem_ or _Solution_.

### Checklist
- [ ] The title starts either with `feat(area)`, `fix(area)`, or `chore(area)`
- `feat` should be used if this pull request implements a new feature
- `fix` should be used if this pull request fixes a bug
- `chore` should be used for maintenance changes
- `area` should be describing the relevant section of the project
- [ ] ran `go mod tidy`
- [ ] ran `go mod vendor`
- [ ] ran `docker run --rm -ti -v $PWD:/workspace -w /workspace eunts/minigo:latest --template -o /workspace/README.md /workspace/README.md.template`

16 changes: 16 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: 2
updates:
- package-ecosystem: "gomod"
open-pull-requests-limit: 10
directory: "/"
schedule:
interval: daily
time: "04:00"

- package-ecosystem: "github-actions"
open-pull-requests-limit: 10
directory: "/"
schedule:
interval: "daily"
time: "04:00"

38 changes: 38 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
categories:
- title: '🚀 Features'
label: 'feature'
- title: '🐛 Bug Fixes'
label: 'fix'
- title: '🧰 Maintenance'
label: 'chore'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: patch
autolabeler:
- label: 'feature'
title:
- '/^feat/i'
- '/^feature/i'
- label: 'fix'
title:
- '/^fix/i'
- label: 'chore'
title:
- '/^chore/i'
template: |
## Changes

$CHANGES

66 changes: 66 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: CI
on:
push:
jobs:
golangci-lint:
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@v2
-
name: lint
continue-on-error: false
uses: golangci/golangci-lint-action@v2
with:
version: latest
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

vulns:
name: Vulnerability scanner
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@v2
-
uses: actions/setup-go@v2
# We cannot use nancy-github-action because it is outdated, so it's better to use the latest
# docker image for the validation
-
name: nancy
run: go list -json -m all | docker run -i sonatypecommunity/nancy:latest

test:
strategy:
matrix:
go-version: [1.14.x, 1.15.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
-
name: Install Go
uses: actions/setup-go@v1
with:
go-version: ${{ matrix.go-version }}
-
name: Checkout code
uses: actions/checkout@v2
-
name: Test
run: go test -v -count=1 -coverprofile="coverage-${{ matrix.platform }}-${{ matrix.go-version }}.txt" -covermode=atomic ./...
-
name: Send coverage
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: coverage-${{ matrix.platform }}-${{ matrix.go-version }}.txt
flag-name: ${{ matrix.platform }}-${{ matrix.go-version }}
parallel: true

# notifies that all test jobs are finished.
finish:
needs: test
runs-on: ubuntu-latest
steps:
- uses: shogo82148/actions-goveralls@v1
with:
parallel-finished: true
34 changes: 0 additions & 34 deletions .github/workflows/fill-readme-with-samples.yml

This file was deleted.

17 changes: 0 additions & 17 deletions .github/workflows/golangci-lint-runner.yml

This file was deleted.

16 changes: 16 additions & 0 deletions .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Release Drafter
on:
push:
# branches to consider in the event; optional, defaults to all
branches:
- master
jobs:
update_release_draft:
runs-on: ubuntu-latest
steps:
# Drafts your next Release notes as Pull Requests are merged into "master"
- uses: release-drafter/release-drafter@v5
with:
config-name: release-drafter.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
14 changes: 0 additions & 14 deletions .travis.yml

This file was deleted.

10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# go-convert [![Travis](https://img.shields.io/travis/Eun/go-convert.svg)](https://travis-ci.org/Eun/go-convert) [![Codecov](https://img.shields.io/codecov/c/github/Eun/go-convert.svg)](https://codecov.io/gh/Eun/go-convert) [![GoDoc](https://godoc.org/github.com/Eun/go-convert?status.svg)](https://godoc.org/github.com/Eun/go-convert) [![go-report](https://goreportcard.com/badge/github.com/Eun/go-convert)](https://goreportcard.com/report/github.com/Eun/go-convert)
# go-convert [![Actions Status](https://github.com/Eun/go-convert/workflows/CI/badge.svg)](https://github.com/Eun/go-convert/actions) [![Coverage Status](https://coveralls.io/repos/github/Eun/go-convert/badge.svg?branch=master)](https://coveralls.io/github/Eun/go-convert?branch=master) [![PkgGoDev](https://img.shields.io/badge/pkg.go.dev-reference-blue)](https://pkg.go.dev/github.com/Eun/go-convert) [![GoDoc](https://godoc.org/github.com/Eun/go-convert?status.svg)](https://godoc.org/github.com/Eun/go-convert) [![go-report](https://goreportcard.com/badge/github.com/Eun/go-convert)](https://goreportcard.com/report/github.com/Eun/go-convert)
Convert a value into another type.

```bash
Expand Down Expand Up @@ -144,13 +144,13 @@ func (user *User) ConvertRecipes() []convert.Recipe {
return convert.MustMakeRecipes(
// convert string into Roles
func(_ convert.Converter, in string, out *Roles) error {
(*out).IsAdmin = false
(*out).IsDeveloper = false
out.IsAdmin = false
out.IsDeveloper = false
if strings.Contains(in, "A") {
(*out).IsAdmin = true
out.IsAdmin = true
}
if strings.Contains(in, "D") {
(*out).IsDeveloper = true
out.IsDeveloper = true
}
return nil
},
Expand Down
7 changes: 5 additions & 2 deletions .github/README.md.template → README.md.template
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<$
import "io/ioutil"
import (
"fmt"
"io/ioutil"
)
func printFile(f string) {
buf, err := ioutil.ReadFile(f)
if err != nil {
panic(err)
}
fmt.Print(string(buf))
}
$># go-convert [![Travis](https://img.shields.io/travis/Eun/go-convert.svg)](https://travis-ci.org/Eun/go-convert) [![Codecov](https://img.shields.io/codecov/c/github/Eun/go-convert.svg)](https://codecov.io/gh/Eun/go-convert) [![GoDoc](https://godoc.org/github.com/Eun/go-convert?status.svg)](https://godoc.org/github.com/Eun/go-convert) [![go-report](https://goreportcard.com/badge/github.com/Eun/go-convert)](https://goreportcard.com/report/github.com/Eun/go-convert)
$># go-convert [![Actions Status](https://github.com/Eun/go-convert/workflows/CI/badge.svg)](https://github.com/Eun/go-convert/actions) [![Coverage Status](https://coveralls.io/repos/github/Eun/go-convert/badge.svg?branch=master)](https://coveralls.io/github/Eun/go-convert?branch=master) [![PkgGoDev](https://img.shields.io/badge/pkg.go.dev-reference-blue)](https://pkg.go.dev/github.com/Eun/go-convert) [![GoDoc](https://godoc.org/github.com/Eun/go-convert?status.svg)](https://godoc.org/github.com/Eun/go-convert) [![go-report](https://goreportcard.com/badge/github.com/Eun/go-convert)](https://goreportcard.com/report/github.com/Eun/go-convert)
Convert a value into another type.

```bash
Expand Down
8 changes: 6 additions & 2 deletions convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"reflect"
)

//nolint:golint // silence consider calling this Recipes
// ConvertRecipes can be used to add recipes to a type in a convenient way
type ConvertRecipes interface {
ConvertRecipes() []Recipe
Expand Down Expand Up @@ -191,8 +192,7 @@ func (conv defaultConverter) convertNow(src, dst, out reflect.Value, options ...
}
if src.IsNil() {
debug(">> src is nil\n")
// make a new instance if src is nil
return conv.ConvertReflectValue(reflect.Zero(src.Type().Elem()), dst, options...)
return nil
}
}

Expand Down Expand Up @@ -270,6 +270,7 @@ func MustConvert(src, dst interface{}, options ...Options) {
defaultConverterInstance.MustConvert(src, dst, options...)
}

//nolint:golint // silence consider calling this ReflectValue
// ConvertReflectValue converts the specified reflect value to the specified type
// The behavior can be influenced by using the options
func ConvertReflectValue(src, dstTyp reflect.Value, options ...Options) error {
Expand All @@ -293,6 +294,9 @@ func printValue(value reflect.Value) string {
for v.IsValid() {
switch v.Kind() {
case reflect.Ptr, reflect.Interface:
if v.IsNil() {
return "<nil>"
}
v = v.Elem()
default:
if v.CanInterface() {
Expand Down
8 changes: 4 additions & 4 deletions convert_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ func ExampleNew() {
Recipes: convert.MustMakeRecipes(
// convert string into Roles
func(_ convert.Converter, in string, out *Roles) error {
(*out).IsAdmin = false
(*out).IsDeveloper = false
out.IsAdmin = false
out.IsDeveloper = false
if strings.Contains(in, "A") {
(*out).IsAdmin = true
out.IsAdmin = true
}
if strings.Contains(in, "D") {
(*out).IsDeveloper = true
out.IsDeveloper = true
}
return nil
},
Expand Down
8 changes: 4 additions & 4 deletions examples/inline_recipes/inline_recipes.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ func (user *User) ConvertRecipes() []convert.Recipe {
return convert.MustMakeRecipes(
// convert string into Roles
func(_ convert.Converter, in string, out *Roles) error {
(*out).IsAdmin = false
(*out).IsDeveloper = false
out.IsAdmin = false
out.IsDeveloper = false
if strings.Contains(in, "A") {
(*out).IsAdmin = true
out.IsAdmin = true
}
if strings.Contains(in, "D") {
(*out).IsDeveloper = true
out.IsDeveloper = true
}
return nil
},
Expand Down
2 changes: 1 addition & 1 deletion int.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func genericIntConvert(in reflect.Value) (bool, int64, error) {

// check for struct.Int64()
if i, ok := in.Interface().(toInt64); ok {
return true, int64(i.Int64()), nil
return true, i.Int64(), nil
}
if i, ok := in.Interface().(toInt64WithErr); ok {
v, err := i.Int64()
Expand Down
9 changes: 9 additions & 0 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ func (stdRecipes) structToMap(c Converter, in StructValue, out MapValue) error {
valueValue = reflect.New(existingValue.Type())
valueValue.Elem().Set(existingValue)
} else {
// if the source is nil and the destination map does not expect us to have the field
// skip
switch in.Field(i).Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
if in.Field(i).IsNil() {
continue
}
}

valueValue = reflect.New(valueType)
}

Expand Down
4 changes: 2 additions & 2 deletions map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package convert_test

import (
"testing"

"time"

"github.com/Eun/go-convert/internal/testhelpers"
Expand Down Expand Up @@ -91,7 +90,8 @@ func TestMap(t *testing.T) {
{map[string]User{"Foo": {"Joe"}}, map[string]string{}, map[string]string{}, "unable to convert map[string]convert_test.User to map[string]string: unable to convert convert_test.User to string: convert_test.User has no String() function", nil},
{UserAndCompany{"Joe", Company{"Wood Inc"}}, map[string]string{}, map[string]string{}, "unable to convert convert_test.UserAndCompany to map[string]string: unable to convert convert_test.Company to string: convert_test.Company has no String() function", nil},

{TimeStruct{}, map[string]string{}, map[string]string{"CreatedOn": "0001-01-01 00:00:00 +0000 UTC"}, "", nil},
{TimeStruct{}, map[string]string{}, map[string]string{}, "", nil},
{TimeStruct{}, map[string]string{"CreatedOn": ""}, map[string]string{"CreatedOn": ""}, "", nil},
{TimeStruct{CreatedOn: &beginningOfTime}, map[string]string{}, map[string]string{"CreatedOn": "1970-01-01 00:00:00 +0000 UTC"}, "", nil},
}

Expand Down
2 changes: 1 addition & 1 deletion option.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package convert

// Options can be used to alter the behaviour of the converter
// Options can be used to alter the behavior of the converter
type Options struct {
// SkipUnknownFields can be used to ignore fields that are not existent in the destination type
//
Expand Down
Loading