octodiff

package
v0.0.0-...-31efa0c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2023 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	SignatureMinimumChunkSize = 128
	SignatureDefaultChunkSize = 2048
	SignatureMaximumChunkSize = 31 * 1024
)
View Source
const Adler32RollingChecksumName = "Adler32"
View Source
const Adler32RollingChecksumV2Name = "Adler32V2"

Variables

View Source
var BinaryCopyCommand = []byte{0x60}
View Source
var BinaryDataCommand = []byte{0x80}
View Source
var BinaryDeltaHeader = []byte("OCTODELTA")
View Source
var BinaryEndOfMetadata = []byte(">>>")
View Source
var BinarySignatureHeader = []byte("OCTOSIG")
View Source
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

func (*Adler32RollingChecksum) Rotate

func (_ *Adler32RollingChecksum) Rotate(checksum uint32, remove byte, add byte, chunkSize int) uint32

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

func (*Adler32RollingChecksumV2) Rotate

func (_ *Adler32RollingChecksumV2) Rotate(checksum uint32, remove byte, add byte, chunkSize int) uint32

type BinaryDeltaReader

type BinaryDeltaReader struct {
	ProgressReporter ProgressReporter
	// contains filtered or unexported fields
}

func NewBinaryDeltaReader

func NewBinaryDeltaReader(input io.Reader) *BinaryDeltaReader

func (*BinaryDeltaReader) Apply

func (b *BinaryDeltaReader) Apply(writeData func([]byte) error, copyData func(int64, int64) error) error

func (*BinaryDeltaReader) ExpectedHash

func (b *BinaryDeltaReader) ExpectedHash() ([]byte, error)

func (*BinaryDeltaReader) HashAlgorithm

func (b *BinaryDeltaReader) HashAlgorithm() (HashAlgorithm, error)

type BinaryDeltaWriter

type BinaryDeltaWriter struct {
	Output io.Writer
	// contains filtered or unexported fields
}

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 ChunkSignature struct {
	// StartOffset is not written to disk, it's just calculated in-memory
	StartOffset int64
	// These fields are included in the binary file
	Length          uint16
	Hash            []byte
	RollingChecksum uint32
}

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

func (*SignatureBuilder) Build

func (s *SignatureBuilder) Build(input io.Reader, inputLength int64, output io.Writer) error

type SignatureReader

type SignatureReader struct {
	ProgressReporter ProgressReporter // must be non-null
}

func NewSignatureReader

func NewSignatureReader() *SignatureReader

func (*SignatureReader) ReadSignature

func (s *SignatureReader) ReadSignature(input io.Reader, inputLength int64) (*Signature, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL