Skip to content

Commit

Permalink
feat: Add Decoder.NormalizeHeader
Browse files Browse the repository at this point in the history
Closes: #45
  • Loading branch information
jszwec committed Nov 7, 2021
1 parent 50fc372 commit 6bfc75a
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
22 changes: 22 additions & 0 deletions decoder.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package csvutil

import (
"errors"
"io"
"reflect"
)
Expand Down Expand Up @@ -202,6 +203,27 @@ func (d *Decoder) Header() []string {
return header
}

// NormalizeHeader applies f to every column in the header. It returns error
// if calling f results in conflicting header columns.
//
// NormalizeHeader must be called before Decode.
func (d *Decoder) NormalizeHeader(f func(string) string) error {
set := make(map[string]int, len(d.header))
for i, s := range d.header {
set[f(s)] = i
}

if len(set) != len(d.header) {
return errors.New("csvutil: normalize header results in conflicting columns")
}

for s, i := range set {
d.header[i] = s
}
d.hmap = set
return nil
}

// Unused returns a list of column indexes that were not used during decoding
// due to lack of matching struct field.
func (d *Decoder) Unused() []int {
Expand Down
39 changes: 39 additions & 0 deletions decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2405,6 +2405,45 @@ s,1,3.14,true
t.Log(e)
})
})

t.Run("normalize header", func(t *testing.T) {
csvr := csv.NewReader(strings.NewReader("STRING,INT\nfirst,1"))
dec, err := NewDecoder(csvr)
if err != nil {
t.Fatalf("want err == nil; got %v", err)
}

if err := dec.NormalizeHeader(strings.ToLower); err != nil {
t.Fatalf("want err=nil; got %v", err)
}

var data struct {
String string `csv:"string"`
Int int `csv:"int"`
}
if err := dec.Decode(&data); err != nil {
t.Fatalf("want err=nil; got %v", err)
}

if data.String != "first" {
t.Errorf("want String=first; got %s", data.String)
}
if data.Int != 1 {
t.Errorf("want Int=1; got %d", data.Int)
}
})

t.Run("normalize header - duplicate error", func(t *testing.T) {
csvr := csv.NewReader(strings.NewReader("STRING,string\nfirst,1"))
dec, err := NewDecoder(csvr)
if err != nil {
t.Fatalf("want err == nil; got %v", err)
}

if err := dec.NormalizeHeader(strings.ToLower); err == nil {
t.Fatal("want err not to be nil")
}
})
}

func BenchmarkDecode(b *testing.B) {
Expand Down

0 comments on commit 6bfc75a

Please sign in to comment.