Skip to content

Commit

Permalink
Fix incorrect error for very long lines (#48)
Browse files Browse the repository at this point in the history
Fix a bug where an io.EOF error would incorrectly be returned when a
line of data contains bufio.MaxScanTokenSize characters or greater.
The decoder will now return ErrTooLong when a line is too long to
decode.

Fixes #47
  • Loading branch information
ianlopshire authored Jun 13, 2022
1 parent 5919528 commit 2a77f58
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
15 changes: 15 additions & 0 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import (
"strings"
)

var (
// ErrTooLong indicates a line was too long to decode. Currently, the maximum
// decodable line length is bufio.MaxScanTokenSize-1.
ErrTooLong = bufio.ErrTooLong
)

// Unmarshal parses fixed width encoded data and stores the
// result in the value pointed to by v. If v is nil or not a
// pointer, Unmarshal returns an InvalidUnmarshalError.
Expand Down Expand Up @@ -95,6 +101,9 @@ func (d *Decoder) SetUseCodepointIndices(use bool) {
//
// In the case that v points to a slice value, Decode will read until
// the end of its input.
//
// Currently, the maximum decodable line length is bufio.MaxScanTokenSize-1. ErrTooLong
// is returned if a line is encountered that too long to decode.
func (d *Decoder) Decode(v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
Expand Down Expand Up @@ -158,9 +167,15 @@ func (d *Decoder) scan(data []byte, atEOF bool) (advance int, token []byte, err
return 0, nil, nil
}

// readLine reads the next line of data. False is returned if there is no remaining data
// to read.
func (d *Decoder) readLine(v reflect.Value) (err error, ok bool) {
ok = d.scanner.Scan()
if !ok {
if d.scanner.Err() != nil {
return d.scanner.Err(), false
}

d.done = true
return nil, false
}
Expand Down
17 changes: 17 additions & 0 deletions decode_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fixedwidth

import (
"bufio"
"bytes"
"encoding"
"fmt"
Expand Down Expand Up @@ -396,6 +397,22 @@ func TestDecode_EOF(t *testing.T) {
}
}

// Verify that lines longer than the bufio.Scanner buffer decode correctly. See
// https://github.com/ianlopshire/go-fixedwidth/issues/47.
func TestDecode_VeryLongLines(t *testing.T) {
var s struct {
Field1 string `fixed:"1,10"`
}

// Fill a line with bufio.MaxScanTokenSize charters.
data := bytes.Repeat([]byte("a"), bufio.MaxScanTokenSize)

d := NewDecoder(bytes.NewReader(data))
if err := d.Decode(&s); err != ErrTooLong {
t.Errorf("Decode should have returned ErrTooLong. Returned: %v", err)
}
}

func TestNewRawValue(t *testing.T) {
for _, tt := range []struct {
name string
Expand Down

0 comments on commit 2a77f58

Please sign in to comment.