Skip to content

Commit

Permalink
Refactor Write (#8)
Browse files Browse the repository at this point in the history
* fix: reorderColumns execute position

* feat: add Test_writeToChan_emptyptr_sortOrder

* fix: checkSortOrderSlice exec position

* fix: reorderColumns func

* fix: remove unnecessary func

* feat: error handling
  • Loading branch information
shigetaichi authored Aug 16, 2023
1 parent a29b8ed commit 0561755
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 29 deletions.
5 changes: 4 additions & 1 deletion decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ func setInnerField(outInner *reflect.Value, outInnerWasPointer bool, index []int
if outInnerWasPointer {
// initialize nil pointer
if oi.IsNil() {
setField(oi, "", omitEmpty)
err := setField(oi, "", omitEmpty)
if err != nil {
return err
}
}
oi = outInner.Elem()
}
Expand Down
12 changes: 0 additions & 12 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,3 @@ func getInnerField(outInner reflect.Value, outInnerWasPointer bool, index []int)
}
return getFieldAsString(oi.FieldByIndex(index))
}

func getPickedFields(fields []fieldInfo, columnFieldsIndexes []int) []fieldInfo {
var newFields []fieldInfo
if len(columnFieldsIndexes) > 0 {
for _, columnFieldsIndex := range columnFieldsIndexes {
newFields = append(newFields, fields[columnFieldsIndex])
}
} else {
newFields = fields
}
return newFields
}
41 changes: 38 additions & 3 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ func Test_writeTo_emptyptr_sortOrder(t *testing.T) {
}

xsvWrite := NewXsvWrite[EmbedPtrSample]()
xsvWrite.SortOrder = []int{1, 0, 2, 3, 4, 5, 6, 7, 8, 9}
xsvWrite.SortOrder = []int{1, 0, 2, 3, 4, 5, 6, 7, 9, 8}
if err := xsvWrite.SetWriter(csv.NewWriter(e.out)).Write(s); err != nil {
t.Fatal(err)
}
Expand All @@ -670,6 +670,41 @@ func Test_writeTo_emptyptr_sortOrder(t *testing.T) {
if len(lines) != 2 {
t.Fatalf("expected 2 lines, got %d", len(lines))
}
assertLine(t, []string{"foo", "first", "BAR", "Baz", "Quux", "Blah", "SPtr", "Omit", "garply", "last"}, lines[0])
assertLine(t, []string{"f", "aaa", "1", "baz", "0.2", "2", "*string", "", "3.141592653589793", "zzz"}, lines[1])
assertLine(t, []string{"foo", "first", "BAR", "Baz", "Quux", "Blah", "SPtr", "Omit", "last", "garply"}, lines[0])
assertLine(t, []string{"f", "aaa", "1", "baz", "0.2", "2", "*string", "", "zzz", "3.141592653589793"}, lines[1])
}

