Files
sqlite3/sqlite3vfs/reader.go
Nuno Cruces 7ca9d79424 MemoryVFS.
2023-05-27 23:36:39 +01:00

119 lines
2.5 KiB
Go

package sqlite3vfs
import (
"io"
"io/fs"
)
// A ReaderVFS is a [VFS] for immutable databases.
type ReaderVFS map[string]SizeReaderAt
var _ VFS = ReaderVFS{}
// A SizeReaderAt is a ReaderAt with a Size method.
// Use [NewSizeReaderAt] to adapt different Size interfaces.
type SizeReaderAt interface {
Size() (int64, error)
io.ReaderAt
}
// Open implements the [VFS] interface.
func (vfs ReaderVFS) Open(name string, flags OpenFlag) (File, OpenFlag, error) {
if flags&OPEN_MAIN_DB == 0 {
return nil, flags, _CANTOPEN
}
if ra, ok := vfs[name]; ok {
return readerFile{ra}, flags, nil
}
return nil, flags, _CANTOPEN
}
// Delete implements the [VFS] interface.
func (vfs ReaderVFS) Delete(name string, dirSync bool) error {
return _IOERR_DELETE
}
// Access implements the [VFS] interface.
func (vfs ReaderVFS) Access(name string, flag AccessFlag) (bool, error) {
return false, nil
}
// FullPathname implements the [VFS] interface.
func (vfs ReaderVFS) FullPathname(name string) (string, error) {
return name, nil
}
type readerFile struct{ SizeReaderAt }
func (r readerFile) Close() error {
if c, ok := r.SizeReaderAt.(io.Closer); ok {
return c.Close()
}
return nil
}
func (readerFile) WriteAt(b []byte, off int64) (n int, err error) {
return 0, _READONLY
}
func (readerFile) Truncate(size int64) error {
return _READONLY
}
func (readerFile) Sync(flag SyncFlag) error {
return nil
}
func (readerFile) Lock(lock LockLevel) error {
return nil
}
func (readerFile) Unlock(lock LockLevel) error {
return nil
}
func (readerFile) CheckReservedLock() (bool, error) {
return false, nil
}
func (readerFile) SectorSize() int {
return 0
}
func (readerFile) DeviceCharacteristics() DeviceCharacteristic {
return IOCAP_IMMUTABLE
}
// NewSizeReaderAt returns a SizeReaderAt given an io.ReaderAt
// that implements one of:
// - Size() (int64, error)
// - Size() int64
// - Len() int
// - Stat() (fs.FileInfo, error)
// - Seek(offset int64, whence int) (int64, error)
func NewSizeReaderAt(r io.ReaderAt) SizeReaderAt {
return sizer{r}
}
type sizer struct{ io.ReaderAt }
func (s sizer) Size() (int64, error) {
switch s := s.ReaderAt.(type) {
case interface{ Size() (int64, error) }:
return s.Size()
case interface{ Size() int64 }:
return s.Size(), nil
case interface{ Len() int }:
return int64(s.Len()), nil
case interface{ Stat() (fs.FileInfo, error) }:
fi, err := s.Stat()
if err != nil {
return 0, err
}
return fi.Size(), nil
case io.Seeker:
return s.Seek(0, io.SeekEnd)
}
return 0, _IOERR_SEEK
}