Documentation ¶
Index ¶
- Constants
- Variables
- func ApplyDelta(basisFile io.ReadSeeker, deltaReader DeltaReader, output io.Writer) error
- func VerifyNewFile(newFile io.Reader, deltaReader DeltaReader) error
- type Adler32RollingChecksum
- type Adler32RollingChecksumV2
- type BinaryDeltaReader
- type BinaryDeltaWriter
- func (w *BinaryDeltaWriter) Flush() error
- func (w *BinaryDeltaWriter) WriteCopyCommand(offset int64, length int64) error
- func (w *BinaryDeltaWriter) WriteDataCommand(source io.ReadSeeker, offset int64, length int64) (err error)
- func (w *BinaryDeltaWriter) WriteMetadata(hashAlgorithm HashAlgorithm, expectedNewFileHash []byte) error
- type ChunkSignature
- type DeltaBuilder
- type DeltaReader
- type DeltaWriter
- type HashAlgorithm
- type ProgressReporter
- type ReaderIterator
- func NewReaderIteratorBuffer(reader io.Reader, buffer []byte) ReaderIterator
- func NewReaderIteratorBufferNBytes(reader io.Reader, buffer []byte, nBytesToRead int64) ReaderIterator
- func NewReaderIteratorSize(reader io.Reader, bufferSize int) ReaderIterator
- func NewReaderIteratorSizeNBytes(reader io.Reader, bufferSize int, nBytesToRead int64) ReaderIterator
- type RollingChecksum
- type Sha1HashAlgorithm
- type Signature
- type SignatureBuilder
- type SignatureReader
Constants ¶
const ( SignatureMinimumChunkSize = 128 SignatureDefaultChunkSize = 2048 SignatureMaximumChunkSize = 31 * 1024 )
const Adler32RollingChecksumName = "Adler32"
const Adler32RollingChecksumV2Name = "Adler32V2"
Variables ¶
var BinaryCopyCommand = []byte{0x60}
var BinaryDataCommand = []byte{0x80}
var BinaryDeltaHeader = []byte("OCTODELTA")
var BinaryEndOfMetadata = []byte(">>>")
var BinarySignatureHeader = []byte("OCTOSIG")
var BinaryVersion = []byte{0x01}
Functions ¶
func ApplyDelta ¶
func ApplyDelta(basisFile io.ReadSeeker, deltaReader DeltaReader, output io.Writer) error
ApplyDelta builds thew new file. Verifying the hash of the written file is done seperately, to allow the caller to use a buffered output writer to improve performance.
func VerifyNewFile ¶
func VerifyNewFile(newFile io.Reader, deltaReader DeltaReader) error
Types ¶
type Adler32RollingChecksum ¶
type Adler32RollingChecksum struct{}
func NewAdler32RollingChecksum ¶
func NewAdler32RollingChecksum() *Adler32RollingChecksum
func (*Adler32RollingChecksum) Calculate ¶
func (_ *Adler32RollingChecksum) Calculate(block []byte) uint32
func (*Adler32RollingChecksum) Name ¶
func (_ *Adler32RollingChecksum) Name() string
type Adler32RollingChecksumV2 ¶
type Adler32RollingChecksumV2 struct{}
func NewAdler32RollingChecksumV2 ¶
func NewAdler32RollingChecksumV2() *Adler32RollingChecksumV2
func (*Adler32RollingChecksumV2) Calculate ¶
func (_ *Adler32RollingChecksumV2) Calculate(block []byte) uint32
func (*Adler32RollingChecksumV2) Name ¶
func (_ *Adler32RollingChecksumV2) Name() string
type BinaryDeltaReader ¶
type BinaryDeltaReader struct { ProgressReporter ProgressReporter // contains filtered or unexported fields }
func NewBinaryDeltaReader ¶
func NewBinaryDeltaReader(input io.Reader) *BinaryDeltaReader
func (*BinaryDeltaReader) ExpectedHash ¶
func (b *BinaryDeltaReader) ExpectedHash() ([]byte, error)
func (*BinaryDeltaReader) HashAlgorithm ¶
func (b *BinaryDeltaReader) HashAlgorithm() (HashAlgorithm, error)
type BinaryDeltaWriter ¶
func NewBinaryDeltaWriter ¶
func NewBinaryDeltaWriter(output io.Writer) *BinaryDeltaWriter
func (*BinaryDeltaWriter) Flush ¶
func (w *BinaryDeltaWriter) Flush() error
func (*BinaryDeltaWriter) WriteCopyCommand ¶
func (w *BinaryDeltaWriter) WriteCopyCommand(offset int64, length int64) error
WriteCopyCommand writes the "Copy Command" header to `output` followed by offset and length; There's no data
func (*BinaryDeltaWriter) WriteDataCommand ¶
func (w *BinaryDeltaWriter) WriteDataCommand(source io.ReadSeeker, offset int64, length int64) (err error)
WriteDataCommand writes the "Data Command" header to `output` then proceeds to read `length` bytes from `source`, seeking to `offset` and write those to `output`
func (*BinaryDeltaWriter) WriteMetadata ¶
func (w *BinaryDeltaWriter) WriteMetadata(hashAlgorithm HashAlgorithm, expectedNewFileHash []byte) error
type ChunkSignature ¶
type DeltaBuilder ¶
type DeltaBuilder struct {
ProgressReporter ProgressReporter
}
func NewDeltaBuilder ¶
func NewDeltaBuilder() *DeltaBuilder
func (*DeltaBuilder) Build ¶
func (d *DeltaBuilder) Build(newFile io.ReadSeeker, newFileLength int64, signatureFile io.Reader, signatureFileLength int64, deltaWriter DeltaWriter) error
Build creates a new delta file, writing it out using `deltaWriter` confusing naming: "newFile" isn't a new file that we are creating, but rather an existing file which is "new" in that we haven't created a delta for it yet.
type DeltaReader ¶
type DeltaReader interface { ExpectedHash() ([]byte, error) HashAlgorithm() (HashAlgorithm, error) // Apply reads the delta file. // This method will invoke the second func to copy the data from the original file multiple times if needed. // This method will also invoke first func to write data from the delta file to the destination file multiple times if needed. Apply( func([]byte) error, func(int64, int64) error, ) error }
type DeltaWriter ¶
type DeltaWriter interface { WriteMetadata(hashAlgorithm HashAlgorithm, expectedNewFileHash []byte) error WriteCopyCommand(offset int64, length int64) error WriteDataCommand(source io.ReadSeeker, offset int64, length int64) error // A DeltaWriter may "hold" the last CopyCommand, to allow merging sequential copy commands // Because of this, we need to tell the writer when it's done to flush any unwritten CopyCommand Flush() error }
type HashAlgorithm ¶
type HashAlgorithm interface { Name() string HashLength() int HashOverData(data []byte) []byte HashOverReader(reader io.Reader) ([]byte, error) }
var DefaultHashAlgorithm HashAlgorithm = &Sha1HashAlgorithm{}
type ProgressReporter ¶
type ProgressReporter interface {
ReportProgress(operation string, currentPosition int64, total int64)
}
func NewStdoutProgressReporter ¶
func NewStdoutProgressReporter() ProgressReporter
func NopProgressReporter ¶
func NopProgressReporter() ProgressReporter
type ReaderIterator ¶
type ReaderIterator struct { // Output; zero-init is good Current []byte // contains filtered or unexported fields }
ReaderIterator lets you treat reading bytes from an io.Reader as a for-loop. The logic of "read all the byes from an io.Reader" is surprisingly complex in Go. this struct wraps it up into a "Next/Current" iterator style object as used by bufio.Scanner, or IEnumerator in C# Important: Like bufio.Scanner, if Next() returns false you MUST check Err() to see if it failed Important: Calling Next() mutates the io.Reader so you can't create more than one ReaderIterator per reader Note: This is designed to be stack-allocated by the caller, so the New functions don't return pointers
func NewReaderIteratorBuffer ¶
func NewReaderIteratorBuffer(reader io.Reader, buffer []byte) ReaderIterator
NewReaderIteratorBuffer creates an iterator, referencing an already-allocated buffer that will read until EOF
func NewReaderIteratorBufferNBytes ¶
func NewReaderIteratorBufferNBytes(reader io.Reader, buffer []byte, nBytesToRead int64) ReaderIterator
NewReaderIteratorBufferNBytes creates an iterator that will stop after reading `nBytesToRead` bytes, referencing an already-allocated buffer
func NewReaderIteratorSize ¶
func NewReaderIteratorSize(reader io.Reader, bufferSize int) ReaderIterator
NewReaderIteratorSize creates an iterator, allocating a buffer of `bufferSize`
func NewReaderIteratorSizeNBytes ¶
func NewReaderIteratorSizeNBytes(reader io.Reader, bufferSize int, nBytesToRead int64) ReaderIterator
NewReaderIteratorSize creates an iterator, allocating a buffer of `bufferSize`
func (*ReaderIterator) Err ¶
func (b *ReaderIterator) Err() error
func (*ReaderIterator) Next ¶
func (b *ReaderIterator) Next() bool
Next calls `Read` on the underlying reader, returning true
type RollingChecksum ¶
type RollingChecksum interface { Name() string Calculate(block []byte) uint32 Rotate(checksum uint32, remove byte, add byte, chunkSize int) uint32 }
var DefaultChecksumAlgorithm RollingChecksum = NewAdler32RollingChecksum()
type Sha1HashAlgorithm ¶
type Sha1HashAlgorithm struct { }
func (*Sha1HashAlgorithm) HashLength ¶
func (s *Sha1HashAlgorithm) HashLength() int
returns the length in bytes of a Hash computed with this aglorithm
func (*Sha1HashAlgorithm) HashOverData ¶
func (s *Sha1HashAlgorithm) HashOverData(data []byte) []byte
func (*Sha1HashAlgorithm) HashOverReader ¶
func (s *Sha1HashAlgorithm) HashOverReader(reader io.Reader) ([]byte, error)
This will issue lots of 1k reads into the reader. It's up to the caller to pass us a bufio if performance is of concern
func (*Sha1HashAlgorithm) Name ¶
func (s *Sha1HashAlgorithm) Name() string
type Signature ¶
type Signature struct { HashAlgorithm HashAlgorithm RollingChecksumAlgorithm RollingChecksum Chunks []*ChunkSignature }
type SignatureBuilder ¶
type SignatureBuilder struct { ChunkSize int HashAlgorithm HashAlgorithm // must be non-null RollingChecksumAlgorithm RollingChecksum // must be non-null ProgressReporter ProgressReporter // must be non-null }
func NewSignatureBuilder ¶
func NewSignatureBuilder() *SignatureBuilder
type SignatureReader ¶
type SignatureReader struct {
ProgressReporter ProgressReporter // must be non-null
}
func NewSignatureReader ¶
func NewSignatureReader() *SignatureReader