mirror of
https://github.com/restic/restic.git
synced 2025-12-03 21:51:47 +00:00
move Backend interface to backend package
This commit is contained in:
117
internal/backend/rewind_reader.go
Normal file
117
internal/backend/rewind_reader.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/restic/restic/internal/errors"
|
||||
)
|
||||
|
||||
// RewindReader allows resetting the Reader to the beginning of the data.
|
||||
type RewindReader interface {
|
||||
io.Reader
|
||||
|
||||
// Rewind rewinds the reader so the same data can be read again from the
|
||||
// start.
|
||||
Rewind() error
|
||||
|
||||
// Length returns the number of bytes that can be read from the Reader
|
||||
// after calling Rewind.
|
||||
Length() int64
|
||||
|
||||
// Hash return a hash of the data if requested by the backed.
|
||||
Hash() []byte
|
||||
}
|
||||
|
||||
// ByteReader implements a RewindReader for a byte slice.
|
||||
type ByteReader struct {
|
||||
*bytes.Reader
|
||||
Len int64
|
||||
hash []byte
|
||||
}
|
||||
|
||||
// Rewind restarts the reader from the beginning of the data.
|
||||
func (b *ByteReader) Rewind() error {
|
||||
_, err := b.Reader.Seek(0, io.SeekStart)
|
||||
return err
|
||||
}
|
||||
|
||||
// Length returns the number of bytes read from the reader after Rewind is
|
||||
// called.
|
||||
func (b *ByteReader) Length() int64 {
|
||||
return b.Len
|
||||
}
|
||||
|
||||
// Hash return a hash of the data if requested by the backed.
|
||||
func (b *ByteReader) Hash() []byte {
|
||||
return b.hash
|
||||
}
|
||||
|
||||
// statically ensure that *ByteReader implements RewindReader.
|
||||
var _ RewindReader = &ByteReader{}
|
||||
|
||||
// NewByteReader prepares a ByteReader that can then be used to read buf.
|
||||
func NewByteReader(buf []byte, hasher hash.Hash) *ByteReader {
|
||||
var hash []byte
|
||||
if hasher != nil {
|
||||
// must never fail according to interface
|
||||
_, err := hasher.Write(buf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
hash = hasher.Sum(nil)
|
||||
}
|
||||
return &ByteReader{
|
||||
Reader: bytes.NewReader(buf),
|
||||
Len: int64(len(buf)),
|
||||
hash: hash,
|
||||
}
|
||||
}
|
||||
|
||||
// statically ensure that *FileReader implements RewindReader.
|
||||
var _ RewindReader = &FileReader{}
|
||||
|
||||
// FileReader implements a RewindReader for an open file.
|
||||
type FileReader struct {
|
||||
io.ReadSeeker
|
||||
Len int64
|
||||
hash []byte
|
||||
}
|
||||
|
||||
// Rewind seeks to the beginning of the file.
|
||||
func (f *FileReader) Rewind() error {
|
||||
_, err := f.ReadSeeker.Seek(0, io.SeekStart)
|
||||
return errors.Wrap(err, "Seek")
|
||||
}
|
||||
|
||||
// Length returns the length of the file.
|
||||
func (f *FileReader) Length() int64 {
|
||||
return f.Len
|
||||
}
|
||||
|
||||
// Hash return a hash of the data if requested by the backed.
|
||||
func (f *FileReader) Hash() []byte {
|
||||
return f.hash
|
||||
}
|
||||
|
||||
// NewFileReader wraps f in a *FileReader.
|
||||
func NewFileReader(f io.ReadSeeker, hash []byte) (*FileReader, error) {
|
||||
pos, err := f.Seek(0, io.SeekEnd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Seek")
|
||||
}
|
||||
|
||||
fr := &FileReader{
|
||||
ReadSeeker: f,
|
||||
Len: pos,
|
||||
hash: hash,
|
||||
}
|
||||
|
||||
err = fr.Rewind()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fr, nil
|
||||
}
|
||||
Reference in New Issue
Block a user