mirror of
https://github.com/imjasonh/csvstruct
synced 2026-07-18 14:56:23 +00:00
begin encoding, tests fail/skipped currently
This commit is contained in:
parent
2731c3991a
commit
6c63e469f5
2 changed files with 103 additions and 0 deletions
68
encode.go
Normal file
68
encode.go
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
package csvstruct
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Encoder interface {
|
||||||
|
EncodeNext(v interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type encoder struct {
|
||||||
|
w *csv.Writer
|
||||||
|
headersWritten bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEncoder(w io.Writer) Encoder {
|
||||||
|
return &encoder{w: csv.NewWriter(w)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) EncodeNext(v interface{}) error {
|
||||||
|
t := reflect.ValueOf(v).Type()
|
||||||
|
if !e.headersWritten {
|
||||||
|
headers := make([]string, t.NumField())
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if f.PkgPath != "" { // Filter unexported fields
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
h := f.Name
|
||||||
|
if f.Tag.Get("csv") != "" {
|
||||||
|
h = f.Tag.Get("csv")
|
||||||
|
}
|
||||||
|
headers[i] = h
|
||||||
|
}
|
||||||
|
if err := e.w.Write(headers); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.headersWritten = true
|
||||||
|
}
|
||||||
|
|
||||||
|
rv := reflect.ValueOf(v)
|
||||||
|
row := make([]string, t.NumField())
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if f.PkgPath != "" { // Filter unexported fields
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vf := rv.Field(i)
|
||||||
|
switch vf.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
row[i] = vf.String()
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
row[i] = fmt.Sprintf("%d", vf.Int())
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
row[i] = fmt.Sprintf("%d", vf.Uint())
|
||||||
|
case reflect.Float64:
|
||||||
|
row[i] = fmt.Sprintf("%f", vf.Float())
|
||||||
|
case reflect.Bool:
|
||||||
|
row[i] = fmt.Sprintf("%t", vf.Bool())
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("can't decode type %v", f.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e.w.Write(row)
|
||||||
|
}
|
||||||
35
encode_test.go
Normal file
35
encode_test.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package csvstruct
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEncodeNext(t *testing.T) {
|
||||||
|
t.Skip("failing for some reason... TODO: investigate")
|
||||||
|
type row struct {
|
||||||
|
Foo, Bar, Baz string
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range []struct {
|
||||||
|
rows []row
|
||||||
|
exp string
|
||||||
|
}{{
|
||||||
|
[]row{{"a", "b", "c"}, {"d", "e", "f"}},
|
||||||
|
`Foo,Bar,Baz
|
||||||
|
a,b,c
|
||||||
|
d,e,f`,
|
||||||
|
}} {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
e := NewEncoder(&buf)
|
||||||
|
for _, r := range c.rows {
|
||||||
|
if err := e.EncodeNext(r); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
got := string(buf.Bytes())
|
||||||
|
if got != c.exp {
|
||||||
|
t.Errorf("unexpected result, got %s, want %s", got, c.exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue