Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions seq/csvseq/iterate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package csvseq

import (
"encoding/csv"
"io"
"iter"
)

// Iterate creates an iterator over the records of the CSV reader. Errors occuring might be csv.ErrFieldCount or
// parse errors. As Iterate is supposed to consume all the records, the error is never io.EOF.
func Iterate(reader *csv.Reader) iter.Seq2[[]string, error] {
return func(yield func([]string, error) bool) {
for {
record, err := reader.Read()
if err == io.EOF {
return
}

if !yield(record, err) {
return
}
}
}
}
63 changes: 63 additions & 0 deletions seq/csvseq/iterate_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package csvseq_test

import (
"encoding/csv"
"errors"
"fmt"
"strings"

"github.com/GodsBoss/g/seq/csvseq"
)

func ExampleIterate_tooFewFields() {
raw := strings.Join(
[]string{
"Foo,Bar,Baz",
"a,b",
"1,2,3",
},
"\n",
)

reader := csv.NewReader(strings.NewReader(raw))
reader.FieldsPerRecord = 3

for record, err := range csvseq.Iterate(reader) {
if err != nil {
fmt.Println("Invalid record " + strings.Join(record, ",") + " - " + err.Error())
break
}
}

// Output:
// Invalid record a,b - record on line 2: wrong number of fields
}

func ExampleIterate_exhaustion() {
raw := strings.Join(
[]string{
"1,2,3",
"a,b,c",
"x,y,z",
},
"\n",
)

reader := csv.NewReader(strings.NewReader(raw))

var errs error

for record, err := range csvseq.Iterate(reader) {
fmt.Println(record[0])
errs = errors.Join(errs, err)
}

if errs != nil {
fmt.Println(errs)
}

// Output:
// 1
// a
// x
}
17 changes: 17 additions & 0 deletions seq/csvseq/iterate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package csvseq_test

import (
"encoding/csv"
"strings"
"testing"

"github.com/GodsBoss/g/seq/csvseq"
)

func TestEmpty(t *testing.T) {
iterator := csvseq.Iterate(csv.NewReader(strings.NewReader("")))

for record, err := range iterator {
t.Errorf("expected no iteration, got %v; %v", record, err)
}
}