Compare commits

..

3 Commits

Author SHA1 Message Date
Suyono
b062eea7b6 wip: unmarshaler 2023-06-23 11:46:38 +10:00
Suyono
07fabf1962 wip: unmarshaler 2023-06-19 11:29:21 +10:00
Suyono
33a3a90d81 wip: unmarshal 2023-06-18 16:28:27 +10:00
8 changed files with 247 additions and 0 deletions

1
.tool-versions Normal file
View File

@ -0,0 +1 @@
golang 1.18

72
default_record_handler.go Normal file
View File

@ -0,0 +1,72 @@
package gocsvparser
import (
"fmt"
"reflect"
"strings"
)
type defaultRecordHandler struct {
handlersByName map[string]reflect.StructField
outType reflect.Type
fieldsHandlers []FieldsHandler
}
func newDefaultHandler() *defaultRecordHandler {
newHander := new(defaultRecordHandler)
newHander.handlersByName = make(map[string]reflect.StructField)
return newHander
}
func (d *defaultRecordHandler) HandleRecord(v interface{}, record []string) error {
//TODO: implementation
if d.outType == nil {
}
return nil
}
func (d *defaultRecordHandler) FieldsHandlers() []FieldsHandler {
//TODO: implementation
return nil
}
func (d *defaultRecordHandler) SetFieldConfigs(configs []FieldsConfig) {
}
func (d *defaultRecordHandler) parseVal(v interface{}) error {
typ := reflect.TypeOf(v)
if typ.Kind() == reflect.Pointer {
typ = typ.Elem()
if typ.Kind() == reflect.Struct {
d.outType = typ
return d.buildStructHandlers()
} else if typ.Kind() == reflect.Map {
//TODO: implementation
} else if typ.Kind() == reflect.Slice {
//TODO: implementation
}
}
return fmt.Errorf("v should be pointer of Struct, Map, or Slice: %+v", typ)
}
func (d *defaultRecordHandler) buildStructHandlers() error {
//TODO: implementation
for _, field := range reflect.VisibleFields(d.outType) {
if csv, ok := field.Tag.Lookup(csvTag); ok {
s := strings.Split(csv, ",")
if len(s) == 0 {
return fmt.Errorf("invalid tag %+v", field.Tag)
}
if _, ok = d.handlersByName[s[0]]; ok {
return fmt.Errorf("problem with the receiving struct, multiple field with tag %s", s[0])
}
d.handlersByName[s[0]] = field
} else if csvIndex, ok := field.Tag.Lookup(csvIndexTag); ok {
_ = csvIndex //TODO: process tag
}
}
return nil
}

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module github.com/budiuno/gocsvparser
go 1.14

6
gocsvparser.go Normal file
View File

@ -0,0 +1,6 @@
package gocsvparser
const (
csvTag string = "csv"
csvIndexTag string = "csv.index"
)

1
marshal.go Normal file
View File

@ -0,0 +1 @@
package gocsvparser

2
proposals/initial.md Normal file
View File

@ -0,0 +1,2 @@
# Proposal 1

89
unmarshal.go Normal file
View File

@ -0,0 +1,89 @@
package gocsvparser
import (
"encoding/csv"
)
type FieldsConfig struct {
Name string
Num int
}
type FieldsHandlerByName interface {
FieldName() string
FieldByName(name, field string) error
FieldsHandler
}
type FieldsHandlerByIndices interface {
FieldsIndices() []int
FieldByIndex(index int, field string) error
FieldsHandler
}
type FieldsHandler interface {
Fields(fields ...string) error
NumFields() int
}
type RecordHandler interface {
FieldsHandlers() []FieldsHandler
// SetFieldConfigs is only effective if a Map is passed to HandleRecord
SetFieldConfigs(configs []FieldsConfig)
HandleRecord(v interface{}, record []string) error
}
type Unmarshaler struct {
header []string
reader *csv.Reader
recordHandler RecordHandler
}
func NewUnmarshaler() *Unmarshaler {
return &Unmarshaler{}
}
func (u *Unmarshaler) WithCsvReader(reader *csv.Reader) *Unmarshaler {
u.reader = reader
return u
}
func (u *Unmarshaler) WithHeader(header []string) *Unmarshaler {
if len(header) > 0 {
newHeader := make([]string, len(header))
copy(newHeader, header)
u.header = newHeader
}
return u
}
func (u *Unmarshaler) WithRecordHandler(handler RecordHandler) *Unmarshaler {
u.recordHandler = handler
return u
}
func (u *Unmarshaler) Unmarshal(data []byte, v interface{}) error {
//TODO: implementation
return nil
}
func Unmarshal(data []byte, v interface{}) error {
return NewUnmarshaler().Unmarshal(data, v)
}
// func Read(i interface{}) {
// var val reflect.Value
// val = reflect.ValueOf(i)
// if val.Kind() == reflect.Pointer {
// val = val.Elem()
// if val.Kind() == reflect.Slice {
// val = val.Elem()
// if val.Kind() == reflect.Struct {
// fields := reflect.VisibleFields(val.Type())
// }
// }
// }
// }

73
unmarshal_test.go Normal file
View File

@ -0,0 +1,73 @@
package gocsvparser
import (
"reflect"
"testing"
)
type Coba struct {
Name string `csv:"name"`
Address string `csv:"address,omitempty"`
Mile int64 `csv:"mile"`
anon
}
type anon struct {
FieldX int64 `csv:"x"`
OutputY int64 `csv:"y"`
}
func TestParse(t *testing.T) {
newDefaultHandler().parseVal(&Coba{})
}
func TestRead(t *testing.T) {
var coba []Coba
Read(&coba, t)
t.Logf("outside %+v", coba)
// type args struct {
// i interface{}
// }
// tests := []struct {
// name string
// args args
// }{
// // TODO: Add test cases.
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// Read(tt.args.i)
// })
// }
}
func Read(i interface{}, t *testing.T) {
var val reflect.Value
val = reflect.ValueOf(i)
if val.Kind() == reflect.Pointer {
val = val.Elem()
if val.Kind() == reflect.Slice {
vslice := val
typ := val.Type().Elem()
if typ.Kind() == reflect.Struct {
for _, x := range reflect.VisibleFields(typ) {
t.Logf("test: %+v", x)
}
nv := reflect.New(typ).Elem()
nv.FieldByName("Name").SetString("hello")
nv.FieldByName("Mile").SetInt(72)
// vslice = reflect.Append(vslice, nv)
vslice.Set(reflect.Append(vslice, nv))
t.Logf("inside: %+v", vslice)
}
}
}
}