Skip to content

Commit

Permalink
Refactor utility io conversions into one internal package
Browse files Browse the repository at this point in the history
Improve reader type conversion by checking if type satisfies
ReaderAt to avoid unnecessary wrapping.

Move io converters into one place.

Fixes:
- ipld/go-car#145


This commit was moved from ipld/go-car@f3fc595
  • Loading branch information
masih authored and mvdan committed Jul 16, 2021
1 parent bf399a8 commit 4b9c91b
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 18 deletions.
19 changes: 1 addition & 18 deletions ipld/car/v2/index_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"io"
"os"
"sync"

internalio "github.com/ipld/go-car/v2/internal/io"

Expand Down Expand Up @@ -97,22 +96,6 @@ func GenerateIndexFromFile(path string) (index.Index, error) {
return GenerateIndex(f)
}

var _ io.ReaderAt = (*readSeekerAt)(nil)

type readSeekerAt struct {
rs io.ReadSeeker
mu sync.Mutex
}

func (rsa *readSeekerAt) ReadAt(p []byte, off int64) (n int, err error) {
rsa.mu.Lock()
defer rsa.mu.Unlock()
if _, err := rsa.rs.Seek(off, io.SeekStart); err != nil {
return 0, err
}
return rsa.rs.Read(p)
}

// ReadOrGenerateIndex accepts both CAR v1 and v2 format, and reads or generates an index for it.
// When the given reader is in CAR v1 format an index is always generated.
// For a payload in CAR v2 format, an index is only generated if Header.HasIndex returns false.
Expand All @@ -137,7 +120,7 @@ func ReadOrGenerateIndex(rs io.ReadSeeker) (index.Index, error) {
return GenerateIndex(rs)
case 2:
// Read CAR v2 format
v2r, err := NewReader(&readSeekerAt{rs: rs})
v2r, err := NewReader(internalio.ToReaderAt(rs))
if err != nil {
return nil, err
}
Expand Down
23 changes: 23 additions & 0 deletions ipld/car/v2/internal/io/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package io
import (
"io"
"io/ioutil"
"sync"
)

var (
_ io.ByteReader = (*readerPlusByte)(nil)
_ io.ByteReader = (*readSeekerPlusByte)(nil)
_ io.ByteReader = (*discardingReadSeekerPlusByte)(nil)
_ io.ReadSeeker = (*discardingReadSeekerPlusByte)(nil)
_ io.ReaderAt = (*readSeekerAt)(nil)
)

type (
Expand All @@ -30,6 +32,11 @@ type (
io.ReadSeeker
io.ByteReader
}

readSeekerAt struct {
rs io.ReadSeeker
mu sync.Mutex
}
)

func ToByteReader(r io.Reader) io.ByteReader {
Expand All @@ -49,6 +56,13 @@ func ToByteReadSeeker(r io.Reader) ByteReadSeeker {
return &discardingReadSeekerPlusByte{Reader: r}
}

func ToReaderAt(rs io.ReadSeeker) io.ReaderAt {
if ra, ok := rs.(io.ReaderAt); ok {
return ra
}
return &readSeekerAt{rs: rs}
}

func (rb readerPlusByte) ReadByte() (byte, error) {
return readByte(rb)
}
Expand Down Expand Up @@ -89,3 +103,12 @@ func readByte(r io.Reader) (byte, error) {
_, err := io.ReadFull(r, p[:])
return p[0], err
}

func (rsa *readSeekerAt) ReadAt(p []byte, off int64) (n int, err error) {
rsa.mu.Lock()
defer rsa.mu.Unlock()
if _, err := rsa.rs.Seek(off, io.SeekStart); err != nil {
return 0, err
}
return rsa.rs.Read(p)
}

0 comments on commit 4b9c91b

Please sign in to comment.