summaryrefslogtreecommitdiff
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/gocarina/gocsv/.travis.yml3
-rw-r--r--vendor/github.com/gocarina/gocsv/README.md2
-rw-r--r--vendor/github.com/gocarina/gocsv/csv.go76
-rw-r--r--vendor/github.com/gocarina/gocsv/decode.go69
-rw-r--r--vendor/github.com/gocarina/gocsv/encode.go32
-rw-r--r--vendor/github.com/gocarina/gocsv/go.mod3
-rw-r--r--vendor/github.com/gocarina/gocsv/reflect.go95
-rw-r--r--vendor/github.com/gocarina/gocsv/safe_csv.go6
-rw-r--r--vendor/github.com/gocarina/gocsv/types.go22
-rw-r--r--vendor/github.com/gocarina/gocsv/unmarshaller.go20
-rw-r--r--vendor/github.com/spf13/pflag/go.mod3
-rw-r--r--vendor/github.com/spf13/pflag/go.sum0
12 files changed, 273 insertions, 58 deletions
diff --git a/vendor/github.com/gocarina/gocsv/.travis.yml b/vendor/github.com/gocarina/gocsv/.travis.yml
index 4f2ee4d..61c24c6 100644
--- a/vendor/github.com/gocarina/gocsv/.travis.yml
+++ b/vendor/github.com/gocarina/gocsv/.travis.yml
@@ -1 +1,4 @@
language: go
+arch:
+ - amd64
+ - ppc64le
diff --git a/vendor/github.com/gocarina/gocsv/README.md b/vendor/github.com/gocarina/gocsv/README.md
index e606ac7..6f0d344 100644
--- a/vendor/github.com/gocarina/gocsv/README.md
+++ b/vendor/github.com/gocarina/gocsv/README.md
@@ -152,7 +152,7 @@ func main() {
...
- gocsv.SetCSVWriter(func(out io.Writer) *SafeCSVWriter {
+ gocsv.SetCSVWriter(func(out io.Writer) *gocsv.SafeCSVWriter {
writer := csv.NewWriter(out)
writer.Comma = '|'
return gocsv.NewSafeCSVWriter(writer)
diff --git a/vendor/github.com/gocarina/gocsv/csv.go b/vendor/github.com/gocarina/gocsv/csv.go
index 22846c0..3ba3efb 100644
--- a/vendor/github.com/gocarina/gocsv/csv.go
+++ b/vendor/github.com/gocarina/gocsv/csv.go
@@ -127,6 +127,15 @@ func MarshalString(in interface{}) (out string, err error) {
return bufferString.String(), nil
}
+// MarshalStringWithoutHeaders returns the CSV string from the interface.
+func MarshalStringWithoutHeaders(in interface{}) (out string, err error) {
+ bufferString := bytes.NewBufferString(out)
+ if err := MarshalWithoutHeaders(in, bufferString); err != nil {
+ return "", err
+ }
+ return bufferString.String(), nil
+}
+
// MarshalBytes returns the CSV bytes from the interface.
func MarshalBytes(in interface{}) (out []byte, err error) {
bufferString := bytes.NewBuffer(out)
@@ -149,17 +158,22 @@ func MarshalWithoutHeaders(in interface{}, out io.Writer) (err error) {
}
// MarshalChan returns the CSV read from the channel.
-func MarshalChan(c <-chan interface{}, out *SafeCSVWriter) error {
- return writeFromChan(out, c)
+func MarshalChan(c <-chan interface{}, out CSVWriter) error {
+ return writeFromChan(out, c, false)
+}
+
+// MarshalChanWithoutHeaders returns the CSV read from the channel.
+func MarshalChanWithoutHeaders(c <-chan interface{}, out CSVWriter) error {
+ return writeFromChan(out, c, true)
}
// MarshalCSV returns the CSV in writer from the interface.
-func MarshalCSV(in interface{}, out *SafeCSVWriter) (err error) {
+func MarshalCSV(in interface{}, out CSVWriter) (err error) {
return writeTo(out, in, false)
}
// MarshalCSVWithoutHeaders returns the CSV in writer from the interface.
-func MarshalCSVWithoutHeaders(in interface{}, out *SafeCSVWriter) (err error) {
+func MarshalCSVWithoutHeaders(in interface{}, out CSVWriter) (err error) {
return writeTo(out, in, true)
}
@@ -216,6 +230,43 @@ func UnmarshalCSV(in CSVReader, out interface{}) error {
return readTo(csvDecoder{in}, out)
}
+// UnmarshalCSVToMap parses a CSV of 2 columns into a map.
+func UnmarshalCSVToMap(in CSVReader, out interface{}) error {
+ decoder := NewSimpleDecoderFromCSVReader(in)
+ header, err := decoder.GetCSVRow()
+ if err != nil {
+ return err
+ }
+ if len(header) != 2 {
+ return fmt.Errorf("maps can only be created for csv of two columns")
+ }
+ outValue, outType := getConcreteReflectValueAndType(out)
+ if outType.Kind() != reflect.Map {
+ return fmt.Errorf("cannot use " + outType.String() + ", only map supported")
+ }
+ keyType := outType.Key()
+ valueType := outType.Elem()
+ outValue.Set(reflect.MakeMap(outType))
+ for {
+ key := reflect.New(keyType)
+ value := reflect.New(valueType)
+ line, err := decoder.GetCSVRow()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ return err
+ }
+ if err := setField(key, line[0], false); err != nil {
+ return err
+ }
+ if err := setField(value, line[1], false); err != nil {
+ return err
+ }
+ outValue.SetMapIndex(key.Elem(), value.Elem())
+ }
+ return nil
+}
+
// UnmarshalToChan parses the CSV from the reader and send each value in the chan c.
// The channel must have a concrete type.
func UnmarshalToChan(in io.Reader, c interface{}) error {
@@ -278,7 +329,13 @@ func UnmarshalToCallback(in io.Reader, f interface{}) error {
if !notClosed || v.Interface() == nil {
break
}
- valueFunc.Call([]reflect.Value{v})
+ callResults := valueFunc.Call([]reflect.Value{v})
+ // if last returned value from Call() is an error, return it
+ if len(callResults) > 0 {
+ if err, ok := callResults[len(callResults)-1].Interface().(error); ok {
+ return err
+ }
+ }
}
return nil
}
@@ -340,7 +397,7 @@ func UnmarshalToCallbackWithError(in io.Reader, f interface{}) error {
return fmt.Errorf("the given function must have exactly one return value")
}
if !isErrorType(t.Out(0)) {
- return fmt.Errorf("the given function must only return error.")
+ return fmt.Errorf("the given function must only return error")
}
cerr := make(chan error)
@@ -361,6 +418,9 @@ func UnmarshalToCallbackWithError(in io.Reader, f interface{}) error {
}
v, notClosed := c.Recv()
if !notClosed || v.Interface() == nil {
+ if err := <-cerr; err != nil {
+ fErr = err
+ }
break
}
@@ -405,7 +465,7 @@ func UnmarshalStringToCallbackWithError(in string, c interface{}) (err error) {
// CSVToMap creates a simple map from a CSV of 2 columns.
func CSVToMap(in io.Reader) (map[string]string, error) {
decoder := newSimpleDecoderFromReader(in)
- header, err := decoder.getCSVRow()
+ header, err := decoder.GetCSVRow()
if err != nil {
return nil, err
}
@@ -414,7 +474,7 @@ func CSVToMap(in io.Reader) (map[string]string, error) {
}
m := make(map[string]string)
for {
- line, err := decoder.getCSVRow()
+ line, err := decoder.GetCSVRow()
if err == io.EOF {
break
} else if err != nil {
diff --git a/vendor/github.com/gocarina/gocsv/decode.go b/vendor/github.com/gocarina/gocsv/decode.go
index a832e84..537251d 100644
--- a/vendor/github.com/gocarina/gocsv/decode.go
+++ b/vendor/github.com/gocarina/gocsv/decode.go
@@ -10,13 +10,13 @@ import (
// Decoder .
type Decoder interface {
- getCSVRows() ([][]string, error)
+ GetCSVRows() ([][]string, error)
}
// SimpleDecoder .
type SimpleDecoder interface {
- getCSVRow() ([]string, error)
- getCSVRows() ([][]string, error)
+ GetCSVRow() ([]string, error)
+ GetCSVRows() ([][]string, error)
}
type CSVReader interface {
@@ -32,6 +32,11 @@ func newSimpleDecoderFromReader(r io.Reader) SimpleDecoder {
return csvDecoder{getCSVReader(r)}
}
+var (
+ ErrEmptyCSVFile = errors.New("empty csv file given")
+ ErrNoStructTags = errors.New("no csv struct tags found")
+)
+
// NewSimpleDecoderFromCSVReader creates a SimpleDecoder, which may be passed
// to the UnmarshalDecoder* family of functions, from a CSV reader. Note that
// encoding/csv.Reader implements CSVReader, so you can pass one of those
@@ -40,11 +45,11 @@ func NewSimpleDecoderFromCSVReader(r CSVReader) SimpleDecoder {
return csvDecoder{r}
}
-func (c csvDecoder) getCSVRows() ([][]string, error) {
+func (c csvDecoder) GetCSVRows() ([][]string, error) {
return c.ReadAll()
}
-func (c csvDecoder) getCSVRow() ([]string, error) {
+func (c csvDecoder) GetCSVRow() ([]string, error) {
return c.Read()
}
@@ -137,19 +142,19 @@ func readToWithErrorHandler(decoder Decoder, errHandler ErrorHandler, out interf
if err := ensureOutInnerType(outInnerType); err != nil {
return err
}
- csvRows, err := decoder.getCSVRows() // Get the CSV csvRows
+ csvRows, err := decoder.GetCSVRows() // Get the CSV csvRows
if err != nil {
return err
}
if len(csvRows) == 0 {
- return errors.New("empty csv file given")
+ return ErrEmptyCSVFile
}
if err := ensureOutCapacity(&outValue, len(csvRows)); err != nil { // Ensure the container is big enough to hold the CSV content
return err
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
headers := normalizeHeaders(csvRows[0])
@@ -203,8 +208,11 @@ func readToWithErrorHandler(decoder Decoder, errHandler ErrorHandler, out interf
continue
}
}
-
- if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct
+ value := csvColumnContent
+ if value == "" {
+ value = fieldInfo.defaultValue
+ }
+ if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, value, fieldInfo.omitEmpty); err != nil { // Set field of struct
parseError := csv.ParseError{
Line: i + 2, //add 2 to account for the header & 0-indexing of arrays
Column: j + 1,
@@ -234,7 +242,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error {
}
defer outValue.Close()
- headers, err := decoder.getCSVRow()
+ headers, err := decoder.GetCSVRow()
if err != nil {
return err
}
@@ -246,7 +254,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error {
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
csvHeadersLabels := make(map[int]*fieldInfo, len(outInnerStructInfo.Fields)) // Used to store the correspondance header <-> position in CSV
headerCount := map[string]int{}
@@ -272,7 +280,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error {
}
i := 0
for {
- line, err := decoder.getCSVRow()
+ line, err := decoder.GetCSVRow()
if err == io.EOF {
break
} else if err != nil {
@@ -309,12 +317,12 @@ func readEachWithoutHeaders(decoder SimpleDecoder, c interface{}) error {
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
i := 0
for {
- line, err := decoder.getCSVRow()
+ line, err := decoder.GetCSVRow()
if err == io.EOF {
break
} else if err != nil {
@@ -346,19 +354,19 @@ func readToWithoutHeaders(decoder Decoder, out interface{}) error {
if err := ensureOutInnerType(outInnerType); err != nil {
return err
}
- csvRows, err := decoder.getCSVRows() // Get the CSV csvRows
+ csvRows, err := decoder.GetCSVRows() // Get the CSV csvRows
if err != nil {
return err
}
if len(csvRows) == 0 {
- return errors.New("empty csv file given")
+ return ErrEmptyCSVFile
}
if err := ensureOutCapacity(&outValue, len(csvRows)+1); err != nil { // Ensure the container is big enough to hold the CSV content
return err
}
outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations
if len(outInnerStructInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
for i, csvRow := range csvRows {
@@ -446,6 +454,31 @@ func setInnerField(outInner *reflect.Value, outInnerWasPointer bool, index []int
}
oi = outInner.Elem()
}
+
+ if oi.Kind() == reflect.Slice || oi.Kind() == reflect.Array {
+ i := index[0]
+
+ // grow slice when needed
+ if i >= oi.Cap() {
+ newcap := oi.Cap() + oi.Cap()/2
+ if newcap < 4 {
+ newcap = 4
+ }
+ newoi := reflect.MakeSlice(oi.Type(), oi.Len(), newcap)
+ reflect.Copy(newoi, oi)
+ oi.Set(newoi)
+ }
+ if i >= oi.Len() {
+ oi.SetLen(i + 1)
+ }
+
+ item := oi.Index(i)
+ if len(index) > 1 {
+ return setInnerField(&item, false, index[1:], value, omitEmpty)
+ }
+ return setField(item, value, omitEmpty)
+ }
+
// because pointers can be nil need to recurse one index at a time and perform nil check
if len(index) > 1 {
nextField := oi.Field(index[0])
diff --git a/vendor/github.com/gocarina/gocsv/encode.go b/vendor/github.com/gocarina/gocsv/encode.go
index 8671533..a7c0e72 100644
--- a/vendor/github.com/gocarina/gocsv/encode.go
+++ b/vendor/github.com/gocarina/gocsv/encode.go
@@ -1,11 +1,16 @@
package gocsv
import (
+ "errors"
"fmt"
"io"
"reflect"
)
+var (
+ ErrChannelIsClosed = errors.New("channel is closed")
+)
+
type encoder struct {
out io.Writer
}
@@ -14,11 +19,11 @@ func newEncoder(out io.Writer) *encoder {
return &encoder{out}
}
-func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error {
+func writeFromChan(writer CSVWriter, c <-chan interface{}, omitHeaders bool) error {
// Get the first value. It wil determine the header structure.
firstValue, ok := <-c
if !ok {
- return fmt.Errorf("channel is closed")
+ return ErrChannelIsClosed
}
inValue, inType := getConcreteReflectValueAndType(firstValue) // Get the concrete type
if err := ensureStructOrPtr(inType); err != nil {
@@ -30,8 +35,10 @@ func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error {
for i, fieldInfo := range inInnerStructInfo.Fields { // Used to write the header (first line) in CSV
csvHeadersLabels[i] = fieldInfo.getFirstKey()
}
- if err := writer.Write(csvHeadersLabels); err != nil {
- return err
+ if !omitHeaders {
+ if err := writer.Write(csvHeadersLabels); err != nil {
+ return err
+ }
}
write := func(val reflect.Value) error {
for j, fieldInfo := range inInnerStructInfo.Fields {
@@ -63,7 +70,7 @@ func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error {
return writer.Error()
}
-func writeTo(writer *SafeCSVWriter, in interface{}, omitHeaders bool) error {
+func writeTo(writer CSVWriter, in interface{}, omitHeaders bool) error {
inValue, inType := getConcreteReflectValueAndType(in) // Get the concrete type (not pointer) (Slice<?> or Array<?>)
if err := ensureInType(inType); err != nil {
return err
@@ -138,6 +145,21 @@ func getInnerField(outInner reflect.Value, outInnerWasPointer bool, index []int)
}
oi = outInner.Elem()
}
+
+ if oi.Kind() == reflect.Slice || oi.Kind() == reflect.Array {
+ i := index[0]
+
+ if i >= oi.Len() {
+ return "", nil
+ }
+
+ item := oi.Index(i)
+ if len(index) > 1 {
+ return getInnerField(item, false, index[1:])
+ }
+ return getFieldAsString(item)
+ }
+
// because pointers can be nil need to recurse one index at a time and perform nil check
if len(index) > 1 {
nextField := oi.Field(index[0])
diff --git a/vendor/github.com/gocarina/gocsv/go.mod b/vendor/github.com/gocarina/gocsv/go.mod
deleted file mode 100644
index c746a5a..0000000
--- a/vendor/github.com/gocarina/gocsv/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/gocarina/gocsv
-
-go 1.13
diff --git a/vendor/github.com/gocarina/gocsv/reflect.go b/vendor/github.com/gocarina/gocsv/reflect.go
index dfc63b3..309f80b 100644
--- a/vendor/github.com/gocarina/gocsv/reflect.go
+++ b/vendor/github.com/gocarina/gocsv/reflect.go
@@ -1,7 +1,9 @@
package gocsv
import (
+ "fmt"
"reflect"
+ "strconv"
"strings"
"sync"
)
@@ -17,9 +19,10 @@ type structInfo struct {
// Each IndexChain element before the last is the index of an the embedded struct field
// that defines Key as a tag
type fieldInfo struct {
- keys []string
- omitEmpty bool
- IndexChain []int
+ keys []string
+ omitEmpty bool
+ IndexChain []int
+ defaultValue string
}
func (f fieldInfo) getFirstKey() string {
@@ -64,18 +67,17 @@ func getFieldInfos(rType reflect.Type, parentIndexChain []int) []fieldInfo {
var cpy = make([]int, len(parentIndexChain))
copy(cpy, parentIndexChain)
indexChain := append(cpy, i)
-
// if the field is a pointer to a struct, follow the pointer then create fieldinfo for each field
if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
- // unless it implements marshalText or marshalCSV. Structs that implement this
+ // Structs that implement any of the text or CSV marshaling methods
// should result in one value and not have their fields exposed
- if !(canMarshal(field.Type.Elem())) {
+ if !(canMarshal(field.Type.Elem()) || canMarshal(field.Type)) {
fieldsList = append(fieldsList, getFieldInfos(field.Type.Elem(), indexChain)...)
}
}
// if the field is a struct, create a fieldInfo for each of its fields
if field.Type.Kind() == reflect.Struct {
- // unless it implements marshalText or marshalCSV. Structs that implement this
+ // Structs that implement any of the text or CSV marshaling methods
// should result in one value and not have their fields exposed
if !(canMarshal(field.Type)) {
fieldsList = append(fieldsList, getFieldInfos(field.Type, indexChain)...)
@@ -87,26 +89,91 @@ func getFieldInfos(rType reflect.Type, parentIndexChain []int) []fieldInfo {
continue
}
- fieldInfo := fieldInfo{IndexChain: indexChain}
+ currFieldInfo := fieldInfo{IndexChain: indexChain}
fieldTag := field.Tag.Get(TagName)
fieldTags := strings.Split(fieldTag, TagSeparator)
filteredTags := []string{}
for _, fieldTagEntry := range fieldTags {
- if fieldTagEntry != "omitempty" {
- filteredTags = append(filteredTags, normalizeName(fieldTagEntry))
+ trimmedFieldTagEntry := strings.TrimSpace(fieldTagEntry) // handles cases like `csv:"foo, omitempty, default=test"`
+ if trimmedFieldTagEntry == "omitempty" {
+ currFieldInfo.omitEmpty = true
+ } else if strings.HasPrefix(trimmedFieldTagEntry, "default=") {
+ currFieldInfo.defaultValue = strings.TrimPrefix(trimmedFieldTagEntry, "default=")
} else {
- fieldInfo.omitEmpty = true
+ filteredTags = append(filteredTags, normalizeName(trimmedFieldTagEntry))
}
}
if len(filteredTags) == 1 && filteredTags[0] == "-" {
continue
} else if len(filteredTags) > 0 && filteredTags[0] != "" {
- fieldInfo.keys = filteredTags
+ currFieldInfo.keys = filteredTags
+ } else {
+ currFieldInfo.keys = []string{normalizeName(field.Name)}
+ }
+
+ if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array {
+ var arrayLength = -1
+ if arrayTag, ok := field.Tag.Lookup(TagName + "[]"); ok {
+ arrayLength, _ = strconv.Atoi(arrayTag)
+ }
+
+ // When the field is a slice/array of structs, create a fieldInfo for each index and each field
+ if field.Type.Elem().Kind() == reflect.Struct {
+ fieldInfos := getFieldInfos(field.Type.Elem(), []int{})
+
+ for idx := 0; idx < arrayLength; idx++ {
+ // copy index chain and append array index
+ var cpy2 = make([]int, len(indexChain))
+ copy(cpy2, indexChain)
+ arrayIndexChain := append(cpy2, idx)
+ for _, childFieldInfo := range fieldInfos {
+ // copy array index chain and append array index
+ var cpy3 = make([]int, len(arrayIndexChain))
+ copy(cpy3, arrayIndexChain)
+
+ arrayFieldInfo := fieldInfo{
+ IndexChain: append(cpy3, childFieldInfo.IndexChain...),
+ omitEmpty: childFieldInfo.omitEmpty,
+ defaultValue: childFieldInfo.defaultValue,
+ }
+
+ // create cartesian product of keys
+ // eg: array field keys x struct field keys
+ for _, akey := range currFieldInfo.keys {
+ for _, fkey := range childFieldInfo.keys {
+ arrayFieldInfo.keys = append(arrayFieldInfo.keys, normalizeName(fmt.Sprintf("%s[%d].%s", akey, idx, fkey)))
+ }
+ }
+
+ fieldsList = append(fieldsList, arrayFieldInfo)
+ }
+ }
+ } else if arrayLength > 0 {
+ // When the field is a slice/array of primitives, create a fieldInfo for each index
+ for idx := 0; idx < arrayLength; idx++ {
+ // copy index chain and append array index
+ var cpy2 = make([]int, len(indexChain))
+ copy(cpy2, indexChain)
+
+ arrayFieldInfo := fieldInfo{
+ IndexChain: append(cpy2, idx),
+ omitEmpty: currFieldInfo.omitEmpty,
+ defaultValue: currFieldInfo.defaultValue,
+ }
+
+ for _, akey := range currFieldInfo.keys {
+ arrayFieldInfo.keys = append(arrayFieldInfo.keys, normalizeName(fmt.Sprintf("%s[%d]", akey, idx)))
+ }
+
+ fieldsList = append(fieldsList, arrayFieldInfo)
+ }
+ } else {
+ fieldsList = append(fieldsList, currFieldInfo)
+ }
} else {
- fieldInfo.keys = []string{normalizeName(field.Name)}
+ fieldsList = append(fieldsList, currFieldInfo)
}
- fieldsList = append(fieldsList, fieldInfo)
}
return fieldsList
}
diff --git a/vendor/github.com/gocarina/gocsv/safe_csv.go b/vendor/github.com/gocarina/gocsv/safe_csv.go
index 4b2882f..858b078 100644
--- a/vendor/github.com/gocarina/gocsv/safe_csv.go
+++ b/vendor/github.com/gocarina/gocsv/safe_csv.go
@@ -6,6 +6,12 @@ import (
"sync"
)
+type CSVWriter interface {
+ Write(row []string) error
+ Flush()
+ Error() error
+}
+
type SafeCSVWriter struct {
*csv.Writer
m sync.Mutex
diff --git a/vendor/github.com/gocarina/gocsv/types.go b/vendor/github.com/gocarina/gocsv/types.go
index a5dda89..537151a 100644
--- a/vendor/github.com/gocarina/gocsv/types.go
+++ b/vendor/github.com/gocarina/gocsv/types.go
@@ -182,6 +182,7 @@ func toFloat(in interface{}) (float64, error) {
if s == "" {
return 0, nil
}
+ s = strings.Replace(s, ",", ".", -1)
return strconv.ParseFloat(s, 64)
case reflect.Bool:
if inValue.Bool() {
@@ -279,6 +280,10 @@ func setField(field reflect.Value, value string, omitEmpty bool) error {
}
field.SetFloat(f)
case reflect.Slice, reflect.Struct:
+ if value == "" {
+ return nil
+ }
+
err := json.Unmarshal([]byte(value), field.Addr().Interface())
if err != nil {
return err
@@ -300,8 +305,6 @@ func getFieldAsString(field reflect.Value) (str string, err error) {
return "", nil
}
return getFieldAsString(field.Elem())
- case reflect.String:
- return field.String(), nil
default:
// Check if field is go native type
switch field.Interface().(type) {
@@ -363,6 +366,15 @@ func getFieldAsString(field reflect.Value) (str string, err error) {
if err != nil {
return str, err
}
+ case reflect.Slice:
+ fallthrough
+ case reflect.Array:
+ b, err := json.Marshal(field.Addr().Interface())
+ if err != nil {
+ return str, err
+ }
+
+ str = string(b)
}
} else {
return str, nil
@@ -376,11 +388,13 @@ func getFieldAsString(field reflect.Value) (str string, err error) {
// Un/serializations helpers
func canMarshal(t reflect.Type) bool {
- // unless it implements marshalText or marshalCSV. Structs that implement this
+ // Structs that implement any of the text or CSV marshaling methods
// should result in one value and not have their fields exposed
_, canMarshalText := t.MethodByName("MarshalText")
_, canMarshalCSV := t.MethodByName("MarshalCSV")
- return canMarshalCSV || canMarshalText
+ _, canUnmarshalText := t.MethodByName("UnmarshalText")
+ _, canUnmarshalCSV := t.MethodByName("UnmarshalCSV")
+ return canMarshalCSV || canMarshalText || canUnmarshalText || canUnmarshalCSV
}
func unmarshall(field reflect.Value, value string) error {
diff --git a/vendor/github.com/gocarina/gocsv/unmarshaller.go b/vendor/github.com/gocarina/gocsv/unmarshaller.go
index 87e6a8f..50d528e 100644
--- a/vendor/github.com/gocarina/gocsv/unmarshaller.go
+++ b/vendor/github.com/gocarina/gocsv/unmarshaller.go
@@ -2,7 +2,6 @@ package gocsv
import (
"encoding/csv"
- "errors"
"fmt"
"reflect"
)
@@ -15,6 +14,7 @@ type Unmarshaller struct {
MismatchedHeaders []string
MismatchedStructFields []string
outType reflect.Type
+ out interface{}
}
// NewUnmarshaller creates an unmarshaller from a csv.Reader and a struct.
@@ -66,7 +66,7 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error {
}
structInfo := getStructInfo(concreteType) // Get struct info to get CSV annotations.
if len(structInfo.Fields) == 0 {
- return errors.New("no csv struct tags found")
+ return ErrNoStructTags
}
csvHeadersLabels := make([]*fieldInfo, len(headers)) // Used to store the corresponding header <-> position in CSV
headerCount := map[string]int{}
@@ -91,6 +91,7 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error {
um.fieldInfoMap = csvHeadersLabels
um.MismatchedHeaders = mismatchHeaderFields(structInfo.Fields, headers)
um.MismatchedStructFields = mismatchStructFields(structInfo.Fields, headers)
+ um.out = s
return nil
}
@@ -116,3 +117,18 @@ func (um *Unmarshaller) unmarshalRow(row []string, unmatched map[string]string)
}
return outValue.Interface(), nil
}
+
+// RenormalizeHeaders will remap the header names based on the headerNormalizer.
+// This can be used to map a CSV to a struct where the CSV header names do not match in the file but a mapping is known
+func (um *Unmarshaller) RenormalizeHeaders(headerNormalizer func([]string) []string) error {
+ headers := um.Headers
+ if headerNormalizer != nil {
+ headers = headerNormalizer(headers)
+ }
+ err := validate(um, um.out, headers)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/spf13/pflag/go.mod b/vendor/github.com/spf13/pflag/go.mod
deleted file mode 100644
index b2287ee..0000000
--- a/vendor/github.com/spf13/pflag/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/spf13/pflag
-
-go 1.12
diff --git a/vendor/github.com/spf13/pflag/go.sum b/vendor/github.com/spf13/pflag/go.sum
deleted file mode 100644
index e69de29..0000000
--- a/vendor/github.com/spf13/pflag/go.sum
+++ /dev/null