aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/bufpool/buffers.go22
-rw-r--r--internal/flatex/decompress_bytes.go10
-rw-r--r--internal/zlibx/decompress.go26
-rw-r--r--loose.go18
-rw-r--r--pack_pack.go54
5 files changed, 62 insertions, 68 deletions
diff --git a/internal/bufpool/buffers.go b/internal/bufpool/buffers.go
index 24b29fb5..27c017bd 100644
--- a/internal/bufpool/buffers.go
+++ b/internal/bufpool/buffers.go
@@ -23,11 +23,10 @@ const (
// pooled buffer, the caller should invoke Release() to return it to the pool.
//
// Buffers must not be copied after first use; doing so can cause double-returns
-// to the pool and data races. A zero-value Buffer is not valid for use.
-//
-//go:nocopy
+// to the pool and data races. A zero-value Buffer is not valid for use. Use
+// the pointer type (*Buffer) returned by Borrow/FromOwned to avoid accidental
+// copies.
type Buffer struct {
- _ noCopy
buf []byte
pool poolIndex
}
@@ -70,28 +69,28 @@ var bufferPools = func() []sync.Pool {
// unpooled buffer is allocated.
//
// The caller must call Release() when finished using the returned Buffer.
-func Borrow(capHint int) Buffer {
+func Borrow(capHint int) *Buffer {
if capHint < DefaultBufferCap {
capHint = DefaultBufferCap
}
classIdx, classCap, pooled := classFor(capHint)
if !pooled {
newBuf := make([]byte, 0, capHint)
- return Buffer{buf: newBuf, pool: unpooled}
+ return &Buffer{buf: newBuf, pool: unpooled}
}
buf := bufferPools[classIdx].Get().(*[]byte)
if cap(*buf) < classCap {
*buf = make([]byte, 0, classCap)
}
slice := (*buf)[:0]
- return Buffer{buf: slice, pool: poolIndex(classIdx)}
+ return &Buffer{buf: slice, pool: poolIndex(classIdx)}
}
// FromOwned constructs a Buffer from a caller-owned byte slice. The resulting
// Buffer does not participate in pooling and will never be returned to the
// internal pool when released.
-func FromOwned(buf []byte) Buffer {
- return Buffer{buf: buf, pool: unpooled}
+func FromOwned(buf []byte) *Buffer {
+ return &Buffer{buf: buf, pool: unpooled}
}
// Resize adjusts the length of the buffer to n bytes. If n exceeds the current
@@ -187,8 +186,3 @@ func (buf *Buffer) returnToPool() {
tmp := buf.buf[:0]
bufferPools[int(buf.pool)].Put(&tmp)
}
-
-type noCopy struct{}
-
-func (*noCopy) Lock() {}
-func (*noCopy) Unlock() {}
diff --git a/internal/flatex/decompress_bytes.go b/internal/flatex/decompress_bytes.go
index 5e29f82d..ce6d0558 100644
--- a/internal/flatex/decompress_bytes.go
+++ b/internal/flatex/decompress_bytes.go
@@ -25,26 +25,26 @@ var bufferDecompressorPool = sync.Pool{
// Decompress inflates the provided DEFLATE stream and returns the full output
// in a pooled bufpool.Buffer along with the number of consumed bytes from src.
-func Decompress(src []byte) (bufpool.Buffer, int, error) {
+func Decompress(src []byte) (*bufpool.Buffer, int, error) {
return DecompressDictSized(src, nil, 0)
}
// DecompressDict inflates the provided DEFLATE stream using dict as the preset
// dictionary and returns the full output in a pooled bufpool.Buffer. The second
// returned value reports how many bytes of src were consumed.
-func DecompressDict(src []byte, dict []byte) (bufpool.Buffer, int, error) {
+func DecompressDict(src []byte, dict []byte) (*bufpool.Buffer, int, error) {
return DecompressDictSized(src, dict, 0)
}
// DecompressDictSized is like DecompressDict but allows providing an expected
// output size to pre-size the destination buffer and avoid repeated growth.
// A non-positive sizeHint falls back to the default buffer capacity.
-func DecompressDictSized(src []byte, dict []byte, sizeHint int) (bufpool.Buffer, int, error) {
+func DecompressDictSized(src []byte, dict []byte, sizeHint int) (*bufpool.Buffer, int, error) {
d := bufferDecompressorPool.Get().(*bufferDecompressor)
defer bufferDecompressorPool.Put(d)
if err := d.inflater.reset(src, dict); err != nil {
- return bufpool.Buffer{}, 0, err
+ return nil, 0, err
}
out := bufpool.Borrow(sizeHint)
@@ -61,7 +61,7 @@ func DecompressDictSized(src []byte, dict []byte, sizeHint int) (bufpool.Buffer,
return out, d.inflater.pos, nil
}
out.Release()
- return bufpool.Buffer{}, 0, d.inflater.err
+ return nil, 0, d.inflater.err
}
d.inflater.step(&d.inflater)
if d.inflater.err != nil && len(d.inflater.toRead) == 0 {
diff --git a/internal/zlibx/decompress.go b/internal/zlibx/decompress.go
index c6eb65e5..68a92587 100644
--- a/internal/zlibx/decompress.go
+++ b/internal/zlibx/decompress.go
@@ -11,71 +11,71 @@ import (
// Decompress inflates the provided zlib wrapped stream and returns the
// uncompressed data inside a pooled bufpool.Buffer.
-func Decompress(src []byte) (bufpool.Buffer, error) {
+func Decompress(src []byte) (*bufpool.Buffer, error) {
return DecompressSized(src, 0)
}
// DecompressSized inflates the provided zlib stream, using sizeHint to
// preallocate the output buffer when known (e.g. packfile entries).
-func DecompressSized(src []byte, sizeHint int) (bufpool.Buffer, error) {
+func DecompressSized(src []byte, sizeHint int) (*bufpool.Buffer, error) {
return DecompressDictSized(src, nil, sizeHint)
}
// DecompressDict is like Decompress but accepts a preset dictionary. The
// dictionary must match the checksum embedded in the stream if the dictionary
// flag is present.
-func DecompressDict(src []byte, dict []byte) (bufpool.Buffer, error) {
+func DecompressDict(src []byte, dict []byte) (*bufpool.Buffer, error) {
return DecompressDictSized(src, dict, 0)
}
// DecompressDictSized is like DecompressDict but allows providing an expected
// uncompressed size to avoid buffer growth copies.
-func DecompressDictSized(src []byte, dict []byte, sizeHint int) (bufpool.Buffer, error) {
+func DecompressDictSized(src []byte, dict []byte, sizeHint int) (*bufpool.Buffer, error) {
if len(src) < 6 {
- return bufpool.Buffer{}, io.ErrUnexpectedEOF
+ return nil, io.ErrUnexpectedEOF
}
cmf := src[0]
flg := src[1]
if (cmf&0x0f != zlibDeflate) || (cmf>>4 > zlibMaxWindow) || (binary.BigEndian.Uint16(src[:2])%31 != 0) {
- return bufpool.Buffer{}, ErrHeader
+ return nil, ErrHeader
}
offset := 2
haveDict := flg&0x20 != 0
if haveDict {
if len(src) < offset+4 {
- return bufpool.Buffer{}, io.ErrUnexpectedEOF
+ return nil, io.ErrUnexpectedEOF
}
if dict == nil {
- return bufpool.Buffer{}, ErrDictionary
+ return nil, ErrDictionary
}
checksum := binary.BigEndian.Uint32(src[offset : offset+4])
if checksum != adler32.Checksum(dict) {
- return bufpool.Buffer{}, ErrDictionary
+ return nil, ErrDictionary
}
offset += 4
}
if len(src[offset:]) < 4 {
- return bufpool.Buffer{}, io.ErrUnexpectedEOF
+ return nil, io.ErrUnexpectedEOF
}
deflateData := src[offset:]
out, consumed, err := flatex.DecompressDictSized(deflateData, dict, sizeHint)
if err != nil {
- return bufpool.Buffer{}, err
+ return nil, err
}
checksumPos := offset + consumed
if checksumPos+4 > len(src) {
out.Release()
- return bufpool.Buffer{}, io.ErrUnexpectedEOF
+ return nil, io.ErrUnexpectedEOF
}
expected := binary.BigEndian.Uint32(src[checksumPos : checksumPos+4])
if expected != adler32.Checksum(out.Bytes()) {
out.Release()
- return bufpool.Buffer{}, ErrChecksum
+ return nil, ErrChecksum
}
return out, nil
}
diff --git a/loose.go b/loose.go
index 86f67890..adfa8f05 100644
--- a/loose.go
+++ b/loose.go
@@ -34,36 +34,36 @@ func (repo *Repository) looseRead(id Hash) (StoredObject, error) {
return obj, err
}
-func (repo *Repository) looseReadTyped(id Hash) (ObjectType, bufpool.Buffer, error) {
+func (repo *Repository) looseReadTyped(id Hash) (ObjectType, *bufpool.Buffer, error) {
path, err := repo.loosePath(id)
if err != nil {
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
path = repo.repoPath(path)
f, err := os.Open(path)
if err != nil {
if os.IsNotExist(err) {
- return ObjectTypeInvalid, bufpool.Buffer{}, ErrNotFound
+ return ObjectTypeInvalid, nil, ErrNotFound
}
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
defer func() { _ = f.Close() }()
compressed, err := io.ReadAll(f)
if err != nil {
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
raw, err := zlibx.Decompress(compressed)
if err != nil {
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
rawBytes := raw.Bytes()
nul := bytes.IndexByte(rawBytes, 0)
if nul < 0 {
raw.Release()
- return ObjectTypeInvalid, bufpool.Buffer{}, ErrInvalidObject
+ return ObjectTypeInvalid, nil, ErrInvalidObject
}
header := rawBytes[:nul]
@@ -72,11 +72,11 @@ func (repo *Repository) looseReadTyped(id Hash) (ObjectType, bufpool.Buffer, err
ty, declaredSize, err := parseLooseHeader(header)
if err != nil {
raw.Release()
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
if declaredSize != int64(len(body)) {
raw.Release()
- return ObjectTypeInvalid, bufpool.Buffer{}, ErrInvalidObject
+ return ObjectTypeInvalid, nil, ErrInvalidObject
}
copy(rawBytes, body)
diff --git a/pack_pack.go b/pack_pack.go
index 6dcfb5d9..99f885a1 100644
--- a/pack_pack.go
+++ b/pack_pack.go
@@ -63,10 +63,10 @@ func (repo *Repository) packReadAt(loc packlocation, want Hash) (StoredObject, e
return obj, err
}
-func (repo *Repository) packBodyResolveAtLocation(loc packlocation) (ObjectType, bufpool.Buffer, error) {
+func (repo *Repository) packBodyResolveAtLocation(loc packlocation) (ObjectType, *bufpool.Buffer, error) {
pf, err := repo.packFile(loc.PackPath)
if err != nil {
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
return repo.packBodyResolveWithin(pf, loc.Offset)
}
@@ -100,17 +100,17 @@ func packHeaderParse(data []byte) (ObjectType, int, int, error) {
return ty, size, consumed, nil
}
-func packSectionInflate(pf *packFile, start uint64, sizeHint int) (bufpool.Buffer, error) {
+func packSectionInflate(pf *packFile, start uint64, sizeHint int) (*bufpool.Buffer, error) {
if start > uint64(len(pf.data)) {
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
body, err := zlibx.DecompressSized(pf.data[start:], sizeHint)
if err != nil {
- return bufpool.Buffer{}, err
+ return nil, err
}
if sizeHint > 0 && len(body.Bytes()) != sizeHint {
body.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
return body, nil
}
@@ -228,13 +228,13 @@ func (repo *Repository) packTypeSizeWithin(pf *packFile, ofs uint64, seen map[pa
}
}
-func (repo *Repository) packBodyResolveWithin(pf *packFile, ofs uint64) (ObjectType, bufpool.Buffer, error) {
+func (repo *Repository) packBodyResolveWithin(pf *packFile, ofs uint64) (ObjectType, *bufpool.Buffer, error) {
if pf == nil {
- return ObjectTypeInvalid, bufpool.Buffer{}, ErrInvalidObject
+ return ObjectTypeInvalid, nil, ErrInvalidObject
}
type deltaFrame struct {
- delta bufpool.Buffer
+ delta *bufpool.Buffer
}
var frames []deltaFrame
defer func() {
@@ -244,16 +244,16 @@ func (repo *Repository) packBodyResolveWithin(pf *packFile, ofs uint64) (ObjectT
}()
var (
- body bufpool.Buffer
+ body *bufpool.Buffer
bodyReady bool
resultTy ObjectType
)
- fail := func(err error) (ObjectType, bufpool.Buffer, error) {
+ fail := func(err error) (ObjectType, *bufpool.Buffer, error) {
if bodyReady {
body.Release()
bodyReady = false
}
- return ObjectTypeInvalid, bufpool.Buffer{}, err
+ return ObjectTypeInvalid, nil, err
}
resolved := false
@@ -351,20 +351,20 @@ func (repo *Repository) packBodyResolveWithin(pf *packFile, ofs uint64) (ObjectT
return resultTy, body, nil
}
-func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
+func packDeltaApply(base, delta *bufpool.Buffer) (*bufpool.Buffer, error) {
pos := 0
baseBytes := base.Bytes()
deltaBytes := delta.Bytes()
srcSize, err := packVarintRead(deltaBytes, &pos)
if err != nil {
- return bufpool.Buffer{}, err
+ return nil, err
}
dstSize, err := packVarintRead(deltaBytes, &pos)
if err != nil {
- return bufpool.Buffer{}, err
+ return nil, err
}
if srcSize != len(baseBytes) {
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
out := bufpool.Borrow(dstSize)
out.Resize(dstSize)
@@ -381,7 +381,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x01 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
off |= int(deltaBytes[pos])
pos++
@@ -389,7 +389,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x02 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
off |= int(deltaBytes[pos]) << 8
pos++
@@ -397,7 +397,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x04 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
off |= int(deltaBytes[pos]) << 16
pos++
@@ -405,7 +405,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x08 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
off |= int(deltaBytes[pos]) << 24
pos++
@@ -413,7 +413,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x10 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
n |= int(deltaBytes[pos])
pos++
@@ -421,7 +421,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x20 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
n |= int(deltaBytes[pos]) << 8
pos++
@@ -429,7 +429,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
if op&0x40 != 0 {
if pos >= len(deltaBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
n |= int(deltaBytes[pos]) << 16
pos++
@@ -439,7 +439,7 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
}
if off+n > len(baseBytes) || outPos+n > len(outBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
copy(outBytes[outPos:], baseBytes[off:off+n])
outPos += n
@@ -447,20 +447,20 @@ func packDeltaApply(base, delta bufpool.Buffer) (bufpool.Buffer, error) {
n := int(op)
if pos+n > len(deltaBytes) || outPos+n > len(outBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
copy(outBytes[outPos:], deltaBytes[pos:pos+n])
pos += n
outPos += n
default:
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
}
if outPos != len(outBytes) {
out.Release()
- return bufpool.Buffer{}, ErrInvalidObject
+ return nil, ErrInvalidObject
}
return out, nil
}