1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
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
}
|