0402b0a2ee
Now allows creation of a squashfs.Reader from an io.Reader
134 lines
2.5 KiB
Go
134 lines
2.5 KiB
Go
package rawreader
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
)
|
|
|
|
func ConvertReader(r io.Reader) RawReader {
|
|
if rr, ok := r.(RawReader); ok {
|
|
return rr
|
|
}
|
|
if rs, is := r.(io.ReadSeeker); is {
|
|
return &fromReadSeeker{
|
|
ReadSeeker: rs,
|
|
}
|
|
}
|
|
return &fromReader{
|
|
rdr: r,
|
|
cache: make([]byte, 0),
|
|
}
|
|
}
|
|
|
|
func ConvertReaderAt(r io.ReaderAt) RawReader {
|
|
if rr, ok := r.(RawReader); ok {
|
|
return rr
|
|
}
|
|
return &fromReaderAt{
|
|
ReaderAt: r,
|
|
}
|
|
}
|
|
|
|
//TODO: Add way to discard data from fromReader
|
|
//RawReader implements the needed interfaces for reading a squashfs archive.
|
|
type RawReader interface {
|
|
io.ReadSeeker
|
|
io.ReaderAt
|
|
}
|
|
|
|
type fromReader struct {
|
|
rdr io.Reader
|
|
cache []byte
|
|
off int
|
|
}
|
|
|
|
func (r *fromReader) increaseCache(len int) error {
|
|
newCache := make([]byte, len)
|
|
_, err := r.rdr.Read(newCache)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.cache = append(r.cache, newCache...)
|
|
return nil
|
|
}
|
|
|
|
func (r *fromReader) ReadAt(p []byte, off int64) (n int, err error) {
|
|
if int(off)+len(p) > len(r.cache) {
|
|
r.increaseCache((int(off) + len(p)) - len(r.cache))
|
|
}
|
|
for i := int64(0); i < int64(len(p)); i++ {
|
|
p[i] = r.cache[off+i]
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *fromReader) Seek(off int64, whence int) (n int64, err error) {
|
|
switch whence {
|
|
case io.SeekEnd:
|
|
return 0, errors.New("cannot SeekEnd RawReader")
|
|
case io.SeekCurrent:
|
|
r.off += int(off)
|
|
case io.SeekStart:
|
|
r.off = int(off)
|
|
}
|
|
if r.off > len(r.cache) {
|
|
err = r.increaseCache(len(r.cache) - r.off)
|
|
if err != nil {
|
|
r.off = len(r.cache)
|
|
}
|
|
}
|
|
return int64(r.off), err
|
|
}
|
|
|
|
func (r *fromReader) Read(p []byte) (n int, err error) {
|
|
if len(p)+r.off > len(r.cache) {
|
|
err = r.increaseCache((len(p) + r.off) - len(r.cache))
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
for i := 0; i < len(p); i++ {
|
|
p[i] = r.cache[r.off+i]
|
|
}
|
|
r.off += len(p)
|
|
return
|
|
}
|
|
|
|
type fromReadSeeker struct {
|
|
io.ReadSeeker
|
|
}
|
|
|
|
func (r *fromReadSeeker) ReadAt(p []byte, off int64) (n int, err error) {
|
|
tmp, _ := r.Seek(0, io.SeekCurrent)
|
|
defer r.Seek(tmp, io.SeekStart)
|
|
_, err = r.Seek(off, io.SeekStart)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return r.Read(p)
|
|
}
|
|
|
|
type fromReaderAt struct {
|
|
io.ReaderAt
|
|
|
|
off int
|
|
}
|
|
|
|
func (r *fromReaderAt) Read(p []byte) (n int, err error) {
|
|
n, err = r.ReadAt(p, int64(r.off))
|
|
r.off += n
|
|
return
|
|
}
|
|
|
|
func (r *fromReaderAt) Seek(off int64, whence int) (n int64, err error) {
|
|
switch whence {
|
|
case io.SeekEnd:
|
|
return 0, errors.New("cannot SeekEnd RawReader")
|
|
case io.SeekCurrent:
|
|
r.off += int(off)
|
|
case io.SeekStart:
|
|
r.off = int(off)
|
|
}
|
|
return int64(r.off), nil
|
|
}
|