Commit f3fc5958 authored by Masih H. Derkani's avatar Masih H. Derkani Committed by Daniel Martí

Refactor utility io conversions into one internal package

Improve reader type conversion by checking if type satisfies
ReaderAt to avoid unnecessary wrapping.

Move io converters into one place.

Fixes:
- https://github.com/ipld/go-car/issues/145
parent 6434cd83
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"sync"
internalio "github.com/ipld/go-car/v2/internal/io" internalio "github.com/ipld/go-car/v2/internal/io"
...@@ -97,22 +96,6 @@ func GenerateIndexFromFile(path string) (index.Index, error) { ...@@ -97,22 +96,6 @@ func GenerateIndexFromFile(path string) (index.Index, error) {
return GenerateIndex(f) 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. // 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. // 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. // For a payload in CAR v2 format, an index is only generated if Header.HasIndex returns false.
...@@ -137,7 +120,7 @@ func ReadOrGenerateIndex(rs io.ReadSeeker) (index.Index, error) { ...@@ -137,7 +120,7 @@ func ReadOrGenerateIndex(rs io.ReadSeeker) (index.Index, error) {
return GenerateIndex(rs) return GenerateIndex(rs)
case 2: case 2:
// Read CAR v2 format // Read CAR v2 format
v2r, err := NewReader(&readSeekerAt{rs: rs}) v2r, err := NewReader(internalio.ToReaderAt(rs))
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -3,6 +3,7 @@ package io ...@@ -3,6 +3,7 @@ package io
import ( import (
"io" "io"
"io/ioutil" "io/ioutil"
"sync"
) )
var ( var (
...@@ -10,6 +11,7 @@ var ( ...@@ -10,6 +11,7 @@ var (
_ io.ByteReader = (*readSeekerPlusByte)(nil) _ io.ByteReader = (*readSeekerPlusByte)(nil)
_ io.ByteReader = (*discardingReadSeekerPlusByte)(nil) _ io.ByteReader = (*discardingReadSeekerPlusByte)(nil)
_ io.ReadSeeker = (*discardingReadSeekerPlusByte)(nil) _ io.ReadSeeker = (*discardingReadSeekerPlusByte)(nil)
_ io.ReaderAt = (*readSeekerAt)(nil)
) )
type ( type (
...@@ -30,6 +32,11 @@ type ( ...@@ -30,6 +32,11 @@ type (
io.ReadSeeker io.ReadSeeker
io.ByteReader io.ByteReader
} }
readSeekerAt struct {
rs io.ReadSeeker
mu sync.Mutex
}
) )
func ToByteReader(r io.Reader) io.ByteReader { func ToByteReader(r io.Reader) io.ByteReader {
...@@ -49,6 +56,13 @@ func ToByteReadSeeker(r io.Reader) ByteReadSeeker { ...@@ -49,6 +56,13 @@ func ToByteReadSeeker(r io.Reader) ByteReadSeeker {
return &discardingReadSeekerPlusByte{Reader: r} 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) { func (rb readerPlusByte) ReadByte() (byte, error) {
return readByte(rb) return readByte(rb)
} }
...@@ -89,3 +103,12 @@ func readByte(r io.Reader) (byte, error) { ...@@ -89,3 +103,12 @@ func readByte(r io.Reader) (byte, error) {
_, err := io.ReadFull(r, p[:]) _, err := io.ReadFull(r, p[:])
return p[0], err 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)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment