Skip to content

Commit

Permalink
chore: csvparser module layout
Browse files Browse the repository at this point in the history
  • Loading branch information
sonirico committed Oct 5, 2022
1 parent 78889b0 commit 8634f13
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 197 deletions.
66 changes: 66 additions & 0 deletions csvparser/columns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package csvparser

type (
Col[T any] interface {
Parse(data []byte, item *T) error
//Compile(x T, writer io.Writer) error
}

StringColumn[T any] struct {
inner StringType
setter func(x *T, v string)
getter func(x T) string
}

IntColumn[T any] struct {
inner IntegerType
setter func(x *T, v int)
getter func(x T) int
}

BoolColumn[T any] struct {
inner StringType
setter func(x T, v bool)
getter func(x T) bool
}
)

func (s StringColumn[T]) Parse(data []byte, item *T) error {
val, err := s.inner.Parse(data)
if err != nil {
return err
}
s.setter(item, val)
return nil
}

func (c IntColumn[T]) Parse(data []byte, item *T) error {
val, err := c.inner.Parse(data)
if err != nil {
return err
}
c.setter(item, val)
return nil
}

func StringCol[T any](
quoted bool,
getter func(T) string,
setter func(*T, string),
) Col[T] {
return StringColumn[T]{
inner: StrType(quoted),
getter: getter, setter: setter,
}
}

func IntCol[T any](
quoted bool,
getter func(T) int,
setter func(*T, int),
) Col[T] {
return IntColumn[T]{
inner: IntType(quoted),
getter: getter, setter: setter,
}
}
197 changes: 0 additions & 197 deletions csvparser/csvparser.go

This file was deleted.

65 changes: 65 additions & 0 deletions csvparser/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package csvparser

import (
"github.com/pkg/errors"
"github.com/sonirico/stadio/slices"
)

var (
quote = []byte{byte('"')}

SeparatorComma byte = ','
SeparatorSemicolon byte = ';'
SeparatorTab byte = '\t'
)

type (
Parser[T any] struct {
separator byte
columns []Col[T]
}
)

func (p Parser[T]) Parse(data []byte, item *T) (err error) {
counter := 0
for _, col := range p.columns {
pos := slices.IndexOf[byte](
data,
func(x byte) bool {
return x == p.separator
},
)

lastCol := counter == len(p.columns)-1

if pos == -1 && !lastCol {
// Only if no more separators have been found, and current column is not the last one, yield error
err = errors.Wrapf(
ErrColumnMismatch,
"want %d, have %d",
len(p.columns),
counter,
)
}

payload := data
if !lastCol {
payload = data[:pos]
}

if err = col.Parse(payload, item); err != nil {
return err
}

counter++

if !lastCol {
data = data[pos+1:]
}
}
return nil
}

func NewParser[T any](sep byte, cols ...Col[T]) Parser[T] {
return Parser[T]{separator: sep, columns: cols}
}
Loading

0 comments on commit 8634f13

Please sign in to comment.