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:
parent
b3642d32df
commit
3d555447d4
2 changed files with 86 additions and 52 deletions
85
csvstruct.go
85
csvstruct.go
|
|
@ -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
53
csvstruct_test.go
Normal 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++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue