Added a generic ReaderAt

This commit is contained in:
Brandon Dyck 2024-09-25 16:34:31 -06:00
parent e61bf67b85
commit c0603b1c30
2 changed files with 29 additions and 8 deletions

View File

@ -3,6 +3,7 @@
package cursor package cursor
import ( import (
"errors"
"io" "io"
) )
@ -32,6 +33,26 @@ type Cursor[Datum any] interface {
At(pos uint64) Cursor[Datum] At(pos uint64) Cursor[Datum]
} }
type ReaderAt[T any] interface {
ReadAt(p []T, off int64) (n int, err error)
}
type SliceReaderAt[T any] []T
func (s SliceReaderAt[T]) ReadAt(dst []T, off int64) (n int, err error) {
if off < 0 {
return 0, errors.New("SliceReaderAt.ReadAt: negative offset")
}
if off >= int64(len(s)) {
return 0, io.EOF
}
n = copy(dst, s[off:])
if n < len(dst) {
err = io.EOF
}
return n, err
}
type SliceCursor[Datum any] struct { type SliceCursor[Datum any] struct {
data []Datum data []Datum
offset uint64 offset uint64
@ -66,16 +87,16 @@ func (sc SliceCursor[Datum]) At(pos uint64) Cursor[Datum] {
return sc return sc
} }
type ReaderAtCursor struct { type ReaderAtCursor[T any] struct {
r io.ReaderAt r ReaderAt[T]
pos uint64 pos uint64
} }
func NewReaderAt(r io.ReaderAt) ReaderAtCursor { func NewReaderAt[T any](r ReaderAt[T]) ReaderAtCursor[T] {
return ReaderAtCursor{r: r} return ReaderAtCursor[T]{r: r}
} }
func (rac ReaderAtCursor) Read(dst []byte) (uint64, Cursor[byte], error) { func (rac ReaderAtCursor[T]) Read(dst []T) (uint64, Cursor[T], error) {
n, err := rac.r.ReadAt(dst, int64(rac.pos)) n, err := rac.r.ReadAt(dst, int64(rac.pos))
if n > 0 { if n > 0 {
rac.pos += uint64(n) rac.pos += uint64(n)
@ -83,11 +104,11 @@ func (rac ReaderAtCursor) Read(dst []byte) (uint64, Cursor[byte], error) {
return uint64(n), rac, err return uint64(n), rac, err
} }
func (rac ReaderAtCursor) Pos() uint64 { func (rac ReaderAtCursor[T]) Pos() uint64 {
return rac.pos return rac.pos
} }
func (rac ReaderAtCursor) At(pos uint64) Cursor[byte] { func (rac ReaderAtCursor[T]) At(pos uint64) Cursor[T] {
rac.pos = pos rac.pos = pos
return rac return rac
} }

View File

@ -105,7 +105,7 @@ func TestSliceCursor(t *testing.T) {
} }
func TestReaderAtCursor(t *testing.T) { func TestReaderAtCursor(t *testing.T) {
testCursor(t, func(b []byte) cursor.ReaderAtCursor { testCursor(t, func(b []byte) cursor.ReaderAtCursor[byte] {
return cursor.NewReaderAt(bytes.NewReader(b)) return cursor.NewReaderAt(bytes.NewReader(b))
}) })
t.Run("Read returns an error if the ReaderAt fails", rapid.MakeCheck(func(t *rapid.T) { t.Run("Read returns an error if the ReaderAt fails", rapid.MakeCheck(func(t *rapid.T) {