wip: unmarshaler

This commit is contained in:
Suyono 2023-06-23 11:46:38 +10:00
parent 07fabf1962
commit b062eea7b6
4 changed files with 71 additions and 47 deletions

View File

@ -3,64 +3,70 @@ package gocsvparser
import ( import (
"fmt" "fmt"
"reflect" "reflect"
) "strings"
type defaultRecordHandlerMode int
const (
single defaultRecordHandlerMode = 1
slice defaultRecordHandlerMode = 2
) )
type defaultRecordHandler struct { type defaultRecordHandler struct {
structType reflect.Type handlersByName map[string]reflect.StructField
mode defaultRecordHandlerMode outType reflect.Type
slice reflect.Value
fieldByName map[string]FieldsHandlerByName
fieldByIndices map[int]FieldsHandlerByIndices
fieldsHandlers []FieldsHandler fieldsHandlers []FieldsHandler
} }
type defaultFieldsHandlerByName struct { func newDefaultHandler() *defaultRecordHandler {
newHander := new(defaultRecordHandler)
newHander.handlersByName = make(map[string]reflect.StructField)
return newHander
} }
func newDefaultRecordHandler(v interface{}) (*defaultRecordHandler, error) { func (d *defaultRecordHandler) HandleRecord(v interface{}, record []string) error {
val := reflect.ValueOf(v) //TODO: implementation
if val.Kind() == reflect.Pointer { if d.outType == nil {
val = val.Elem()
recordHandler := &defaultRecordHandler{}
switch val.Kind() {
case reflect.Slice:
recordHandler.mode = slice
typ := val.Type().Elem()
if typ.Kind() == reflect.Struct {
recordHandler.slice = val
recordHandler.structType = typ
}
case reflect.Struct:
recordHandler.mode = single
}
} }
return nil
return nil, fmt.Errorf("invalid value %v", val)
} }
func (dr *defaultRecordHandler) buildFieldsHandler() { func (d *defaultRecordHandler) FieldsHandlers() []FieldsHandler {
}
func (df *defaultFieldsHandlerByName) FieldsName() string {
//TODO: implementation
return ""
}
func (df *defaultFieldsHandlerByName) NumFields() int {
//TODO: implementation
return 0
}
func (df *defaultFieldsHandlerByName) Fields(fields ...string) error {
//TODO: implementation //TODO: implementation
return nil 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
}

View File

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

View File

@ -4,8 +4,14 @@ import (
"encoding/csv" "encoding/csv"
) )
type FieldsConfig struct {
Name string
Num int
}
type FieldsHandlerByName interface { type FieldsHandlerByName interface {
FieldsName() string FieldName() string
FieldByName(name, field string) error
FieldsHandler FieldsHandler
} }
@ -22,6 +28,9 @@ type FieldsHandler interface {
type RecordHandler interface { type RecordHandler interface {
FieldsHandlers() []FieldsHandler 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 { type Unmarshaler struct {

View File

@ -17,6 +17,10 @@ type anon struct {
OutputY int64 `csv:"y"` OutputY int64 `csv:"y"`
} }
func TestParse(t *testing.T) {
newDefaultHandler().parseVal(&Coba{})
}
func TestRead(t *testing.T) { func TestRead(t *testing.T) {
var coba []Coba var coba []Coba