From 1bbce1aa65e4af84a144b137ea2037004eb2881d Mon Sep 17 00:00:00 2001 From: Victor Häggqvist Date: Wed, 14 Sep 2022 23:54:17 +0200 Subject: go bump --- vendor/github.com/gocarina/gocsv/reflect.go | 95 ++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 14 deletions(-) (limited to 'vendor/github.com/gocarina/gocsv/reflect.go') 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 } -- cgit v1.2.3