99 lines
1.9 KiB
Go
99 lines
1.9 KiB
Go
package asar
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
)
|
|
|
|
type SizedReaderAt interface {
|
|
io.ReaderAt
|
|
Size() int64
|
|
}
|
|
|
|
type WriterReaderAtWriterTo interface {
|
|
io.Writer
|
|
io.ReaderAt
|
|
io.WriterTo
|
|
}
|
|
|
|
type BytesReadAtWriter struct {
|
|
s []byte
|
|
i int64
|
|
}
|
|
|
|
func NewBytesReadAtWriter(s []byte) *BytesReadAtWriter {
|
|
return &BytesReadAtWriter{s: s, i: 0}
|
|
}
|
|
|
|
func (b *BytesReadAtWriter) Write(p []byte) (n int, err error) {
|
|
b.s = append(b.s, p...)
|
|
return len(p), nil
|
|
}
|
|
|
|
func (b *BytesReadAtWriter) ReadAt(p []byte, off int64) (n int, err error) {
|
|
// cannot modify state - see io.ReaderAt
|
|
if off < 0 {
|
|
return 0, errors.New("negative offset")
|
|
}
|
|
if off >= int64(len(b.s)) {
|
|
return 0, io.EOF
|
|
}
|
|
n = copy(p, b.s[off:])
|
|
if n < len(p) {
|
|
err = io.EOF
|
|
}
|
|
return
|
|
}
|
|
|
|
func (b *BytesReadAtWriter) WriteTo(w io.Writer) (n int64, err error) {
|
|
return io.Copy(w, bytes.NewReader(b.s))
|
|
}
|
|
|
|
type FilesystemStorage struct {
|
|
existing SizedReaderAt
|
|
new WriterReaderAtWriterTo
|
|
newOffset int64
|
|
}
|
|
|
|
func NewFilesystemStorage(existing SizedReaderAt, new WriterReaderAtWriterTo) *FilesystemStorage {
|
|
return &FilesystemStorage{
|
|
existing: existing,
|
|
new: new,
|
|
newOffset: 0,
|
|
}
|
|
}
|
|
|
|
func (fs *FilesystemStorage) Size() int64 {
|
|
return fs.existing.Size() + fs.newOffset
|
|
}
|
|
|
|
func (fs *FilesystemStorage) ReadAt(p []byte, off int64) (n int, err error) {
|
|
existingSize := fs.existing.Size()
|
|
if off < existingSize {
|
|
// error when cross boundary
|
|
if off+int64(len(p)) > existingSize {
|
|
return 0, io.ErrUnexpectedEOF
|
|
}
|
|
return fs.existing.ReadAt(p, off)
|
|
}
|
|
|
|
return fs.new.ReadAt(p, off-existingSize)
|
|
}
|
|
|
|
func (fs *FilesystemStorage) Write(p []byte) (n int, err error) {
|
|
n, err = fs.new.Write(p)
|
|
fs.newOffset += int64(n)
|
|
return
|
|
}
|
|
|
|
func (fs *FilesystemStorage) WriteTo(w io.Writer) (n int64, err error) {
|
|
// write existing
|
|
n, err = io.Copy(w, io.NewSectionReader(fs.existing, 0, fs.existing.Size()))
|
|
if err != nil {
|
|
return n, err
|
|
}
|
|
|
|
n2, err := fs.new.WriteTo(w)
|
|
return n + n2, err
|
|
}
|