distribution/vendor/github.com/go-llsqlite/crawshaw/sqlitex/blob-readwriter.go

68 lines
1.3 KiB
Go

package sqlitex
import (
"errors"
"io"
sqlite "github.com/go-llsqlite/crawshaw"
)
// This wraps a sqlite.Blob with positional state provide extra io implementations.
func NewBlobSeeker(blob *sqlite.Blob) *blobSeeker {
return &blobSeeker{
size: blob.Size(),
blob: blob,
ReaderAt: blob,
WriterAt: blob,
}
}
var _ interface {
io.ReadWriteSeeker
} = (*blobSeeker)(nil)
type blobSeeker struct {
io.ReaderAt
io.WriterAt
blob *sqlite.Blob
off int64
size int64
}
func (blob *blobSeeker) Read(p []byte) (n int, err error) {
if blob.off >= blob.size {
return 0, io.EOF
}
if rem := blob.size - blob.off; int64(len(p)) > rem {
p = p[:rem]
}
n, err = blob.ReadAt(p, blob.off)
blob.off += int64(n)
return n, err
}
func (blob *blobSeeker) Write(p []byte) (n int, err error) {
if rem := blob.size - blob.off; int64(len(p)) > rem {
return 0, io.ErrShortWrite
}
n, err = blob.WriteAt(p, blob.off)
blob.off += int64(n)
return n, err
}
func (blob *blobSeeker) Seek(offset int64, whence int) (int64, error) {
switch whence {
case io.SeekStart:
// use offset directly
case io.SeekCurrent:
offset += blob.off
case io.SeekEnd:
offset += blob.size
}
if offset < 0 {
return blob.off, errors.New("seek to offset < 0")
}
blob.off = offset
return offset, nil
}