github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/util/ioutil/size.go (about)

     1  package ioutil
     2  
     3  import (
     4  	"io"
     5  	"io/fs"
     6  
     7  	"github.com/ncruces/go-sqlite3"
     8  )
     9  
    10  // A SizeReaderAt is a ReaderAt with a Size method.
    11  // Use [NewSizeReaderAt] to adapt different Size interfaces.
    12  type SizeReaderAt interface {
    13  	Size() (int64, error)
    14  	io.ReaderAt
    15  }
    16  
    17  // NewSizeReaderAt returns a SizeReaderAt given an io.ReaderAt
    18  // that implements one of:
    19  //   - Size() (int64, error)
    20  //   - Size() int64
    21  //   - Len() int
    22  //   - Stat() (fs.FileInfo, error)
    23  //   - Seek(offset int64, whence int) (int64, error)
    24  func NewSizeReaderAt(r io.ReaderAt) SizeReaderAt {
    25  	return sizer{r}
    26  }
    27  
    28  type sizer struct{ io.ReaderAt }
    29  
    30  func (s sizer) Size() (int64, error) {
    31  	switch s := s.ReaderAt.(type) {
    32  	case interface{ Size() (int64, error) }:
    33  		return s.Size()
    34  	case interface{ Size() int64 }:
    35  		return s.Size(), nil
    36  	case interface{ Len() int }:
    37  		return int64(s.Len()), nil
    38  	case interface{ Stat() (fs.FileInfo, error) }:
    39  		fi, err := s.Stat()
    40  		if err != nil {
    41  			return 0, err
    42  		}
    43  		return fi.Size(), nil
    44  	case io.Seeker:
    45  		return s.Seek(0, io.SeekEnd)
    46  	}
    47  	return 0, sqlite3.IOERR_SEEK
    48  }