From 3e884f5f3d42cbc4874a04da31dde10314b0cfad Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Thu, 26 Mar 2026 09:17:14 +0000 Subject: format: Move commitgraph and packfile here --- format/commitgraph/bloom/key.go | 117 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 format/commitgraph/bloom/key.go (limited to 'format/commitgraph/bloom/key.go') diff --git a/format/commitgraph/bloom/key.go b/format/commitgraph/bloom/key.go new file mode 100644 index 00000000..a15df904 --- /dev/null +++ b/format/commitgraph/bloom/key.go @@ -0,0 +1,117 @@ +package bloom + +import "codeberg.org/lindenii/furgit/internal/intconv" + +type key struct { + hashes []uint32 +} + +func keyvec(path []byte, filter *Filter) ([]key, error) { + if len(path) == 0 { + return nil, nil + } + + count := 1 + + for _, b := range path { + if b == '/' { + count++ + } + } + + keys := make([]key, 0, count) + + full, err := keyFill(path, filter) + if err != nil { + return nil, err + } + + keys = append(keys, full) + + for i := len(path) - 1; i >= 0; i-- { + if path[i] == '/' { + k, err := keyFill(path[:i], filter) + if err != nil { + return nil, err + } + + keys = append(keys, k) + } + } + + return keys, nil +} + +func keyFill(path []byte, filter *Filter) (key, error) { + const ( + seed0 = 0x293ae76f + seed1 = 0x7e646e2c + ) + + var ( + h0 uint32 + h1 uint32 + err error + ) + + switch filter.HashVersion { + case 2: + h0, err = murmur3SeededV2(seed0, path) + if err != nil { + return key{}, err + } + + h1, err = murmur3SeededV2(seed1, path) + if err != nil { + return key{}, err + } + case 1: + h0, err = murmur3SeededV1(seed0, path) + if err != nil { + return key{}, err + } + + h1, err = murmur3SeededV1(seed1, path) + if err != nil { + return key{}, err + } + default: + return key{}, ErrInvalid + } + + hashCount, err := intconv.Uint32ToInt(filter.NumHashes) + if err != nil { + return key{}, ErrInvalid + } + + hashes := make([]uint32, hashCount) + for i := range hashCount { + iU32, err := intconv.IntToUint32(i) + if err != nil { + return key{}, ErrInvalid + } + + hashes[i] = h0 + iU32*h1 + } + + return key{hashes: hashes}, nil +} + +func filterContainsKey(filter *Filter, key key) bool { + 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 +} -- cgit v1.3.1-10-gc9f91