From ed0a113f034aa42aea23471c4bc0d7af159b7002 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Wed, 19 Nov 2025 08:00:00 +0800 Subject: Probably should name the custom packages specially --- internal/flatex/decompress_bytes.go | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 internal/flatex/decompress_bytes.go (limited to 'internal/flatex/decompress_bytes.go') diff --git a/internal/flatex/decompress_bytes.go b/internal/flatex/decompress_bytes.go new file mode 100644 index 00000000..5a660b0a --- /dev/null +++ b/internal/flatex/decompress_bytes.go @@ -0,0 +1,64 @@ +package flatex + +import ( + "io" + "sync" + + "git.sr.ht/~runxiyu/furgit/internal/bufpool" +) + +// bufferDecompressor wraps the custom slice inflater so byte-slice +// decompressions avoid repeated allocations. +type bufferDecompressor struct { + inflater sliceInflater +} + +var bufferDecompressorPool = sync.Pool{ + New: func() any { + fixedHuffmanDecoderInit() + d := &bufferDecompressor{} + d.inflater.bits = new([maxNumLit + maxNumDist]int) + d.inflater.codebits = new([numCodes]int) + return d + }, +} + +// 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) { + return DecompressDict(src, nil) +} + +// 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) { + d := bufferDecompressorPool.Get().(*bufferDecompressor) + defer bufferDecompressorPool.Put(d) + + if err := d.inflater.reset(src, dict); err != nil { + return bufpool.Buffer{}, 0, err + } + + out := bufpool.Borrow(bufpool.DefaultBufferCap) + out.Resize(0) + + for { + if len(d.inflater.toRead) > 0 { + out.Append(d.inflater.toRead) + d.inflater.toRead = nil + continue + } + if d.inflater.err != nil { + if d.inflater.err == io.EOF { + return out, d.inflater.pos, nil + } + out.Release() + return bufpool.Buffer{}, 0, d.inflater.err + } + d.inflater.step(&d.inflater) + if d.inflater.err != nil && len(d.inflater.toRead) == 0 { + d.inflater.toRead = d.inflater.dict.readFlush() + } + } +} -- cgit v1.3.1-10-gc9f91