func Test_writeToChan_emptyptr_sortOrder(t *testing.T) {
b := bytes.Buffer{}
e := &encoder{out: &b}
sampleChan := make(chan Sample)
sptr := "*string"
go func() {
for i := 0; i < 100; i++ {
v := Sample{Foo: "f", Bar: i, Baz: "baz" + strconv.Itoa(i), Frop: float64(i), Blah: nil, SPtr: &sptr}
sampleChan <- v
}
close(sampleChan)
}()

xsvWrite := NewXsvWrite[Sample]()
xsvWrite.SortOrder = []int{1, 0, 2, 3, 4, 5, 6}
err := xsvWrite.SetWriter(csv.NewWriter(e.out)).WriteFromChan(sampleChan)
if err != nil {
t.Fatal(err)
}
lines, err := csv.NewReader(&b).ReadAll()
if err != nil {
t.Fatal(err)
}
if len(lines) != 101 {
t.Fatalf("expected 100 lines, got %d", len(lines))
}
for i, l := range lines {
if i == 0 {
assertLine(t, []string{"BAR", "foo", "Baz", "Quux", "Blah", "SPtr", "Omit"}, l)
continue
}
assertLine(t, []string{strconv.Itoa(i - 1), "f", "baz" + strconv.Itoa(i-1), strconv.FormatFloat(float64(i-1), 'f', -1, 64), "", "*string", ""}, l)
}
}
24 changes: 11 additions & 13 deletions xsv_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ func (xw *XsvWriter[T]) Write(data []T) error {

fieldInfos := getFieldInfos(inInnerType, []int{}, []string{}, xw.TagName, xw.TagSeparator, xw.nameNormalizer) // Get the inner struct info to get CSV annotations
fieldInfos = xw.getSelectedFieldInfos(fieldInfos)
if err := xw.checkSortOrderSlice(len(fieldInfos)); err != nil {
return err
}
fieldInfos = reorderColumns[fieldInfo](fieldInfos, xw.SortOrder)
inInnerStructInfo := &structInfo{fieldInfos}

csvHeadersLabels := make([]string, len(inInnerStructInfo.Fields))
for i, fieldInfo := range inInnerStructInfo.Fields { // Used to write the header (first line) in CSV
csvHeadersLabels[i] = fieldInfo.getFirstKey()
}
if err := xw.checkSortOrderSlice(len(fieldInfos)); err != nil {
return err
}
csvHeadersLabels = reorderColumns(csvHeadersLabels, xw.SortOrder)
if !xw.OmitHeaders {
if err := xw.writer.Write(csvHeadersLabels); err != nil {
return err
Expand All @@ -59,7 +59,6 @@ func (xw *XsvWriter[T]) Write(data []T) error {
}
csvHeadersLabels[j] = inInnerFieldValue
}
csvHeadersLabels = reorderColumns(csvHeadersLabels, xw.SortOrder)
if err := xw.writer.Write(csvHeadersLabels); err != nil {
return err
}
Expand All @@ -81,16 +80,16 @@ func (xw *XsvWriter[T]) WriteFromChan(dataChan chan T) error {
inInnerWasPointer := inType.Kind() == reflect.Ptr
fieldInfos := getFieldInfos(inType, []int{}, []string{}, xw.TagName, xw.TagSeparator, xw.nameNormalizer) // Get the inner struct info to get CSV annotations
fieldInfos = xw.getSelectedFieldInfos(fieldInfos)
if err := xw.checkSortOrderSlice(len(fieldInfos)); err != nil {
return err
}
fieldInfos = reorderColumns[fieldInfo](fieldInfos, xw.SortOrder)
inInnerStructInfo := &structInfo{fieldInfos}
csvHeadersLabels := make([]string, len(inInnerStructInfo.Fields))
for i, fieldInfo := range inInnerStructInfo.Fields { // Used to Write the header (first line) in CSV
csvHeadersLabels[i] = fieldInfo.getFirstKey()
}

if err := xw.checkSortOrderSlice(len(fieldInfos)); err != nil {
return err
}
csvHeadersLabels = reorderColumns(csvHeadersLabels, xw.SortOrder)
if !xw.OmitHeaders {
if err := xw.writer.Write(csvHeadersLabels); err != nil {
return err
Expand All @@ -104,7 +103,6 @@ func (xw *XsvWriter[T]) WriteFromChan(dataChan chan T) error {
return err
}
csvHeadersLabels[j] = inInnerFieldValue
csvHeadersLabels = reorderColumns(csvHeadersLabels, xw.SortOrder)
}
if err := xw.writer.Write(csvHeadersLabels); err != nil {
return err
Expand All @@ -127,9 +125,9 @@ func (xw *XsvWriter[T]) WriteFromChan(dataChan chan T) error {
return xw.writer.Error()
}

func reorderColumns(row []string, sortOrder []int) []string {
if len(sortOrder) > 0 {
newLine := make([]string, len(row))
func reorderColumns[T any](row []T, sortOrder []int) []T {
if len(sortOrder) > 1 {
newLine := make([]T, len(row))
for from, to := range sortOrder {
newLine[to] = row[from]
}
Expand Down

0 comments on commit 0561755

Please sign in to comment.