1
0
Fork 0
mirror of https://github.com/imjasonh/csvstruct synced 2026-07-18 06:47:35 +00:00

Big refactoring, reflection still borked

This commit is contained in:
Jason Hall 2014-05-14 20:54:19 -04:00
parent b3642d32df
commit 3d555447d4
2 changed files with 86 additions and 52 deletions

View file

@ -1,71 +1,52 @@
package main package csvstruct
import ( import (
"encoding/csv" "encoding/csv"
"fmt"
"io" "io"
"reflect" "reflect"
"strings"
) )
type example struct { type Decoder interface {
Foo string `csv:"foo"` DecodeNext(v interface{}) error
Bar string
} }
func main() { type decoder struct {
data := ` hm map[string]int
foo,Bar,baz r csv.Reader
a,b,c
d,e,f
g,h,i`
ch := make(chan interface{})
r, _ := newCsvReader(strings.NewReader(data))
e := example{}
_ = r.Read(e, ch)
} }
type csvReader struct { func NewDecoder(r io.Reader) Decoder {
header []string return decoder{
r csv.Reader r: *csv.NewReader(r),
}
func newCsvReader(r io.Reader) (*csvReader, error) {
csvr := csv.NewReader(r)
header, err := csvr.Read()
if err != nil {
return nil, err
} }
c := csvReader{
header: header,
r: *csvr,
}
return &c, nil
} }
func (r csvReader) Read(in interface{}, ch chan<- interface{}) error { func (d decoder) DecodeNext(in interface{}) error {
t := reflect.TypeOf(in) if len(d.hm) == 0 {
hm := reverse(r.header) // First run; read header row
header, err := d.r.Read()
line, err := r.r.Read()
for err != io.EOF {
if err != nil { if err != nil {
return err return err
} }
out := reflect.ValueOf(&in) d.hm = reverse(header)
for i := 0; i < t.NumField(); i++ { }
f := t.Field(i)
n := f.Name t := reflect.TypeOf(in)
if f.Tag.Get("csv") == "" {
n = f.Tag.Get("csv") line, err := d.r.Read()
} if err != nil {
val := line[hm[n]] return err
v := reflect.ValueOf(&val) }
v.Elem().SetString(line[hm[n]])
out.Elem().Set(v) out := reflect.ValueOf(in)
} for i := 0; i < t.NumField(); i++ {
fmt.Println("%v", out.Elem().Interface()) f := t.Field(i)
line, err = r.r.Read() n := f.Name
// TODO: f.Tag.Get("csv")
val := line[d.hm[n]]
v := reflect.ValueOf(&val)
v.Elem().SetString(line[d.hm[n]])
out.Elem().Set(v)
} }
return nil return nil
} }
@ -76,4 +57,4 @@ func reverse(in []string) map[string]int {
m[v] = i m[v] = i
} }
return m return m
} }

53
csvstruct_test.go Normal file
View file

@ -0,0 +1,53 @@
package csvstruct
import (
"io"
"strings"
"testing"
)
func TestDecode(t *testing.T) {
type row struct {
Foo, Bar, Baz string
}
for _, c := range []struct {
data string
out []row
}{{
data: `Foo,Bar,Baz
a,b,c
d,e,f`,
out: []row{{"a", "b", "c"}, {"d", "e", "f"}},
}, {
// Rows that only have partial data are only partially filled.
data: `Foo,Bar
a,
,b`,
out: []row{{"a", "", ""}, {"", "b", ""}},
}, {
// Disjoint data results in unset struct.
data: `
Qux
ignored`,
out: []row{{"", "", ""}},
}} {
d := NewDecoder(strings.NewReader(c.data))
var row row
i := 0
for {
err := d.DecodeNext(&row)
if err == io.EOF {
break
}
if err != nil {
t.Errorf("%v", err)
break
}
if c.out[i] != row {
t.Errorf("unexpected item %d, got %+v, want %+v", i, row, c.out[i])
}
i++
}
}
}