aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-02-20 19:06:13 +0800
committerGravatar Runxi Yu2026-02-20 19:07:14 +0800
commitaa513c069c1418734aea894dc944e27c6a78a3bb (patch)
tree687f0a11bb550fa088fd82a98ceb8979bbc35f69 /internal
parentComment on prior reverts removing the pack writing API (diff)
signatureNo signature
Delete everything, I'm redesigning this.
I'll stop using a flat package and make things much more modular. And also experiment with streaming APIs so large blobs don't OOM us.
Diffstat (limited to 'internal')
-rw-r--r--internal/adler32/LICENSE30
-rw-r--r--internal/adler32/LICENSE.ZLIB17
-rw-r--r--internal/adler32/README1
-rw-r--r--internal/adler32/adler32_amd64.go93
-rw-r--r--internal/adler32/adler32_arm64.go73
-rw-r--r--internal/adler32/adler32_avx2.go6
-rw-r--r--internal/adler32/adler32_avx2.s263
-rw-r--r--internal/adler32/adler32_fallback.go19
-rw-r--r--internal/adler32/adler32_generic.go45
-rw-r--r--internal/adler32/adler32_neon.go6
-rw-r--r--internal/adler32/adler32_neon.s208
-rw-r--r--internal/adler32/adler32_sse3.go6
-rw-r--r--internal/adler32/adler32_sse3.s214
-rw-r--r--internal/adler32/bench_test.go22
-rw-r--r--internal/bloom/bloom.go236
-rw-r--r--internal/bloom/errors.go5
-rw-r--r--internal/bufpool/buffers.go189
-rw-r--r--internal/bufpool/buffers_test.go77
-rw-r--r--internal/flatex/LICENSE27
-rw-r--r--internal/flatex/decompress.go38
-rw-r--r--internal/flatex/decompress_test.go57
-rw-r--r--internal/flatex/huffman.go245
-rw-r--r--internal/flatex/slice_inflate.go472
-rw-r--r--internal/flatex/window_decoder.go101
-rw-r--r--internal/zlib/LICENSE27
-rw-r--r--internal/zlib/reader.go199
-rw-r--r--internal/zlib/writer.go228
-rw-r--r--internal/zlibx/LICENSE27
-rw-r--r--internal/zlibx/constants.go52
-rw-r--r--internal/zlibx/decompress.go54
-rw-r--r--internal/zlibx/decompress_test.go170
31 files changed, 0 insertions, 3207 deletions
diff --git a/internal/adler32/LICENSE b/internal/adler32/LICENSE
deleted file mode 100644
index 5cec357a..00000000
--- a/internal/adler32/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-Copyright (c) 2024, Michal Hruby
-Copyright (c) 2017 The Chromium Authors. All rights reserved.
-Copyright (c) 1995-2024 Mark Adler
-Copyright (c) 1995-2024 Jean-loup Gailly
-Copyright (c) 2022 Adam Stylinski
-
-BSD 2-Clause License
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/internal/adler32/LICENSE.ZLIB b/internal/adler32/LICENSE.ZLIB
deleted file mode 100644
index c75c1568..00000000
--- a/internal/adler32/LICENSE.ZLIB
+++ /dev/null
@@ -1,17 +0,0 @@
-Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
diff --git a/internal/adler32/README b/internal/adler32/README
deleted file mode 100644
index b80acd00..00000000
--- a/internal/adler32/README
+++ /dev/null
@@ -1 +0,0 @@
-This package was mostly copied from github.com/mhr3/adler32-simd.
diff --git a/internal/adler32/adler32_amd64.go b/internal/adler32/adler32_amd64.go
deleted file mode 100644
index 88a854ed..00000000
--- a/internal/adler32/adler32_amd64.go
+++ /dev/null
@@ -1,93 +0,0 @@
-//go:build amd64 && !purego
-
-package adler32
-
-import (
- "encoding/binary"
- "errors"
- "hash"
- "hash/adler32"
-
- "golang.org/x/sys/cpu"
-)
-
-// The size of an Adler-32 checksum in bytes.
-const Size = 4
-
-var (
- hasSSE3 = cpu.X86.HasSSE3
- hasAVX2 = cpu.X86.HasAVX2
-)
-
-// digest represents the partial evaluation of a checksum.
-// The low 16 bits are s1, the high 16 bits are s2.
-type digest uint32
-
-func (d *digest) Reset() { *d = 1 }
-
-// New returns a new hash.Hash32 computing the Adler-32 checksum.
-func New() hash.Hash32 {
- if !hasSSE3 {
- return adler32.New()
- }
- d := new(digest)
- d.Reset()
- return d
-}
-
-func (d *digest) MarshalBinary() ([]byte, error) {
- b := make([]byte, 0, marshaledSize)
- b = append(b, magic...)
- b = binary.BigEndian.AppendUint32(b, uint32(*d))
- return b, nil
-}
-
-func (d *digest) UnmarshalBinary(b []byte) error {
- if len(b) < len(magic) || string(b[:len(magic)]) != magic {
- return errors.New("hash/adler32: invalid hash state identifier")
- }
- if len(b) != marshaledSize {
- return errors.New("hash/adler32: invalid hash state size")
- }
- *d = digest(binary.BigEndian.Uint32(b[len(magic):]))
- return nil
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return 4 }
-
-func (d *digest) Write(data []byte) (nn int, err error) {
- if len(data) >= 64 {
- var h uint32
- if hasAVX2 {
- h = adler32_avx2(uint32(*d), data)
- } else {
- h = adler32_sse3(uint32(*d), data)
- }
- *d = digest(h)
- } else {
- h := update(uint32(*d), data)
- *d = digest(h)
- }
- return len(data), nil
-}
-
-func (d *digest) Sum32() uint32 { return uint32(*d) }
-
-func (d *digest) Sum(in []byte) []byte {
- s := uint32(*d)
- return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
-}
-
-// Checksum returns the Adler-32 checksum of data.
-func Checksum(data []byte) uint32 {
- if !hasSSE3 || len(data) < 64 {
- return update(1, data)
- }
-
- if hasAVX2 {
- return adler32_avx2(1, data)
- }
- return adler32_sse3(1, data)
-}
diff --git a/internal/adler32/adler32_arm64.go b/internal/adler32/adler32_arm64.go
deleted file mode 100644
index ddf9cb5e..00000000
--- a/internal/adler32/adler32_arm64.go
+++ /dev/null
@@ -1,73 +0,0 @@
-//go:build arm64 && !purego
-
-package adler32
-
-import (
- "encoding/binary"
- "errors"
- "hash"
-)
-
-// The size of an Adler-32 checksum in bytes.
-const Size = 4
-
-// digest represents the partial evaluation of a checksum.
-// The low 16 bits are s1, the high 16 bits are s2.
-type digest uint32
-
-func (d *digest) Reset() { *d = 1 }
-
-// New returns a new hash.Hash32 computing the Adler-32 checksum.
-func New() hash.Hash32 {
- d := new(digest)
- d.Reset()
- return d
-}
-
-func (d *digest) MarshalBinary() ([]byte, error) {
- b := make([]byte, 0, marshaledSize)
- b = append(b, magic...)
- b = binary.BigEndian.AppendUint32(b, uint32(*d))
- return b, nil
-}
-
-func (d *digest) UnmarshalBinary(b []byte) error {
- if len(b) < len(magic) || string(b[:len(magic)]) != magic {
- return errors.New("hash/adler32: invalid hash state identifier")
- }
- if len(b) != marshaledSize {
- return errors.New("hash/adler32: invalid hash state size")
- }
- *d = digest(binary.BigEndian.Uint32(b[len(magic):]))
- return nil
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return 4 }
-
-func (d *digest) Write(data []byte) (nn int, err error) {
- if len(data) >= 64 {
- h := adler32_neon(uint32(*d), data)
- *d = digest(h)
- } else {
- h := update(uint32(*d), data)
- *d = digest(h)
- }
- return len(data), nil
-}
-
-func (d *digest) Sum32() uint32 { return uint32(*d) }
-
-func (d *digest) Sum(in []byte) []byte {
- s := uint32(*d)
- return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
-}
-
-// Checksum returns the Adler-32 checksum of data.
-func Checksum(data []byte) uint32 {
- if len(data) >= 64 {
- return adler32_neon(1, data)
- }
- return update(1, data)
-}
diff --git a/internal/adler32/adler32_avx2.go b/internal/adler32/adler32_avx2.go
deleted file mode 100644
index 042812b8..00000000
--- a/internal/adler32/adler32_avx2.go
+++ /dev/null
@@ -1,6 +0,0 @@
-//go:build !purego && amd64
-
-package adler32
-
-//go:noescape
-func adler32_avx2(in uint32, buf []byte) uint32
diff --git a/internal/adler32/adler32_avx2.s b/internal/adler32/adler32_avx2.s
deleted file mode 100644
index 1b9a1c50..00000000
--- a/internal/adler32/adler32_avx2.s
+++ /dev/null
@@ -1,263 +0,0 @@
-//go:build !purego && amd64
-
-#include "textflag.h"
-
-DATA weights_1_32<>+0x00(SB)/8, $0x191a1b1c1d1e1f20
-DATA weights_1_32<>+0x08(SB)/8, $0x1112131415161718
-DATA weights_1_32<>+0x10(SB)/8, $0x090a0b0c0d0e0f10
-DATA weights_1_32<>+0x18(SB)/8, $0x0102030405060708
-GLOBL weights_1_32<>(SB), (RODATA|NOPTR), $32
-
-DATA ones_u16<>+0x00(SB)/8, $0x0001000100010001
-DATA ones_u16<>+0x08(SB)/8, $0x0001000100010001
-DATA ones_u16<>+0x10(SB)/8, $0x0001000100010001
-DATA ones_u16<>+0x18(SB)/8, $0x0001000100010001
-GLOBL ones_u16<>(SB), (RODATA|NOPTR), $32
-
-DATA one_u16<>+0x00(SB)/2, $0x0001
-GLOBL one_u16<>(SB), (RODATA|NOPTR), $2
-
-TEXT ·adler32_avx2(SB), NOSPLIT, $0-36
- MOVLQZX in+0(FP), DI
- MOVQ buf_base+8(FP), SI
- MOVQ buf_len+16(FP), DX
- MOVQ buf_cap+24(FP), CX
- WORD $0x8548; BYTE $0xf6
- JE return_one
- WORD $0xf889
- WORD $0x8548; BYTE $0xd2
- JE return_result
- NOP
- NOP
- NOP
- WORD $0xc189
- WORD $0xe9c1; BYTE $0x10
- WORD $0xb70f; BYTE $0xc0
- CMPQ DX, $0x20
- JB tail16_check
- LONG $0x078071bf; BYTE $0x80
- LONG $0xc0eff9c5
- VMOVDQA weights_1_32<>(SB), Y1
- VPBROADCASTW one_u16<>(SB), Y2
- JMP block_loop_setup
-
-block_accum_init:
- LONG $0xf46ffdc5
- LONG $0xedefd1c5
-
-block_reduce:
- SUBQ AX, DX
- LONG $0xf572ddc5; BYTE $0x05
- LONG $0xdbfeddc5
- LONG $0x397de3c4; WORD $0x01f4
- LONG $0xecc6c8c5; BYTE $0x88
- LONG $0xe470f9c5; BYTE $0x88
- LONG $0xe4fed1c5
- LONG $0xec70f9c5; BYTE $0x55
- LONG $0xe4fed1c5
- LONG $0xe07ef9c5
- MOVQ AX, CX
- IMULQ DI, CX
- SHRQ $0x2f, CX
- LONG $0xfff1c969; WORD $0x0000
- WORD $0xc829
- LONG $0x397de3c4; WORD $0x01dc
- LONG $0xdbfed9c5
- LONG $0xe370f9c5; BYTE $0xee
- LONG $0xdcfee1c5
- LONG $0xe370f9c5; BYTE $0x55
- LONG $0xdbfed9c5
- LONG $0xd97ef9c5
- MOVQ CX, R8
- IMULQ DI, R8
- SHRQ $0x2f, R8
- LONG $0xf1c06945; WORD $0x00ff; BYTE $0x00
- WORD $0x2944; BYTE $0xc1
- CMPQ DX, $0x1f
- JBE tail_check
-
-block_loop_setup:
- LONG $0xe06ef9c5
- LONG $0xd96ef9c5
- CMPQ DX, $0x15b0
- LONG $0x15b0b841; WORD $0x0000
- LONG $0xc2420f4c
- WORD $0x8944; BYTE $0xc0
- LONG $0x001fe025; BYTE $0x00
- JE block_accum_init
- ADDQ $-0x20, R8
- LONG $0xedefd1c5
- LONG $0x20c0f641
- JNE block_loop_entry
- LONG $0x2e6ffec5
- ADDQ $0x20, SI
- LEAQ -0x20(AX), CX
- LONG $0xf0f6d5c5
- LONG $0xf4fecdc5
- LONG $0x0455e2c4; BYTE $0xe9
- LONG $0xeaf5d5c5
- LONG $0xdbfed5c5
- LONG $0xec6ffdc5
- LONG $0xe66ffdc5
- CMPQ R8, $0x20
- JAE block_loop_64
- JMP block_reduce
-
-block_loop_entry:
- MOVQ AX, CX
- CMPQ R8, $0x20
- JB block_reduce
-
-block_loop_64:
- LONG $0x366ffec5
- LONG $0x7e6ffec5; BYTE $0x20
- LONG $0xc0f64dc5
- LONG $0xc4fe3dc5
- LONG $0xecfed5c5
- LONG $0x044de2c4; BYTE $0xe1
- LONG $0xe2f5ddc5
- LONG $0xdbfeddc5
- ADDQ $0x40, SI
- LONG $0xe0f6c5c5
- LONG $0xe4febdc5
- LONG $0xedfebdc5
- LONG $0x0445e2c4; BYTE $0xf1
- LONG $0xf2f5cdc5
- LONG $0xdbfecdc5
- ADDQ $-0x40, CX
- JNE block_loop_64
- LONG $0xf46ffdc5
- JMP block_reduce
-
-return_one:
- LONG $0x000001b8; BYTE $0x00
-
-return_result:
- MOVL AX, ret+32(FP)
- RET
-
-tail_check:
- WORD $0x8548; BYTE $0xd2
- JE return_no_tail
-
-tail16_check:
- CMPQ DX, $0x10
- JB tail_bytes_setup
- WORD $0xb60f; BYTE $0x3e
- WORD $0xf801
- WORD $0xc101
- LONG $0x017eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x0246b60f
- WORD $0xf801
- WORD $0xc101
- LONG $0x037eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x0446b60f
- WORD $0xf801
- WORD $0xc101
- LONG $0x057eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x0646b60f
- WORD $0xf801
- WORD $0xc101
- LONG $0x077eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x0846b60f
- WORD $0xf801
- WORD $0xc101
- LONG $0x097eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x0a46b60f
- WORD $0xf801
- WORD $0xc101
- LONG $0x0b7eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x0c46b60f
- WORD $0xf801
- WORD $0xc101
- LONG $0x0d7eb60f
- WORD $0xc701
- WORD $0xf901
- LONG $0x46b60f44; BYTE $0x0e
- WORD $0x0141; BYTE $0xf8
- WORD $0x0144; BYTE $0xc1
- LONG $0x0f46b60f
- WORD $0x0144; BYTE $0xc0
- WORD $0xc101
- ADDQ $-0x10, DX
- JE final_reduce
- ADDQ $0x10, SI
-
-tail_bytes_setup:
- LEAQ -0x1(DX), DI
- MOVQ DX, R9
- ANDQ $0x3, R9
- JE tail_dword_setup
- XORL R8, R8
-
-tail_byte_loop:
- LONG $0x14b60f46; BYTE $0x06
- WORD $0x0144; BYTE $0xd0
- WORD $0xc101
- INCQ R8
- CMPQ R9, R8
- JNE tail_byte_loop
- ADDQ R8, SI
- SUBQ R8, DX
-
-tail_dword_setup:
- CMPQ DI, $0x3
- JB final_reduce
- XORL DI, DI
-
-tail_dword_loop:
- LONG $0x04b60f44; BYTE $0x3e
- WORD $0x0141; BYTE $0xc0
- WORD $0x0144; BYTE $0xc1
- LONG $0x3e44b60f; BYTE $0x01
- WORD $0x0144; BYTE $0xc0
- WORD $0xc101
- LONG $0x44b60f44; WORD $0x023e
- WORD $0x0141; BYTE $0xc0
- WORD $0x0144; BYTE $0xc1
- LONG $0x3e44b60f; BYTE $0x03
- WORD $0x0144; BYTE $0xc0
- WORD $0xc101
- ADDQ $0x4, DI
- CMPQ DX, DI
- JNE tail_dword_loop
-
-final_reduce:
- LONG $0x000f908d; WORD $0xffff
- CMPL AX, $0xfff1
- WORD $0x420f; BYTE $0xd0
- WORD $0xc889
- LONG $0x078071be; BYTE $0x80
- IMULQ AX, SI
- SHRQ $0x2f, SI
- LONG $0xfff1c669; WORD $0x0000
- WORD $0xc129
- WORD $0xe1c1; BYTE $0x10
- WORD $0xd109
- WORD $0xc889
- NOP
- NOP
- VZEROUPPER
- MOVL AX, ret+32(FP)
- RET
-
-return_no_tail:
- WORD $0xe1c1; BYTE $0x10
- WORD $0xc809
- NOP
- NOP
- VZEROUPPER
- MOVL AX, ret+32(FP)
- RET
diff --git a/internal/adler32/adler32_fallback.go b/internal/adler32/adler32_fallback.go
deleted file mode 100644
index c213c3c1..00000000
--- a/internal/adler32/adler32_fallback.go
+++ /dev/null
@@ -1,19 +0,0 @@
-//go:build (!arm64 && !amd64) || purego
-
-package adler32
-
-import (
- "hash"
- "hash/adler32"
-)
-
-// The size of an Adler-32 checksum in bytes.
-const Size = 4
-
-// New returns a new hash.Hash32 computing the Adler-32 checksum.
-func New() hash.Hash32 {
- return adler32.New()
-}
-
-// Checksum returns the Adler-32 checksum of data.
-func Checksum(data []byte) uint32 { return adler32.Checksum(data) }
diff --git a/internal/adler32/adler32_generic.go b/internal/adler32/adler32_generic.go
deleted file mode 100644
index f33e0f9b..00000000
--- a/internal/adler32/adler32_generic.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Package adler32 implements the Adler-32 checksum.
-package adler32
-
-const (
- // mod is the largest prime that is less than 65536.
- mod = 65521
- // nmax is the largest n such that
- // 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
- // It is mentioned in RFC 1950 (search for "5552").
- nmax = 5552
-
- // binary representation compatible with standard library.
- magic = "adl\x01"
- marshaledSize = len(magic) + 4
-)
-
-// Add p to the running checksum d.
-func update(d uint32, p []byte) uint32 {
- s1, s2 := d&0xffff, d>>16
- for len(p) > 0 {
- var q []byte
- if len(p) > nmax {
- p, q = p[:nmax], p[nmax:]
- }
- for len(p) >= 4 {
- s1 += uint32(p[0])
- s2 += s1
- s1 += uint32(p[1])
- s2 += s1
- s1 += uint32(p[2])
- s2 += s1
- s1 += uint32(p[3])
- s2 += s1
- p = p[4:]
- }
- for _, x := range p {
- s1 += uint32(x)
- s2 += s1
- }
- s1 %= mod
- s2 %= mod
- p = q
- }
- return s2<<16 | s1
-}
diff --git a/internal/adler32/adler32_neon.go b/internal/adler32/adler32_neon.go
deleted file mode 100644
index 521b71e0..00000000
--- a/internal/adler32/adler32_neon.go
+++ /dev/null
@@ -1,6 +0,0 @@
-//go:build !purego && arm64
-
-package adler32
-
-//go:noescape
-func adler32_neon(in uint32, buf []byte) uint32
diff --git a/internal/adler32/adler32_neon.s b/internal/adler32/adler32_neon.s
deleted file mode 100644
index 08b170bd..00000000
--- a/internal/adler32/adler32_neon.s
+++ /dev/null
@@ -1,208 +0,0 @@
-//go:build !purego && arm64
-
-#include "textflag.h"
-
-DATA mult_table<>+0x00(SB)/8, $0x001d001e001f0020
-DATA mult_table<>+0x08(SB)/8, $0x0019001a001b001c
-DATA mult_table<>+0x10(SB)/8, $0x0015001600170018
-DATA mult_table<>+0x18(SB)/8, $0x0011001200130014
-DATA mult_table<>+0x20(SB)/8, $0x000d000e000f0010
-DATA mult_table<>+0x28(SB)/8, $0x0009000a000b000c
-DATA mult_table<>+0x30(SB)/8, $0x0005000600070008
-DATA mult_table<>+0x38(SB)/8, $0x0001000200030004
-GLOBL mult_table<>(SB), (RODATA|NOPTR), $64
-
-TEXT ·adler32_neon(SB), NOSPLIT, $0-36
- MOVW in+0(FP), R0
- MOVD buf_base+8(FP), R1
- MOVD buf_len+16(FP), R2
- MOVD buf_cap+24(FP), R3
- NOP
- ANDS $15, R1, R10
- ANDW $65535, R0, R8
- LSRW $16, R0, R9
- NOP
- BEQ vector_loop_setup
- ADD $1, R1, R11
- MOVD R1, R12
-
-align_loop:
- WORD $0x3840158d
- SUB $1, R2, R2
- TST $15, R11
- ADD $1, R11, R11
- ADDW R13, R8, R8
- ADDW R9, R8, R9
- BNE align_loop
- MOVW $32881, R11
- MOVW $65521, R13
- MOVKW $(32775<<16), R11
- MOVW $4294901775, R12
- MOVW $65520, R14
- SUB R10, R1, R10
- UMULL R11, R9, R11
- ADDW R12, R8, R12
- CMPW R14, R8
- ADD $16, R10, R1
- LSR $47, R11, R11
- CSELW HI, R12, R8, R8
- MSUBW R13, R9, R11, R9
-
-vector_loop_setup:
- AND $31, R2, R10
- CMP $32, R2
- BCC tail_entry
- MOVD $mult_table<>(SB), R11
- ADD $0, R11, R11
- MOVW $32881, R14
- MOVW $173, R12
- MOVD $137438953440, R13
- MOVKW $(32775<<16), R14
- VLD1 (R11), [V0.H8, V1.H8, V2.H8, V3.H8]
- LSR $5, R2, R11
- MOVW $65521, R15
- VEXT $8, V0.B16, V0.B16, V4.B16
- VEXT $8, V1.B16, V1.B16, V5.B16
- VEXT $8, V2.B16, V2.B16, V6.B16
- VEXT $8, V3.B16, V3.B16, V7.B16
-
-vector_outer_loop:
- CMP $173, R11
- MOVD R1, R2
- CSEL LO, R11, R12, R16
- WORD $0x6f00e414
- MULW R16, R8, R0
- ADD R16<<5, R13, R17
- WORD $0x6f00e410
- AND $137438953440, R17, R17
- WORD $0x6f00e412
- WORD $0x6f00e413
- WORD $0x6f00e415
- VMOV R0, V20.S[3]
- MOVW R16, R0
- WORD $0x6f00e411
-
-vector_inner_loop:
- WORD $0xacc15857
- SUBSW $1, R0, R0
- VADD V17.S4, V20.S4, V20.S4
- WORD $0x2e3712b5
- WORD $0x6e371273
- WORD $0x6e202ad8
- WORD $0x2e361252
- WORD $0x6e361210
- WORD $0x6e206af8
- WORD $0x6e606b11
- BNE vector_inner_loop
- VSHL $5, V20.S4, V20.S4
- ADD R17, R1, R17
- SUBS R16, R11, R11
- ADD $32, R17, R1
- WORD $0x2e6082b4
- VEXT $8, V21.B16, V21.B16, V21.B16
- WORD $0x2e6482b4
- VEXT $8, V19.B16, V19.B16, V21.B16
- WORD $0x2e618274
- VEXT $8, V18.B16, V18.B16, V19.B16
- WORD $0x2e6582b4
- WORD $0x2e628254
- WORD $0x2e668274
- WORD $0x2e638214
- VEXT $8, V16.B16, V16.B16, V16.B16
- WORD $0x2e678214
- WORD $0x4eb1be30
- WORD $0x4eb4be91
- WORD $0x0eb1be10
- VMOV V16.S[1], R0
- FMOVS F16, R2
- ADDW R8, R2, R8
- ADDW R9, R0, R9
- UMULL R14, R8, R0
- UMULL R14, R9, R2
- LSR $47, R0, R0
- LSR $47, R2, R2
- MSUBW R15, R8, R0, R8
- MSUBW R15, R9, R2, R9
- BNE vector_outer_loop
-
-tail_entry:
- CBZ R10, return_result
- CMP $16, R10
- BCC tail_byte_loop
- WORD $0x3940002b
- SUBS $16, R10, R10
- WORD $0x3940042c
- WORD $0x3940082d
- ADDW R11, R8, R8
- WORD $0x39400c2b
- ADDW R9, R8, R9
- ADDW R12, R8, R8
- WORD $0x3940102c
- ADDW R8, R9, R9
- ADDW R13, R8, R8
- WORD $0x3940142d
- ADDW R8, R9, R9
- ADDW R11, R8, R8
- WORD $0x3940182b
- ADDW R8, R9, R9
- ADDW R12, R8, R8
- WORD $0x39401c2c
- ADDW R8, R9, R9
- ADDW R13, R8, R8
- ADDW R8, R9, R9
- ADDW R11, R8, R8
- WORD $0x3940202b
- ADDW R8, R9, R9
- ADDW R12, R8, R8
- WORD $0x3940242c
- ADDW R8, R9, R9
- WORD $0x3940382d
- ADDW R11, R8, R8
- WORD $0x3940282b
- ADDW R8, R9, R9
- ADDW R12, R8, R8
- WORD $0x39402c2c
- ADDW R8, R9, R9
- ADDW R11, R8, R8
- WORD $0x3940302b
- ADDW R8, R9, R9
- ADDW R12, R8, R8
- WORD $0x3940342c
- ADDW R8, R9, R9
- ADDW R11, R8, R8
- WORD $0x39403c2b
- ADDW R8, R9, R9
- ADDW R12, R8, R8
- ADDW R8, R9, R9
- ADDW R13, R8, R8
- ADDW R8, R9, R9
- ADDW R11, R8, R8
- ADDW R8, R9, R9
- BEQ final_reduce
- ADD $16, R1, R1
-
-tail_byte_loop:
- WORD $0x3840142b
- SUBS $1, R10, R10
- ADDW R11, R8, R8
- ADDW R9, R8, R9
- BNE tail_byte_loop
-
-final_reduce:
- MOVW $32881, R10
- MOVW $65521, R12
- MOVKW $(32775<<16), R10
- MOVW $4294901775, R11
- MOVW $65520, R13
- ADDW R11, R8, R11
- UMULL R10, R9, R10
- CMPW R13, R8
- CSELW HI, R11, R8, R8
- LSR $47, R10, R10
- MSUBW R12, R9, R10, R9
-
-return_result:
- ORRW R9<<16, R8, R0
- NOP
- MOVW R0, ret+32(FP)
- RET
diff --git a/internal/adler32/adler32_sse3.go b/internal/adler32/adler32_sse3.go
deleted file mode 100644
index 8e8c8a9b..00000000
--- a/internal/adler32/adler32_sse3.go
+++ /dev/null
@@ -1,6 +0,0 @@
-//go:build !purego && amd64
-
-package adler32
-
-//go:noescape
-func adler32_sse3(in uint32, buf []byte) uint32
diff --git a/internal/adler32/adler32_sse3.s b/internal/adler32/adler32_sse3.s
deleted file mode 100644
index 5880bab8..00000000
--- a/internal/adler32/adler32_sse3.s
+++ /dev/null
@@ -1,214 +0,0 @@
-//go:build !purego && amd64
-
-#include "textflag.h"
-
-DATA weights_17_32<>+0x00(SB)/8, $0x191a1b1c1d1e1f20
-DATA weights_17_32<>+0x08(SB)/8, $0x1112131415161718
-GLOBL weights_17_32<>(SB), (RODATA|NOPTR), $16
-
-DATA ones_u16<>+0x00(SB)/8, $0x0001000100010001
-DATA ones_u16<>+0x08(SB)/8, $0x0001000100010001
-GLOBL ones_u16<>(SB), (RODATA|NOPTR), $16
-
-DATA weights_1_16<>+0x00(SB)/8, $0x090a0b0c0d0e0f10
-DATA weights_1_16<>+0x08(SB)/8, $0x0102030405060708
-GLOBL weights_1_16<>(SB), (RODATA|NOPTR), $16
-
-TEXT ·adler32_sse3(SB), NOSPLIT, $0-36
- MOVLQZX in+0(FP), DI
- MOVQ buf_base+8(FP), SI
- MOVQ buf_len+16(FP), DX
- MOVQ buf_cap+24(FP), CX
- NOP
- NOP
- NOP
- WORD $0xf889
- LONG $0xc8b70f44
- WORD $0xe8c1; BYTE $0x10
- WORD $0xd189
- WORD $0xe183; BYTE $0x1f
- CMPQ DX, $0x20
- JAE block_loop_setup
- WORD $0x8944; BYTE $0xcf
- JMP tail_entry
-
-block_loop_setup:
- SHRQ $0x5, DX
- LONG $0xc0ef0f66
- MOVO weights_17_32<>(SB), X1
- MOVO ones_u16<>(SB), X2
- MOVO weights_1_16<>(SB), X3
- LONG $0x8071b841; WORD $0x8007
-
-block_outer_loop:
- CMPQ DX, $0xad
- LONG $0x00adba41; WORD $0x0000
- LONG $0xd2420f4c
- WORD $0x8944; BYTE $0xcf
- LONG $0xfaaf0f41
- LONG $0xef6e0f66
- LONG $0xe06e0f66
- WORD $0x8944; BYTE $0xd0
- LONG $0xf6ef0f66
-
-block_inner_loop:
- LONG $0x3e6f0ff3
- LONG $0x6f0f4466; BYTE $0xc7
- LONG $0x04380f66; BYTE $0xf9
- LONG $0xfaf50f66
- LONG $0xfcfe0f66
- LONG $0x666f0ff3; BYTE $0x10
- LONG $0xeefe0f66
- LONG $0xf60f4466; BYTE $0xc0
- LONG $0xfe0f4466; BYTE $0xc6
- LONG $0xf46f0f66
- LONG $0xf0f60f66
- LONG $0xfe0f4166; BYTE $0xf0
- LONG $0x04380f66; BYTE $0xe3
- LONG $0xe2f50f66
- LONG $0xe7fe0f66
- ADDQ $0x20, SI
- WORD $0xc8ff
- JNE block_inner_loop
- LONG $0xf5720f66; BYTE $0x05
- LONG $0xe5fe0f66
- LONG $0xee700f66; BYTE $0xb1
- LONG $0xeefe0f66
- LONG $0xf5700f66; BYTE $0xee
- LONG $0xf5fe0f66
- LONG $0xf77e0f66
- WORD $0x0144; BYTE $0xcf
- LONG $0xec700f66; BYTE $0xb1
- LONG $0xecfe0f66
- LONG $0xe5700f66; BYTE $0xee
- LONG $0xe5fe0f66
- LONG $0xe07e0f66
- MOVQ DI, R9
- IMULQ R8, R9
- SHRQ $0x2f, R9
- LONG $0xf1c96945; WORD $0x00ff; BYTE $0x00
- WORD $0x2944; BYTE $0xcf
- MOVQ AX, R9
- IMULQ R8, R9
- SHRQ $0x2f, R9
- LONG $0xf1c96945; WORD $0x00ff; BYTE $0x00
- WORD $0x2944; BYTE $0xc8
- WORD $0x8941; BYTE $0xf9
- SUBQ R10, DX
- JNE block_outer_loop
-
-tail_entry:
- WORD $0x8548; BYTE $0xc9
- JE return_result
- CMPL CX, $0x10
- JB tail_bytes_setup
- WORD $0xb60f; BYTE $0x16
- WORD $0xd701
- WORD $0xf801
- LONG $0x0156b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x027eb60f
- WORD $0xd701
- WORD $0xf801
- LONG $0x0356b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x047eb60f
- WORD $0xd701
- WORD $0xf801
- LONG $0x0556b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x067eb60f
- WORD $0xd701
- WORD $0xf801
- LONG $0x0756b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x087eb60f
- WORD $0xd701
- WORD $0xf801
- LONG $0x0956b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x0a7eb60f
- WORD $0xd701
- WORD $0xf801
- LONG $0x0b56b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x0c7eb60f
- WORD $0xd701
- WORD $0xf801
- LONG $0x0d56b60f
- WORD $0xfa01
- WORD $0xd001
- LONG $0x46b60f44; BYTE $0x0e
- WORD $0x0141; BYTE $0xd0
- WORD $0x0144; BYTE $0xc0
- LONG $0x0f7eb60f
- WORD $0x0144; BYTE $0xc7
- WORD $0xf801
- ADDQ $-0x10, CX
- JE final_reduce
- ADDQ $0x10, SI
-
-tail_bytes_setup:
- LEAQ -0x1(CX), DX
- MOVQ CX, R9
- ANDQ $0x3, R9
- JE tail_dword_setup
- XORL R8, R8
-
-tail_byte_loop:
- LONG $0x14b60f46; BYTE $0x06
- WORD $0x0144; BYTE $0xd7
- WORD $0xf801
- INCQ R8
- CMPQ R9, R8
- JNE tail_byte_loop
- ADDQ R8, SI
- SUBQ R8, CX
-
-tail_dword_setup:
- CMPQ DX, $0x3
- JB final_reduce
- XORL DX, DX
-
-tail_dword_loop:
- LONG $0x04b60f44; BYTE $0x16
- WORD $0x0141; BYTE $0xf8
- WORD $0x0144; BYTE $0xc0
- LONG $0x167cb60f; BYTE $0x01
- WORD $0x0144; BYTE $0xc7
- WORD $0xf801
- LONG $0x44b60f44; WORD $0x0216
- WORD $0x0141; BYTE $0xf8
- WORD $0x0144; BYTE $0xc0
- LONG $0x167cb60f; BYTE $0x03
- WORD $0x0144; BYTE $0xc7
- WORD $0xf801
- ADDQ $0x4, DX
- CMPQ CX, DX
- JNE tail_dword_loop
-
-final_reduce:
- LONG $0x000f8f8d; WORD $0xffff
- CMPL DI, $0xfff1
- WORD $0x420f; BYTE $0xcf
- WORD $0xc289
- LONG $0x078071be; BYTE $0x80
- IMULQ DX, SI
- SHRQ $0x2f, SI
- LONG $0xfff1d669; WORD $0x0000
- WORD $0xd029
- WORD $0xcf89
-
-return_result:
- WORD $0xe0c1; BYTE $0x10
- WORD $0xf809
- NOP
- NOP
- MOVL AX, ret+32(FP)
- RET
diff --git a/internal/adler32/bench_test.go b/internal/adler32/bench_test.go
deleted file mode 100644
index 7744b903..00000000
--- a/internal/adler32/bench_test.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package adler32
-
-import (
- "testing"
-)
-
-const benchmarkSize = 64 * 1024
-
-var data = make([]byte, benchmarkSize)
-
-func init() {
- for i := range benchmarkSize {
- data[i] = byte(i % 256)
- }
-}
-
-func BenchmarkChecksum(b *testing.B) {
- b.ReportAllocs()
- for range b.N {
- Checksum(data)
- }
-}
diff --git a/internal/bloom/bloom.go b/internal/bloom/bloom.go
deleted file mode 100644
index c1a116d6..00000000
--- a/internal/bloom/bloom.go
+++ /dev/null
@@ -1,236 +0,0 @@
-// Package bloom provides a bloom filter implementation used for changed-path
-// filters in Git commit graphs.
-package bloom
-
-import "encoding/binary"
-
-const (
- // DataHeaderSize is the size of the BDAT header in commit-graph files.
- DataHeaderSize = 3 * 4
- // DefaultMaxChange matches Git's default max-changed-paths behavior.
- DefaultMaxChange = 512
-)
-
-// Settings describe the changed-paths Bloom filter parameters stored in
-// commit-graph BDAT chunks.
-//
-// Obviously, they must match the repository's commit-graph settings to
-// interpret filters correctly.
-type Settings struct {
- HashVersion uint32
- NumHashes uint32
- BitsPerEntry uint32
- MaxChangePaths uint32
-}
-
-// Filter represents a changed-paths Bloom filter associated with a commit.
-//
-// The filter encodes which paths changed between a commit and its first
-// parent. Paths are expected to be in Git's slash-separated form and
-// are queried using a path and its prefixes (e.g. "a/b/c", "a/b", "a").
-type Filter struct {
- Data []byte
- Version uint32
-}
-
-// ParseSettings reads Bloom filter settings from a BDAT chunk header.
-func ParseSettings(bdat []byte) (*Settings, error) {
- if len(bdat) < DataHeaderSize {
- return nil, ErrInvalid
- }
- settings := &Settings{
- HashVersion: binary.BigEndian.Uint32(bdat[0:4]),
- NumHashes: binary.BigEndian.Uint32(bdat[4:8]),
- BitsPerEntry: binary.BigEndian.Uint32(bdat[8:12]),
- MaxChangePaths: DefaultMaxChange,
- }
- return settings, nil
-}
-
-// MightContain reports whether the Bloom filter may contain the given path.
-//
-// Evaluated against the full path and each of its directory prefixes. A true
-// result indicates a possible match; false means the path definitely did not
-// change.
-func (f *Filter) MightContain(path []byte, settings *Settings) bool {
- if f == nil || settings == nil {
- return false
- }
- if len(f.Data) == 0 {
- return false
- }
- keys := keyvec(path, settings)
- for i := range keys {
- if filterContainsKey(f, &keys[i], settings) {
- return true
- }
- }
- return false
-}
-
-type key struct {
- hashes []uint32
-}
-
-func keyvec(path []byte, settings *Settings) []key {
- if len(path) == 0 {
- return nil
- }
- count := 1
- for _, b := range path {
- if b == '/' {
- count++
- }
- }
- keys := make([]key, 0, count)
- keys = append(keys, keyFill(path, settings))
- for i := len(path) - 1; i >= 0; i-- {
- if path[i] == '/' {
- keys = append(keys, keyFill(path[:i], settings))
- }
- }
- return keys
-}
-
-func keyFill(path []byte, settings *Settings) key {
- const seed0 = 0x293ae76f
- const seed1 = 0x7e646e2c
- var h0, h1 uint32
- if settings.HashVersion == 2 {
- h0 = murmur3SeededV2(seed0, path)
- h1 = murmur3SeededV2(seed1, path)
- } else {
- h0 = murmur3SeededV1(seed0, path)
- h1 = murmur3SeededV1(seed1, path)
- }
- hashes := make([]uint32, settings.NumHashes)
- for i := uint32(0); i < settings.NumHashes; i++ {
- hashes[i] = h0 + i*h1
- }
- return key{hashes: hashes}
-}
-
-func filterContainsKey(filter *Filter, key *key, settings *Settings) bool {
- if filter == nil || key == nil || settings == nil {
- return false
- }
- if len(filter.Data) == 0 {
- return false
- }
- mod := uint64(len(filter.Data)) * 8
- for _, h := range key.hashes {
- idx := uint64(h) % mod
- bytePos := idx / 8
- bit := byte(1 << (idx & 7))
- if filter.Data[bytePos]&bit == 0 {
- return false
- }
- }
- return true
-}
-
-func murmur3SeededV2(seed uint32, data []byte) uint32 {
- const (
- c1 = 0xcc9e2d51
- c2 = 0x1b873593
- r1 = 15
- r2 = 13
- m = 5
- n = 0xe6546b64
- )
- h := seed
- nblocks := len(data) / 4
- for i := 0; i < nblocks; i++ {
- k := uint32(data[4*i]) |
- (uint32(data[4*i+1]) << 8) |
- (uint32(data[4*i+2]) << 16) |
- (uint32(data[4*i+3]) << 24)
- k *= c1
- k = (k << r1) | (k >> (32 - r1))
- k *= c2
-
- h ^= k
- h = (h << r2) | (h >> (32 - r2))
- h = h*m + n
- }
-
- var k1 uint32
- tail := data[nblocks*4:]
- switch len(tail) & 3 {
- case 3:
- k1 ^= uint32(tail[2]) << 16
- fallthrough
- case 2:
- k1 ^= uint32(tail[1]) << 8
- fallthrough
- case 1:
- k1 ^= uint32(tail[0])
- k1 *= c1
- k1 = (k1 << r1) | (k1 >> (32 - r1))
- k1 *= c2
- h ^= k1
- }
-
- h ^= uint32(len(data))
- h ^= h >> 16
- h *= 0x85ebca6b
- h ^= h >> 13
- h *= 0xc2b2ae35
- h ^= h >> 16
- return h
-}
-
-func murmur3SeededV1(seed uint32, data []byte) uint32 {
- const (
- c1 = 0xcc9e2d51
- c2 = 0x1b873593
- r1 = 15
- r2 = 13
- m = 5
- n = 0xe6546b64
- )
- h := seed
- nblocks := len(data) / 4
- for i := 0; i < nblocks; i++ {
- b0 := int8(data[4*i])
- b1 := int8(data[4*i+1])
- b2 := int8(data[4*i+2])
- b3 := int8(data[4*i+3])
- k := uint32(b0) |
- (uint32(b1) << 8) |
- (uint32(b2) << 16) |
- (uint32(b3) << 24)
- k *= c1
- k = (k << r1) | (k >> (32 - r1))
- k *= c2
-
- h ^= k
- h = (h << r2) | (h >> (32 - r2))
- h = h*m + n
- }
-
- var k1 uint32
- tail := data[nblocks*4:]
- switch len(tail) & 3 {
- case 3:
- k1 ^= uint32(int8(tail[2])) << 16
- fallthrough
- case 2:
- k1 ^= uint32(int8(tail[1])) << 8
- fallthrough
- case 1:
- k1 ^= uint32(int8(tail[0]))
- k1 *= c1
- k1 = (k1 << r1) | (k1 >> (32 - r1))
- k1 *= c2
- h ^= k1
- }
-
- h ^= uint32(len(data))
- h ^= h >> 16
- h *= 0x85ebca6b
- h ^= h >> 13
- h *= 0xc2b2ae35
- h ^= h >> 16
- return h
-}
diff --git a/internal/bloom/errors.go b/internal/bloom/errors.go
deleted file mode 100644
index fe38d1bc..00000000
--- a/internal/bloom/errors.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package bloom
-
-import "errors"
-
-var ErrInvalid = errors.New("bloom: invalid data")
diff --git a/internal/bufpool/buffers.go b/internal/bufpool/buffers.go
deleted file mode 100644
index 439e7e04..00000000
--- a/internal/bufpool/buffers.go
+++ /dev/null
@@ -1,189 +0,0 @@
-// Package bufpool provides a lightweight byte-buffer type with optional
-// pooling.
-package bufpool
-
-import "sync"
-
-const (
- // DefaultBufferCap is the minimum capacity a borrowed buffer will have.
- // Borrow() will allocate or retrieve a buffer with at least this capacity.
- DefaultBufferCap = 32 * 1024
-
- // maxPooledBuffer defines the maximum capacity of a buffer that may be
- // returned to the pool. Buffers larger than this will not be pooled to
- // avoid unbounded memory usage.
- maxPooledBuffer = 8 << 20
-)
-
-// Buffer is a growable byte container that optionally participates in a
-// memory pool. A Buffer may be obtained through Borrow() or constructed
-// directly from owned data via FromOwned().
-//
-// A Buffer's underlying slice may grow as needed. When finished with a
-// 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.
-//
-//go:nocopy
-type Buffer struct {
- _ struct{} // for nocopy
- buf []byte
- pool poolIndex
-}
-
-type poolIndex int8
-
-const (
- unpooled poolIndex = -1
-)
-
-var sizeClasses = [...]int{
- DefaultBufferCap,
- 64 << 10,
- 128 << 10,
- 256 << 10,
- 512 << 10,
- 1 << 20,
- 2 << 20,
- 4 << 20,
- maxPooledBuffer,
-}
-
-var bufferPools = func() []sync.Pool {
- pools := make([]sync.Pool, len(sizeClasses))
- for i, classCap := range sizeClasses {
- capCopy := classCap
- pools[i].New = func() any {
- buf := make([]byte, 0, capCopy)
- return &buf
- }
- }
- return pools
-}()
-
-// Borrow retrieves a Buffer suitable for storing up to capHint bytes.
-// The returned Buffer may come from an internal sync.Pool.
-//
-// If capHint is smaller than DefaultBufferCap, it is automatically raised
-// to DefaultBufferCap. If no pooled buffer has sufficient capacity, a new
-// unpooled buffer is allocated.
-//
-// The caller must call Release() when finished using the returned 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}
- }
- buf := bufferPools[classIdx].Get().(*[]byte)
- if cap(*buf) < classCap {
- *buf = make([]byte, 0, classCap)
- }
- slice := (*buf)[:0]
- 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}
-}
-
-// Resize adjusts the length of the buffer to n bytes. If n exceeds the current
-// capacity, the underlying storage is grown. If n is negative, it is treated
-// as zero.
-//
-// The buffer's new contents beyond the previous length are undefined.
-func (buf *Buffer) Resize(n int) {
- if n < 0 {
- n = 0
- }
- buf.ensureCapacity(n)
- buf.buf = buf.buf[:n]
-}
-
-// Append copies the provided bytes onto the end of the buffer, growing its
-// capacity if required. If src is empty, the method does nothing.
-//
-// The receiver retains ownership of the data; the caller may reuse src freely.
-func (buf *Buffer) Append(src []byte) {
- if len(src) == 0 {
- return
- }
- start := len(buf.buf)
- buf.ensureCapacity(start + len(src))
- buf.buf = buf.buf[:start+len(src)]
- copy(buf.buf[start:], src)
-}
-
-// Bytes returns the underlying byte slice that represents the current contents
-// of the buffer. Modifying the returned slice modifies the Buffer itself.
-func (buf *Buffer) Bytes() []byte {
- return buf.buf
-}
-
-// Release returns the buffer to the global pool if it originated from the
-// pool and its capacity is no larger than maxPooledBuffer. After release, the
-// Buffer becomes invalid and should not be used further.
-//
-// Releasing a non-pooled buffer has no effect beyond clearing its internal
-// storage.
-func (buf *Buffer) Release() {
- if buf.buf == nil {
- return
- }
- buf.returnToPool()
- buf.buf = nil
- buf.pool = unpooled
-}
-
-// ensureCapacity grows the underlying buffer to accommodate the requested
-// number of bytes. Growth doubles the capacity by default unless a larger
-// expansion is needed. If the previous storage was pooled and not oversized,
-// it is returned to the pool.
-func (buf *Buffer) ensureCapacity(needed int) {
- if cap(buf.buf) >= needed {
- return
- }
- classIdx, classCap, pooled := classFor(needed)
- var newBuf []byte
- if pooled {
- raw := bufferPools[classIdx].Get().(*[]byte)
- if cap(*raw) < classCap {
- *raw = make([]byte, 0, classCap)
- }
- newBuf = (*raw)[:len(buf.buf)]
- } else {
- newBuf = make([]byte, len(buf.buf), classCap)
- }
- copy(newBuf, buf.buf)
- buf.returnToPool()
- buf.buf = newBuf
- if pooled {
- buf.pool = poolIndex(classIdx)
- } else {
- buf.pool = unpooled
- }
-}
-
-func classFor(size int) (idx int, classCap int, ok bool) {
- for i, class := range sizeClasses {
- if size <= class {
- return i, class, true
- }
- }
- return -1, size, false
-}
-
-func (buf *Buffer) returnToPool() {
- if buf.pool == unpooled {
- return
- }
- tmp := buf.buf[:0]
- bufferPools[int(buf.pool)].Put(&tmp)
-}
diff --git a/internal/bufpool/buffers_test.go b/internal/bufpool/buffers_test.go
deleted file mode 100644
index f5c006da..00000000
--- a/internal/bufpool/buffers_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package bufpool
-
-import "testing"
-
-func TestBorrowBufferResizeAndAppend(t *testing.T) {
- b := Borrow(1)
- defer b.Release()
-
- if cap(b.buf) < DefaultBufferCap {
- t.Fatalf("expected capacity >= %d, got %d", DefaultBufferCap, cap(b.buf))
- }
-
- b.Append([]byte("alpha"))
- b.Append([]byte("beta"))
- if got := string(b.Bytes()); got != "alphabeta" {
- t.Fatalf("unexpected contents: %q", got)
- }
-
- b.Resize(3)
- if got := string(b.Bytes()); got != "alp" {
- t.Fatalf("resize shrink mismatch: %q", got)
- }
-
- b.Resize(8)
- if len(b.Bytes()) != 8 {
- t.Fatalf("expected len 8 after grow, got %d", len(b.Bytes()))
- }
- if prefix := string(b.Bytes()[:3]); prefix != "alp" {
- t.Fatalf("prefix lost after grow: %q", prefix)
- }
-}
-
-func TestBorrowBufferRelease(t *testing.T) {
- b := Borrow(DefaultBufferCap / 2)
- b.Append([]byte("data"))
- b.Release()
- if b.buf != nil {
- t.Fatal("expected buffer cleared after release")
- }
-}
-
-func TestBorrowUsesLargerPools(t *testing.T) {
- const request = DefaultBufferCap * 4
-
- classIdx, classCap, pooled := classFor(request)
- if !pooled {
- t.Fatalf("expected %d to map to a pooled class", request)
- }
-
- b := Borrow(request)
- if b.pool != poolIndex(classIdx) {
- t.Fatalf("expected pooled buffer in class %d, got %d", classIdx, b.pool)
- }
- if cap(b.buf) != classCap {
- t.Fatalf("expected capacity %d, got %d", classCap, cap(b.buf))
- }
- b.Release()
-
- b2 := Borrow(request)
- defer b2.Release()
- if b2.pool != poolIndex(classIdx) {
- t.Fatalf("expected pooled buffer in class %d on reuse, got %d", classIdx, b2.pool)
- }
- if cap(b2.buf) != classCap {
- t.Fatalf("expected capacity %d on reuse, got %d", classCap, cap(b2.buf))
- }
-}
-
-func TestGrowingBufferStaysPooled(t *testing.T) {
- b := Borrow(DefaultBufferCap)
- defer b.Release()
-
- b.Append(make([]byte, DefaultBufferCap*3))
- if b.pool == unpooled {
- t.Fatal("buffer should stay pooled after growth within limit")
- }
-}
diff --git a/internal/flatex/LICENSE b/internal/flatex/LICENSE
deleted file mode 100644
index 2a7cf70d..00000000
--- a/internal/flatex/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2009 The Go Authors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google LLC nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/internal/flatex/decompress.go b/internal/flatex/decompress.go
deleted file mode 100644
index 065e23f3..00000000
--- a/internal/flatex/decompress.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package flatex
-
-import (
- "io"
-
- "codeberg.org/lindenii/furgit/internal/bufpool"
-)
-
-func DecompressSized(src []byte, sizeHint int) (bufpool.Buffer, int, error) {
- d := sliceInflaterPool.Get().(*sliceInflater)
- defer sliceInflaterPool.Put(d)
-
- if err := d.reset(src); err != nil {
- return bufpool.Buffer{}, 0, err
- }
-
- out := bufpool.Borrow(sizeHint)
- out.Resize(0)
-
- for {
- if len(d.toRead) > 0 {
- out.Append(d.toRead)
- d.toRead = nil
- continue
- }
- if d.err != nil {
- if d.err == io.EOF {
- return out, d.pos, nil
- }
- out.Release()
- return bufpool.Buffer{}, 0, d.err
- }
- d.step(d)
- if d.err != nil && len(d.toRead) == 0 {
- d.toRead = d.window.readFlush()
- }
- }
-}
diff --git a/internal/flatex/decompress_test.go b/internal/flatex/decompress_test.go
deleted file mode 100644
index e53a6581..00000000
--- a/internal/flatex/decompress_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package flatex
-
-import (
- "bytes"
- stdflate "compress/flate"
- "testing"
-)
-
-func compressDeflate(t *testing.T, payload []byte) []byte {
- t.Helper()
- var buf bytes.Buffer
- w, err := stdflate.NewWriter(&buf, stdflate.DefaultCompression)
- if err != nil {
- t.Fatalf("NewWriter: %v", err)
- }
- if _, err := w.Write(payload); err != nil {
- t.Fatalf("Write: %v", err)
- }
- if err := w.Close(); err != nil {
- t.Fatalf("Close: %v", err)
- }
- return buf.Bytes()
-}
-
-func TestDecompressSized(t *testing.T) {
- payload := bytes.Repeat([]byte("golang"), 32)
- compressed := compressDeflate(t, payload)
-
- out, _, err := DecompressSized(compressed, 0)
- if err != nil {
- t.Fatalf("DecompressSized: %v", err)
- }
- defer out.Release()
-
- if !bytes.Equal(out.Bytes(), payload) {
- t.Fatalf("unexpected payload: got %q", out.Bytes())
- }
-}
-
-func TestDecompressSizedUsesHint(t *testing.T) {
- payload := []byte("short")
- compressed := compressDeflate(t, payload)
-
- const hint = 1 << 19
- out, _, err := DecompressSized(compressed, hint)
- if err != nil {
- t.Fatalf("DecompressSized: %v", err)
- }
- defer out.Release()
-
- if !bytes.Equal(out.Bytes(), payload) {
- t.Fatalf("unexpected payload: got %q", out.Bytes())
- }
- if cap(out.Bytes()) < hint {
- t.Fatalf("expected capacity >= %d, got %d", hint, cap(out.Bytes()))
- }
-}
diff --git a/internal/flatex/huffman.go b/internal/flatex/huffman.go
deleted file mode 100644
index 32172dbb..00000000
--- a/internal/flatex/huffman.go
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package flatex implements the DEFLATE compressed data format, described in
-// RFC 1951. The [compress/gzip] and [compress/zlib] packages implement access
-// to DEFLATE-based file formats.
-package flatex
-
-import (
- "math/bits"
- "strconv"
- "sync"
-)
-
-const (
- // The special code used to mark the end of a block.
- endBlockMarker = 256
- maxCodeLen = 16 // max length of Huffman code
- maxMatchOffset = 1 << 15 // The largest match offset
- // The next three numbers come from the RFC section 3.2.7, with the
- // additional proviso in section 3.2.5 which implies that distance codes
- // 30 and 31 should never occur in compressed data.
- maxNumLit = 286
- maxNumDist = 30
- numCodes = 19 // number of codes in Huffman meta-code
-)
-
-// A CorruptInputError reports the presence of corrupt input at a given offset.
-type CorruptInputError int64
-
-func (e CorruptInputError) Error() string {
- return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10)
-}
-
-// The data structure for decoding Huffman tables is based on that of
-// zlib. There is a lookup table of a fixed bit width (huffmanChunkBits),
-// For codes smaller than the table width, there are multiple entries
-// (each combination of trailing bits has the same value). For codes
-// larger than the table width, the table contains a link to an overflow
-// table. The width of each entry in the link table is the maximum code
-// size minus the chunk width.
-//
-// Note that you can do a lookup in the table even without all bits
-// filled. Since the extra bits are zero, and the DEFLATE Huffman codes
-// have the property that shorter codes come before longer ones, the
-// bit length estimate in the result is a lower bound on the actual
-// number of bits.
-//
-// See the following:
-// https://github.com/madler/zlib/raw/master/doc/algorithm.txt
-
-// chunk & 15 is number of bits
-// chunk >> 4 is value, including table link
-
-const (
- huffmanChunkBits = 9
- huffmanNumChunks = 1 << huffmanChunkBits
- huffmanCountMask = 15
- huffmanValueShift = 4
-)
-
-type huffmanDecoder struct {
- min int // the minimum code length
- chunks [huffmanNumChunks]uint32 // chunks as described above
- links [][]uint32 // overflow links
- linkMask uint32 // mask the width of the link table
-}
-
-// Initialize Huffman decoding tables from array of code lengths.
-// Following this function, h is guaranteed to be initialized into a complete
-// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a
-// degenerate case where the tree has only a single symbol with length 1. Empty
-// trees are permitted.
-func (h *huffmanDecoder) init(lengths []int) bool {
- // Sanity enables additional runtime tests during Huffman
- // table construction. It's intended to be used during
- // development to supplement the currently ad-hoc unit tests.
- const sanity = false
-
- if h.min != 0 {
- *h = huffmanDecoder{}
- }
-
- // Count number of codes of each length,
- // compute min and max length.
- var count [maxCodeLen]int
- var min, max int
- for _, n := range lengths {
- if n == 0 {
- continue
- }
- if min == 0 || n < min {
- min = n
- }
- if n > max {
- max = n
- }
- count[n]++
- }
-
- // Empty tree. The decompressor.huffSym function will fail later if the tree
- // is used. Technically, an empty tree is only valid for the HDIST tree and
- // not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree
- // is guaranteed to fail since it will attempt to use the tree to decode the
- // codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is
- // guaranteed to fail later since the compressed data section must be
- // composed of at least one symbol (the end-of-block marker).
- if max == 0 {
- return true
- }
-
- code := 0
- var nextcode [maxCodeLen]int
- for i := min; i <= max; i++ {
- code <<= 1
- nextcode[i] = code
- code += count[i]
- }
-
- // Check that the coding is complete (i.e., that we've
- // assigned all 2-to-the-max possible bit sequences).
- // Exception: To be compatible with zlib, we also need to
- // accept degenerate single-code codings. See also
- // TestDegenerateHuffmanCoding.
- if code != 1<<uint(max) && (code != 1 || max != 1) {
- return false
- }
-
- h.min = min
- if max > huffmanChunkBits {
- numLinks := 1 << (uint(max) - huffmanChunkBits)
- h.linkMask = uint32(numLinks - 1)
-
- // create link tables
- link := nextcode[huffmanChunkBits+1] >> 1
- h.links = make([][]uint32, huffmanNumChunks-link)
- for j := uint(link); j < huffmanNumChunks; j++ {
- reverse := int(bits.Reverse16(uint16(j)))
- reverse >>= uint(16 - huffmanChunkBits)
- off := j - uint(link)
- if sanity && h.chunks[reverse] != 0 {
- panic("impossible: overwriting existing chunk")
- }
- h.chunks[reverse] = uint32(off<<huffmanValueShift | (huffmanChunkBits + 1))
- h.links[off] = make([]uint32, numLinks)
- }
- }
-
- for i, n := range lengths {
- if n == 0 {
- continue
- }
- code := nextcode[n]
- nextcode[n]++
- chunk := uint32(i<<huffmanValueShift | n)
- reverse := int(bits.Reverse16(uint16(code)))
- reverse >>= uint(16 - n)
- if n <= huffmanChunkBits {
- for off := reverse; off < len(h.chunks); off += 1 << uint(n) {
- // We should never need to overwrite
- // an existing chunk. Also, 0 is
- // never a valid chunk, because the
- // lower 4 "count" bits should be
- // between 1 and 15.
- if sanity && h.chunks[off] != 0 {
- panic("impossible: overwriting existing chunk")
- }
- h.chunks[off] = chunk
- }
- } else {
- j := reverse & (huffmanNumChunks - 1)
- if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 {
- // Longer codes should have been
- // associated with a link table above.
- panic("impossible: not an indirect chunk")
- }
- value := h.chunks[j] >> huffmanValueShift
- linktab := h.links[value]
- reverse >>= huffmanChunkBits
- for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) {
- if sanity && linktab[off] != 0 {
- panic("impossible: overwriting existing chunk")
- }
- linktab[off] = chunk
- }
- }
- }
-
- if sanity {
- // Above we've sanity checked that we never overwrote
- // an existing entry. Here we additionally check that
- // we filled the tables completely.
- for i, chunk := range h.chunks {
- if chunk == 0 {
- // As an exception, in the degenerate
- // single-code case, we allow odd
- // chunks to be missing.
- if code == 1 && i%2 == 1 {
- continue
- }
- panic("impossible: missing chunk")
- }
- }
- for _, linktab := range h.links {
- for _, chunk := range linktab {
- if chunk == 0 {
- panic("impossible: missing chunk")
- }
- }
- }
- }
-
- return true
-}
-
-// RFC 1951 section 3.2.7.
-// Compression with dynamic Huffman codes
-var codeOrder = [...]int{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
-
-var (
- // Initialize the fixedHuffmanDecoder only once upon first use.
- fixedOnce sync.Once
- fixedHuffmanDecoder huffmanDecoder
-)
-
-func fixedHuffmanDecoderInit() {
- fixedOnce.Do(func() {
- // These come from the RFC section 3.2.6.
- var bits [288]int
- for i := 0; i < 144; i++ {
- bits[i] = 8
- }
- for i := 144; i < 256; i++ {
- bits[i] = 9
- }
- for i := 256; i < 280; i++ {
- bits[i] = 7
- }
- for i := 280; i < 288; i++ {
- bits[i] = 8
- }
- fixedHuffmanDecoder.init(bits[:])
- })
-}
diff --git a/internal/flatex/slice_inflate.go b/internal/flatex/slice_inflate.go
deleted file mode 100644
index f9120143..00000000
--- a/internal/flatex/slice_inflate.go
+++ /dev/null
@@ -1,472 +0,0 @@
-package flatex
-
-import (
- "io"
- "math/bits"
- "sync"
-)
-
-// sliceInflater is a specialized DEFLATE decoder that reads directly from an
-// in-memory byte slice. It mirrors the main decompressor but avoids the
-// overhead of the Reader interfaces, enabling faster byte-slice decoding.
-type sliceInflater struct {
- input []byte
- pos int
- roffset int64
-
- b uint32
- nb uint
-
- h1, h2 huffmanDecoder
-
- bits *[maxNumLit + maxNumDist]int
- codebits *[numCodes]int
-
- window windowDecoder
-
- toRead []byte
- step func(*sliceInflater)
- stepState int
- final bool
- err error
- hl, hd *huffmanDecoder
- copyLen int
- copyDist int
-}
-
-var sliceInflaterPool = sync.Pool{
- New: func() any {
- fixedHuffmanDecoderInit()
- return &sliceInflater{
- bits: new([maxNumLit + maxNumDist]int),
- codebits: new([numCodes]int),
- }
- },
-}
-
-func (f *sliceInflater) reset(src []byte) error {
- bits := f.bits
- codebits := f.codebits
- windowState := f.window
- *f = sliceInflater{
- input: src,
- bits: bits,
- codebits: codebits,
- window: windowState,
- step: (*sliceInflater).nextBlock,
- }
- f.window.init(maxMatchOffset)
- return nil
-}
-
-func (f *sliceInflater) nextBlock() {
- for f.nb < 1+2 {
- if err := f.moreBits(); err != nil {
- f.err = err
- return
- }
- }
- f.final = f.b&1 == 1
- f.b >>= 1
- typ := f.b & 3
- f.b >>= 2
- f.nb -= 1 + 2
- switch typ {
- case 0:
- f.dataBlock()
- case 1:
- f.hl = &fixedHuffmanDecoder
- f.hd = nil
- f.huffmanBlock()
- case 2:
- if err := f.readHuffman(); err != nil {
- f.err = err
- return
- }
- f.hl = &f.h1
- f.hd = &f.h2
- f.huffmanBlock()
- default:
- f.err = CorruptInputError(f.roffset)
- }
-}
-
-func (f *sliceInflater) huffmanBlock() {
- const (
- stateInit = iota
- stateDict
- )
- switch f.stepState {
- case stateInit:
- goto readLiteral
- case stateDict:
- goto copyHistory
- }
-
-readLiteral:
- {
- v, err := f.huffSym(f.hl)
- if err != nil {
- f.err = err
- return
- }
- var n uint
- var length int
- switch {
- case v < 256:
- f.window.writeByte(byte(v))
- if f.window.availWrite() == 0 {
- f.toRead = f.window.readFlush()
- f.step = (*sliceInflater).huffmanBlock
- f.stepState = stateInit
- return
- }
- goto readLiteral
- case v == 256:
- f.finishBlock()
- return
- case v < 265:
- length = v - (257 - 3)
- n = 0
- case v < 269:
- length = v*2 - (265*2 - 11)
- n = 1
- case v < 273:
- length = v*4 - (269*4 - 19)
- n = 2
- case v < 277:
- length = v*8 - (273*8 - 35)
- n = 3
- case v < 281:
- length = v*16 - (277*16 - 67)
- n = 4
- case v < 285:
- length = v*32 - (281*32 - 131)
- n = 5
- case v < maxNumLit:
- length = 258
- n = 0
- default:
- f.err = CorruptInputError(f.roffset)
- return
- }
- if n > 0 {
- for f.nb < n {
- if err = f.moreBits(); err != nil {
- f.err = err
- return
- }
- }
- length += int(f.b & uint32(1<<n-1))
- f.b >>= n
- f.nb -= n
- }
-
- var dist int
- if f.hd == nil {
- for f.nb < 5 {
- if err = f.moreBits(); err != nil {
- f.err = err
- return
- }
- }
- dist = int(bits.Reverse8(uint8(f.b & 0x1F << 3)))
- f.b >>= 5
- f.nb -= 5
- } else {
- if dist, err = f.huffSym(f.hd); err != nil {
- f.err = err
- return
- }
- }
-
- switch {
- case dist < 4:
- dist++
- case dist < maxNumDist:
- nb := uint(dist-2) >> 1
- extra := (dist & 1) << nb
- for f.nb < nb {
- if err = f.moreBits(); err != nil {
- f.err = err
- return
- }
- }
- extra |= int(f.b & uint32(1<<nb-1))
- f.b >>= nb
- f.nb -= nb
- dist = 1<<(nb+1) + 1 + extra
- default:
- f.err = CorruptInputError(f.roffset)
- return
- }
-
- if dist > f.window.histSize() {
- f.err = CorruptInputError(f.roffset)
- return
- }
-
- f.copyLen, f.copyDist = length, dist
- goto copyHistory
- }
-
-copyHistory:
- {
- cnt := f.window.tryWriteCopy(f.copyDist, f.copyLen)
- if cnt == 0 {
- cnt = f.window.writeCopy(f.copyDist, f.copyLen)
- }
- f.copyLen -= cnt
-
- if f.window.availWrite() == 0 || f.copyLen > 0 {
- f.toRead = f.window.readFlush()
- f.step = (*sliceInflater).huffmanBlock
- f.stepState = stateDict
- return
- }
- goto readLiteral
- }
-}
-
-func (f *sliceInflater) dataBlock() {
- f.nb = 0
- f.b = 0
-
- if f.pos+4 > len(f.input) {
- f.pos = len(f.input)
- f.err = io.ErrUnexpectedEOF
- return
- }
- hdr := f.input[f.pos : f.pos+4]
- f.pos += 4
- f.roffset += 4
- n := int(hdr[0]) | int(hdr[1])<<8
- nn := int(hdr[2]) | int(hdr[3])<<8
- if uint16(nn) != uint16(^n) {
- f.err = CorruptInputError(f.roffset)
- return
- }
-
- if n == 0 {
- f.toRead = f.window.readFlush()
- f.finishBlock()
- return
- }
-
- f.copyLen = n
- f.copyData()
-}
-
-func (f *sliceInflater) copyData() {
- for {
- if f.copyLen == 0 {
- f.finishBlock()
- return
- }
- buf := f.window.writeSlice()
- if len(buf) == 0 {
- f.toRead = f.window.readFlush()
- f.step = (*sliceInflater).copyData
- return
- }
- n := f.copyLen
- if n > len(buf) {
- n = len(buf)
- }
- if f.pos+n > len(f.input) {
- f.err = io.ErrUnexpectedEOF
- return
- }
- copy(buf[:n], f.input[f.pos:f.pos+n])
- f.pos += n
- f.roffset += int64(n)
- f.copyLen -= n
- f.window.writeMark(n)
- if f.window.availWrite() == 0 {
- f.toRead = f.window.readFlush()
- f.step = (*sliceInflater).copyData
- return
- }
- }
-}
-
-func (f *sliceInflater) finishBlock() {
- if f.final {
- if f.window.availRead() > 0 {
- f.toRead = f.window.readFlush()
- }
- f.err = io.EOF
- }
- f.step = (*sliceInflater).nextBlock
- f.stepState = 0
-}
-
-func (f *sliceInflater) moreBits() error {
- if f.pos >= len(f.input) {
- return io.ErrUnexpectedEOF
- }
- c := f.input[f.pos]
- f.pos++
- f.roffset++
- f.b |= uint32(c) << (f.nb & 31)
- f.nb += 8
- return nil
-}
-
-func (f *sliceInflater) huffSym(h *huffmanDecoder) (int, error) {
- n := uint(h.min)
- nb, b := f.nb, f.b
- for {
- for nb < n {
- if f.pos >= len(f.input) {
- f.b = b
- f.nb = nb
- return 0, io.ErrUnexpectedEOF
- }
- c := f.input[f.pos]
- f.pos++
- f.roffset++
- b |= uint32(c) << (nb & 31)
- nb += 8
- }
- chunk := h.chunks[b&(huffmanNumChunks-1)]
- n = uint(chunk & huffmanCountMask)
- if n > huffmanChunkBits {
- chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask]
- n = uint(chunk & huffmanCountMask)
- }
- if n <= nb {
- if n == 0 {
- f.b = b
- f.nb = nb
- f.err = CorruptInputError(f.roffset)
- return 0, f.err
- }
- f.b = b >> (n & 31)
- f.nb = nb - n
- return int(chunk >> huffmanValueShift), nil
- }
- }
-}
-
-func (f *sliceInflater) readHuffman() error {
- for f.nb < 5+5+4 {
- if err := f.moreBits(); err != nil {
- return err
- }
- }
- nlit := int(f.b&0x1F) + 257
- if nlit > maxNumLit {
- return CorruptInputError(f.roffset)
- }
- f.b >>= 5
- ndist := int(f.b&0x1F) + 1
- if ndist > maxNumDist {
- return CorruptInputError(f.roffset)
- }
- f.b >>= 5
- nclen := int(f.b&0xF) + 4
- f.b >>= 4
- f.nb -= 5 + 5 + 4
- codebits := f.codebits[:]
- bits := f.bits[:]
- clear(codebits)
- clear(bits)
- for i := 0; i < nclen; i++ {
- for f.nb < 3 {
- if err := f.moreBits(); err != nil {
- return err
- }
- }
- codebits[codeOrder[i]] = int(f.b & 0x7)
- f.b >>= 3
- f.nb -= 3
- }
- if !f.h1.init(codebits) {
- return CorruptInputError(f.roffset)
- }
- for i := range bits {
- bits[i] = 0
- }
- i := 0
- for i < nlit+ndist {
- x, err := f.huffSym(&f.h1)
- if err != nil {
- return err
- }
- switch {
- case x < 16:
- bits[i] = x
- i++
- case x == 16:
- if i == 0 {
- return CorruptInputError(f.roffset)
- }
- repeat := 3
- for f.nb < 2 {
- if err := f.moreBits(); err != nil {
- return err
- }
- }
- repeat += int(f.b & 0x3)
- f.b >>= 2
- f.nb -= 2
- for repeat > 0 {
- if i >= len(bits) {
- return CorruptInputError(f.roffset)
- }
- bits[i] = bits[i-1]
- i++
- repeat--
- }
- case x == 17:
- repeat := 3
- for f.nb < 3 {
- if err := f.moreBits(); err != nil {
- return err
- }
- }
- repeat += int(f.b & 0x7)
- f.b >>= 3
- f.nb -= 3
- for repeat > 0 {
- if i >= len(bits) {
- return CorruptInputError(f.roffset)
- }
- bits[i] = 0
- i++
- repeat--
- }
- case x == 18:
- repeat := 11
- for f.nb < 7 {
- if err := f.moreBits(); err != nil {
- return err
- }
- }
- repeat += int(f.b & 0x7F)
- f.b >>= 7
- f.nb -= 7
- for repeat > 0 {
- if i >= len(bits) {
- return CorruptInputError(f.roffset)
- }
- bits[i] = 0
- i++
- repeat--
- }
- default:
- return CorruptInputError(f.roffset)
- }
- }
- if !f.h1.init(bits[:nlit]) {
- return CorruptInputError(f.roffset)
- }
- if !f.h2.init(bits[nlit : nlit+ndist]) {
- return CorruptInputError(f.roffset)
- }
- if f.h1.min < bits[endBlockMarker] {
- f.h1.min = bits[endBlockMarker]
- }
- return nil
-}
diff --git a/internal/flatex/window_decoder.go b/internal/flatex/window_decoder.go
deleted file mode 100644
index 492c6a96..00000000
--- a/internal/flatex/window_decoder.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package flatex
-
-// windowDecoder implements the sliding window used in decompression.
-type windowDecoder struct {
- hist []byte
-
- wrPos int
- rdPos int
- full bool
-}
-
-func (wd *windowDecoder) init(size int) {
- *wd = windowDecoder{hist: wd.hist}
-
- if cap(wd.hist) < size {
- wd.hist = make([]byte, size)
- }
- wd.hist = wd.hist[:size]
-
- wd.wrPos = 0
- wd.rdPos = 0
- wd.full = false
-}
-
-func (wd *windowDecoder) histSize() int {
- if wd.full {
- return len(wd.hist)
- }
- return wd.wrPos
-}
-
-func (wd *windowDecoder) availRead() int {
- return wd.wrPos - wd.rdPos
-}
-
-func (wd *windowDecoder) availWrite() int {
- return len(wd.hist) - wd.wrPos
-}
-
-func (wd *windowDecoder) writeSlice() []byte {
- return wd.hist[wd.wrPos:]
-}
-
-func (wd *windowDecoder) writeMark(cnt int) {
- wd.wrPos += cnt
-}
-
-func (wd *windowDecoder) writeByte(c byte) {
- wd.hist[wd.wrPos] = c
- wd.wrPos++
-}
-
-func (wd *windowDecoder) writeCopy(dist, length int) int {
- dstBase := wd.wrPos
- dstPos := dstBase
- srcPos := dstPos - dist
- endPos := dstPos + length
- if endPos > len(wd.hist) {
- endPos = len(wd.hist)
- }
-
- if srcPos < 0 {
- srcPos += len(wd.hist)
- dstPos += copy(wd.hist[dstPos:endPos], wd.hist[srcPos:])
- srcPos = 0
- }
-
- for dstPos < endPos {
- dstPos += copy(wd.hist[dstPos:endPos], wd.hist[srcPos:dstPos])
- }
-
- wd.wrPos = dstPos
- return dstPos - dstBase
-}
-
-func (wd *windowDecoder) tryWriteCopy(dist, length int) int {
- dstPos := wd.wrPos
- endPos := dstPos + length
- if dstPos < dist || endPos > len(wd.hist) {
- return 0
- }
- dstBase := dstPos
- srcPos := dstPos - dist
-
- for dstPos < endPos {
- dstPos += copy(wd.hist[dstPos:endPos], wd.hist[srcPos:dstPos])
- }
-
- wd.wrPos = dstPos
- return dstPos - dstBase
-}
-
-func (wd *windowDecoder) readFlush() []byte {
- toRead := wd.hist[wd.rdPos:wd.wrPos]
- wd.rdPos = wd.wrPos
- if wd.wrPos == len(wd.hist) {
- wd.wrPos, wd.rdPos = 0, 0
- wd.full = true
- }
- return toRead
-}
diff --git a/internal/zlib/LICENSE b/internal/zlib/LICENSE
deleted file mode 100644
index 2a7cf70d..00000000
--- a/internal/zlib/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2009 The Go Authors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google LLC nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/internal/zlib/reader.go b/internal/zlib/reader.go
deleted file mode 100644
index 2234e7e0..00000000
--- a/internal/zlib/reader.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package zlib implements reading and writing of zlib format compressed data,
-as specified in RFC 1950.
-
-This package differs from the standard library's compress/zlib package
-in that it pools readers and writers to reduce allocations.
-
-Note that closing a reader or writer causes it to be returned to a pool
-for reuse. Therefore, the caller must not retain references to a
-reader or writer after closing it; in the standard library's
-compress/zlib package, it is legal to Reset a closed reader or writer
-and continue using it; that is not allowed here, so there is simply no
-Resetter interface.
-
-The implementation provides filters that uncompress during reading
-and compress during writing. For example, to write compressed data
-to a buffer:
-
- var b bytes.Buffer
- w := zlib.NewWriter(&b)
- w.Write([]byte("hello, world\n"))
- w.Close()
-
-and to read that data back:
-
- r, err := zlib.NewReader(&b)
- io.Copy(os.Stdout, r)
- r.Close()
-*/
-package zlib
-
-import (
- "bufio"
- "compress/flate"
- "encoding/binary"
- "errors"
- "hash"
- "io"
- "sync"
-
- "codeberg.org/lindenii/furgit/internal/adler32"
-)
-
-const (
- zlibDeflate = 8
- zlibMaxWindow = 7
-)
-
-var (
- // ErrChecksum is returned when reading ZLIB data that has an invalid checksum.
- ErrChecksum = errors.New("zlib: invalid checksum")
- // ErrDictionary is returned when reading ZLIB data that has an invalid dictionary.
- ErrDictionary = errors.New("zlib: invalid dictionary")
- // ErrHeader is returned when reading ZLIB data that has an invalid header.
- ErrHeader = errors.New("zlib: invalid header")
-)
-
-var readerPool = sync.Pool{
- New: func() any {
- r := new(reader)
- return r
- },
-}
-
-type reader struct {
- r flate.Reader
- decompressor io.ReadCloser
- digest hash.Hash32
- err error
- scratch [4]byte
-}
-
-// NewReader creates a new ReadCloser.
-// Reads from the returned ReadCloser read and decompress data from r.
-// If r does not implement [io.ByteReader], the decompressor may read more
-// data than necessary from r.
-// It is the caller's responsibility to call Close on the ReadCloser when done.
-func NewReader(r io.Reader) (io.ReadCloser, error) {
- return NewReaderDict(r, nil)
-}
-
-// NewReaderDict is like [NewReader] but uses a preset dictionary.
-// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
-// If the compressed data refers to a different dictionary, NewReaderDict returns [ErrDictionary].
-func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
- v := readerPool.Get()
- z, ok := v.(*reader)
- if !ok {
- panic("zlib: pool returned unexpected type")
- }
- err := z.Reset(r, dict)
- if err != nil {
- return nil, err
- }
- return z, nil
-}
-
-func (z *reader) Read(p []byte) (int, error) {
- if z.err != nil {
- return 0, z.err
- }
-
- var n int
- n, z.err = z.decompressor.Read(p)
- z.digest.Write(p[0:n])
- if z.err != io.EOF {
- // In the normal case we return here.
- return n, z.err
- }
-
- // Finished file; check checksum.
- if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- z.err = err
- return n, z.err
- }
- // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
- checksum := binary.BigEndian.Uint32(z.scratch[:4])
- if checksum != z.digest.Sum32() {
- z.err = ErrChecksum
- return n, z.err
- }
- return n, io.EOF
-}
-
-// Calling Close does not close the wrapped [io.Reader] originally passed to [NewReader].
-// In order for the ZLIB checksum to be verified, the reader must be
-// fully consumed until the [io.EOF].
-func (z *reader) Close() error {
- if z.err != nil && z.err != io.EOF {
- return z.err
- }
- z.err = z.decompressor.Close()
- if z.err != nil {
- return z.err
- }
-
- readerPool.Put(z)
- return nil
-}
-
-func (z *reader) Reset(r io.Reader, dict []byte) error {
- *z = reader{decompressor: z.decompressor}
- if fr, ok := r.(flate.Reader); ok {
- z.r = fr
- } else {
- z.r = bufio.NewReader(r)
- }
-
- // Read the header (RFC 1950 section 2.2.).
- _, z.err = io.ReadFull(z.r, z.scratch[0:2])
- if z.err != nil {
- if z.err == io.EOF {
- z.err = io.ErrUnexpectedEOF
- }
- return z.err
- }
- h := binary.BigEndian.Uint16(z.scratch[:2])
- if (z.scratch[0]&0x0f != zlibDeflate) || (z.scratch[0]>>4 > zlibMaxWindow) || (h%31 != 0) {
- z.err = ErrHeader
- return z.err
- }
- haveDict := z.scratch[1]&0x20 != 0
- if haveDict {
- _, z.err = io.ReadFull(z.r, z.scratch[0:4])
- if z.err != nil {
- if z.err == io.EOF {
- z.err = io.ErrUnexpectedEOF
- }
- return z.err
- }
- checksum := binary.BigEndian.Uint32(z.scratch[:4])
- if checksum != adler32.Checksum(dict) {
- z.err = ErrDictionary
- return z.err
- }
- }
-
- if z.decompressor == nil {
- if haveDict {
- z.decompressor = flate.NewReaderDict(z.r, dict)
- } else {
- z.decompressor = flate.NewReader(z.r)
- }
- } else {
- z.err = z.decompressor.(flate.Resetter).Reset(z.r, dict)
- if z.err != nil {
- return z.err
- }
- }
- z.digest = adler32.New()
- return nil
-}
diff --git a/internal/zlib/writer.go b/internal/zlib/writer.go
deleted file mode 100644
index 81c57f55..00000000
--- a/internal/zlib/writer.go
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package zlib
-
-import (
- "compress/flate"
- "encoding/binary"
- "fmt"
- "hash"
- "io"
- "sync"
-
- "codeberg.org/lindenii/furgit/internal/adler32"
-)
-
-// These constants are copied from the [flate] package, so that code that imports
-// [compress/zlib] does not also have to import [compress/flate].
-const (
- NoCompression = flate.NoCompression
- BestSpeed = flate.BestSpeed
- BestCompression = flate.BestCompression
- DefaultCompression = flate.DefaultCompression
- HuffmanOnly = flate.HuffmanOnly
-)
-
-// A Writer takes data written to it and writes the compressed
-// form of that data to an underlying writer (see [NewWriter]).
-type Writer struct {
- w io.Writer
- level int
- dict []byte
- compressor *flate.Writer
- digest hash.Hash32
- err error
- scratch [4]byte
- wroteHeader bool
-}
-
-var writerPool = sync.Pool{
- New: func() any {
- return new(Writer)
- },
-}
-
-// NewWriter creates a new [Writer].
-// Writes to the returned Writer are compressed and written to w.
-//
-// It is the caller's responsibility to call Close on the Writer when done.
-// Writes may be buffered and not flushed until Close.
-func NewWriter(w io.Writer) *Writer {
- z, _ := NewWriterLevelDict(w, DefaultCompression, nil)
- return z
-}
-
-// NewWriterLevel is like [NewWriter] but specifies the compression level instead
-// of assuming [DefaultCompression].
-//
-// The compression level can be [DefaultCompression], [NoCompression], [HuffmanOnly]
-// or any integer value between [BestSpeed] and [BestCompression] inclusive.
-// The error returned will be nil if the level is valid.
-func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
- return NewWriterLevelDict(w, level, nil)
-}
-
-// NewWriterLevelDict is like [NewWriterLevel] but specifies a dictionary to
-// compress with.
-//
-// The dictionary may be nil. If not, its contents should not be modified until
-// the Writer is closed.
-func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
- if level < HuffmanOnly || level > BestCompression {
- return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
- }
- v := writerPool.Get()
- z, ok := v.(*Writer)
- if !ok {
- panic("zlib: pool returned unexpected type")
- }
-
- // flate.Writer can only be Reset with the same level/dictionary mode.
- // Reuse it only when the configuration is unchanged and dictionary-free.
- reuseCompressor := z.compressor != nil && z.level == level && z.dict == nil && dict == nil
- if !reuseCompressor {
- z.compressor = nil
- }
- if z.digest != nil {
- z.digest.Reset()
- }
-
- *z = Writer{
- w: w,
- level: level,
- dict: dict,
- compressor: z.compressor,
- digest: z.digest,
- }
- if z.compressor != nil {
- z.compressor.Reset(w)
- }
- return z, nil
-}
-
-// Reset clears the state of the [Writer] z such that it is equivalent to its
-// initial state from [NewWriterLevel] or [NewWriterLevelDict], but instead writing
-// to w.
-func (z *Writer) Reset(w io.Writer) {
- z.w = w
- // z.level and z.dict left unchanged.
- if z.compressor != nil {
- z.compressor.Reset(w)
- }
- if z.digest != nil {
- z.digest.Reset()
- }
- z.err = nil
- z.scratch = [4]byte{}
- z.wroteHeader = false
-}
-
-// writeHeader writes the ZLIB header.
-func (z *Writer) writeHeader() (err error) {
- z.wroteHeader = true
- // ZLIB has a two-byte header (as documented in RFC 1950).
- // The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
- // The next four bits is the CM (compression method), which is 8 for deflate.
- z.scratch[0] = 0x78
- // The next two bits is the FLEVEL (compression level). The four values are:
- // 0=fastest, 1=fast, 2=default, 3=best.
- // The next bit, FDICT, is set if a dictionary is given.
- // The final five FCHECK bits form a mod-31 checksum.
- switch z.level {
- case -2, 0, 1:
- z.scratch[1] = 0 << 6
- case 2, 3, 4, 5:
- z.scratch[1] = 1 << 6
- case 6, -1:
- z.scratch[1] = 2 << 6
- case 7, 8, 9:
- z.scratch[1] = 3 << 6
- default:
- panic("unreachable")
- }
- if z.dict != nil {
- z.scratch[1] |= 1 << 5
- }
- z.scratch[1] += uint8(31 - binary.BigEndian.Uint16(z.scratch[:2])%31)
- if _, err = z.w.Write(z.scratch[0:2]); err != nil {
- return err
- }
- if z.dict != nil {
- // The next four bytes are the Adler-32 checksum of the dictionary.
- binary.BigEndian.PutUint32(z.scratch[:], adler32.Checksum(z.dict))
- if _, err = z.w.Write(z.scratch[0:4]); err != nil {
- return err
- }
- }
- if z.compressor == nil {
- // Initialize deflater unless the Writer is being reused
- // after a Reset call.
- z.compressor, err = flate.NewWriterDict(z.w, z.level, z.dict)
- if err != nil {
- return err
- }
- z.digest = adler32.New()
- }
- return nil
-}
-
-// Write writes a compressed form of p to the underlying [io.Writer]. The
-// compressed bytes are not necessarily flushed until the [Writer] is closed or
-// explicitly flushed.
-func (z *Writer) Write(p []byte) (n int, err error) {
- if !z.wroteHeader {
- z.err = z.writeHeader()
- }
- if z.err != nil {
- return 0, z.err
- }
- if len(p) == 0 {
- return 0, nil
- }
- n, err = z.compressor.Write(p)
- if err != nil {
- z.err = err
- return
- }
- z.digest.Write(p)
- return
-}
-
-// Flush flushes the Writer to its underlying [io.Writer].
-func (z *Writer) Flush() error {
- if !z.wroteHeader {
- z.err = z.writeHeader()
- }
- if z.err != nil {
- return z.err
- }
- z.err = z.compressor.Flush()
- return z.err
-}
-
-// Close closes the Writer, flushing any unwritten data to the underlying
-// [io.Writer], but does not close the underlying io.Writer.
-func (z *Writer) Close() error {
- if !z.wroteHeader {
- z.err = z.writeHeader()
- }
- if z.err != nil {
- return z.err
- }
- z.err = z.compressor.Close()
- if z.err != nil {
- return z.err
- }
- checksum := z.digest.Sum32()
- // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
- binary.BigEndian.PutUint32(z.scratch[:], checksum)
- _, z.err = z.w.Write(z.scratch[0:4])
- if z.err != nil {
- return z.err
- }
-
- writerPool.Put(z)
- return nil
-}
diff --git a/internal/zlibx/LICENSE b/internal/zlibx/LICENSE
deleted file mode 100644
index 2a7cf70d..00000000
--- a/internal/zlibx/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2009 The Go Authors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google LLC nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/internal/zlibx/constants.go b/internal/zlibx/constants.go
deleted file mode 100644
index 161e3458..00000000
--- a/internal/zlibx/constants.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package zlibx implements reading of zlib format compressed data,
-as specified in RFC 1950.
-
-This package differs from the standard library's compress/zlib package
-in that it pools readers to reduce allocations. Writing is unsupported.
-
-THis package will likely be refactorered much more for our specific
-use case of only doing full decompressions to byte slices.
-
-Note that closing the reader causes it to be returned to a pool for
-reuse. Therefore, the caller must not retain references to the
-reader after closing it; in the standard library's compress/zlib package,
-it is legal to Reset a closed reader and continue using it; that is
-not allowed here, so there is simply no Resetter interface.
-
-The implementation provides filters that uncompress during reading
-and compress during writing. For example, to write compressed data
-to a buffer:
-
- var b bytes.Buffer
- w := zlib.NewWriter(&b)
- w.Write([]byte("hello, world\n"))
- w.Close()
-
-and to read that data back:
-
- r, err := zlib.NewReader(&b)
- io.Copy(os.Stdout, r)
- r.Close()
-*/
-package zlibx
-
-import (
- "errors"
-)
-
-const (
- zlibDeflate = 8
- zlibMaxWindow = 7
-)
-
-var (
- // ErrChecksum is returned when reading ZLIB data that has an invalid checksum.
- ErrChecksum = errors.New("zlib: invalid checksum")
- // ErrHeader is returned when reading ZLIB data that has an invalid header.
- ErrHeader = errors.New("zlib: invalid header")
-)
diff --git a/internal/zlibx/decompress.go b/internal/zlibx/decompress.go
deleted file mode 100644
index 126c1fcb..00000000
--- a/internal/zlibx/decompress.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package zlibx
-
-import (
- "encoding/binary"
- "io"
-
- "codeberg.org/lindenii/furgit/internal/adler32"
- "codeberg.org/lindenii/furgit/internal/bufpool"
- "codeberg.org/lindenii/furgit/internal/flatex"
-)
-
-func Decompress(src []byte) (bufpool.Buffer, error) {
- out, _, err := DecompressSized(src, 0)
- return out, err
-}
-
-func DecompressSized(src []byte, sizeHint int) (buf bufpool.Buffer, consumed int, err error) {
- if len(src) < 6 {
- return bufpool.Buffer{}, 0, 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{}, 0, ErrHeader
- }
-
- offset := 2
- if flg&0x20 != 0 {
- return bufpool.Buffer{}, 0, ErrHeader
- }
-
- if len(src[offset:]) < 4 {
- return bufpool.Buffer{}, 0, io.ErrUnexpectedEOF
- }
-
- deflateData := src[offset:]
- out, consumed, err := flatex.DecompressSized(deflateData, sizeHint)
- if err != nil {
- return bufpool.Buffer{}, 0, err
- }
-
- checksumPos := offset + consumed
- if checksumPos+4 > len(src) {
- out.Release()
- return bufpool.Buffer{}, 0, io.ErrUnexpectedEOF
- }
- expected := binary.BigEndian.Uint32(src[checksumPos : checksumPos+4])
- if expected != adler32.Checksum(out.Bytes()) {
- out.Release()
- return bufpool.Buffer{}, 0, ErrChecksum
- }
- return out, checksumPos + 4, nil
-}
diff --git a/internal/zlibx/decompress_test.go b/internal/zlibx/decompress_test.go
deleted file mode 100644
index bea348d2..00000000
--- a/internal/zlibx/decompress_test.go
+++ /dev/null
@@ -1,170 +0,0 @@
-package zlibx
-
-import (
- "bytes"
- stdzlib "compress/zlib"
- "crypto/rand"
- "testing"
-)
-
-func compressZlib(t *testing.T, payload []byte) []byte {
- t.Helper()
- var buf bytes.Buffer
- w := stdzlib.NewWriter(&buf)
- if _, err := w.Write(payload); err != nil {
- t.Fatalf("Write: %v", err)
- }
- if err := w.Close(); err != nil {
- t.Fatalf("Close: %v", err)
- }
- return buf.Bytes()
-}
-
-func TestDecompress(t *testing.T) {
- makeRand := func(n int) []byte {
- b := make([]byte, n)
- if _, err := rand.Read(b); err != nil {
- t.Fatalf("rand.Read: %v", err)
- }
- return b
- }
-
- type tc struct {
- name string
- payload []byte
- }
-
- tests := []tc{
- {
- name: "simple-hello",
- payload: []byte("hello, zlib world!"),
- },
- {
- name: "empty",
- payload: []byte{},
- },
- {
- name: "single-byte",
- payload: []byte{0x42},
- },
- {
- name: "all-zero-1k",
- payload: bytes.Repeat([]byte{0}, 1024),
- },
- {
- name: "all-FF-1k",
- payload: bytes.Repeat([]byte{0xFF}, 1024),
- },
- {
- name: "ascii-repeated-pattern",
- payload: bytes.Repeat([]byte("ABC123!"), 500),
- },
- {
- name: "binary-structured",
- payload: []byte{
- 0x00, 0x01, 0x02, 0x03,
- 0x10, 0x20, 0x30, 0x40,
- 0xFF, 0xEE, 0xDD, 0xCC,
- },
- },
- {
- name: "1k-crypto-random",
- payload: makeRand(1024),
- },
- {
- name: "32k-crypto-random",
- payload: makeRand(32 * 1024),
- },
- {
- name: "256k-crypto-random",
- payload: makeRand(256 * 1024),
- },
- {
- name: "highly-compressible-large",
- payload: bytes.Repeat([]byte("AAAAAAAAAAAAAAAAAAAA"), 50_000),
- },
- {
- name: "json",
- payload: []byte(`{"name":"test","values":[1,2,3,4],"deep":{"x":123,"y":"abc"}}`),
- },
- {
- name: "html",
- payload: []byte("<html><body><h1>Title</h1><p>Paragraph</p></body></html>"),
- },
- {
- name: "alternating-binary-pattern",
- payload: func() []byte {
- b := make([]byte, 4096)
- for i := 0; i < len(b); i++ {
- if i%2 == 0 {
- b[i] = 0xAA
- } else {
- b[i] = 0x55
- }
- }
- return b
- }(),
- },
- {
- name: "large-repetitive-words",
- payload: bytes.Repeat([]byte("the quick brown fox jumps over the lazy dog\n"), 4000),
- },
- {
- name: "unicode",
- payload: []byte("我不知道该说点啥就随便打点字吧🤷‍♀️"),
- },
- {
- name: "multi-meg-random-2MB",
- payload: makeRand(2 * 1024 * 1024),
- },
- {
- name: "multi-meg-random-16MB",
- payload: makeRand(16 * 1024 * 1024),
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- compressed := compressZlib(t, tt.payload)
-
- out, err := Decompress(compressed)
- if err != nil {
- t.Fatalf("Decompress: %v", err)
- }
- defer out.Release()
-
- if !bytes.Equal(out.Bytes(), tt.payload) {
- t.Fatalf("payload mismatch: got %d bytes, want %d", len(out.Bytes()), len(tt.payload))
- }
- })
- }
-}
-
-func TestDecompressChecksumError(t *testing.T) {
- payload := []byte("checksum check")
- compressed := compressZlib(t, payload)
- compressed[len(compressed)-1] ^= 0xff
-
- if _, err := Decompress(compressed); err != ErrChecksum {
- t.Fatalf("expected ErrChecksum, got %v", err)
- }
-}
-
-func TestDecompressSizedUsesHint(t *testing.T) {
- payload := []byte("tiny payload")
- compressed := compressZlib(t, payload)
-
- const hint = 1 << 20
- out, _, err := DecompressSized(compressed, hint)
- if err != nil {
- t.Fatalf("DecompressSized: %v", err)
- }
- defer out.Release()
-
- if !bytes.Equal(out.Bytes(), payload) {
- t.Fatalf("unexpected payload %q", out.Bytes())
- }
- if cap(out.Bytes()) < hint {
- t.Fatalf("expected capacity >= %d, got %d", hint, cap(out.Bytes()))
- }
-}