[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/bluekeyes/go-gitdiff/master/gitdiff/binary_reader.go [Back]  [Original]

package gitdiff

import (
	"bytes"
	"compress/zlib"
	"fmt"
	"io"
)

// binaryReader reads the compressed raw data in a binary fragment,
// decompressing it and checking it against the expected size. Clients should
// read until it returns an error or io.EOF.
type binaryReader struct {
	r    *io.LimitedReader
	c    io.Closer
	size int64
	raw  []byte
}

func newBinaryReader(f *BinaryFragment) io.Reader {
	return &binaryReader{
		raw:  f.RawData,
		size: f.Size,
	}
}

func (r *binaryReader) Read(p []byte) (int, error) {
	// Defer initialization of the zlib reader so that we report any header
	// errors from Read() instead of when creating the binaryReader. This
	// allows clients to use io.ReadAll() directly with BinaryFragment.Data().
	if r.r == nil {
		zr, err := zlib.NewReader(bytes.NewReader(r.raw))
		if err != nil {
			return 0, err
		}
		r.r = &io.LimitedReader{R: zr, N: r.size + 1}
		r.c = zr
	}

	n, err := r.r.Read(p)
	if err == io.EOF {
		// If we reached the "end", first check that we read the correct amount
		// of data. On an exact read, the limit reader has one byte remaining.
		switch {
		case r.r.N > 1:
			return n, fmt.Errorf("incorrect inflated size: expected %d bytes, received %d", r.size, r.size-(r.r.N-1))
		case r.r.N < 1:
			return n, fmt.Errorf("incorrect inflated size: expected %d bytes, received more", r.size)
		}
		// Then check that the zlib checksum is valid by closing the reader
		if err := r.c.Close(); err != nil {
			return n, err
		}
	}
	return n, err
}

Web Proxy Viewer  |  New URL  |  Original Page