ref: 1734207266752b9464f42c31f7728a7e3c692c50
dir: /commitgraph/read/bloom.go/
package read
import (
"encoding/binary"
"codeberg.org/lindenii/furgit/commitgraph/bloom"
"codeberg.org/lindenii/furgit/internal/intconv"
)
// HasBloom reports whether any layer has changed-path Bloom data.
func (reader *Reader) HasBloom() bool {
for i := range reader.layers {
layer := &reader.layers[i]
if layer.chunkBloomIndex != nil && layer.chunkBloomData != nil && layer.bloomSettings != nil {
return true
}
}
return false
}
// BloomVersion returns the changed-path Bloom hash version, or 0 if absent.
func (reader *Reader) BloomVersion() uint8 {
for i := len(reader.layers) - 1; i >= 0; i-- {
layer := &reader.layers[i]
if layer.bloomSettings != nil {
version, err := intconv.Uint32ToUint8(layer.bloomSettings.HashVersion)
if err != nil {
return 0
}
return version
}
}
return 0
}
// BloomFilterAt returns one commit's changed-path Bloom filter.
//
// Returns BloomUnavailableError when this commit graph has no Bloom data.
func (reader *Reader) BloomFilterAt(pos Position) (*bloom.Filter, error) {
layer, err := reader.layerByPosition(pos)
if err != nil {
return nil, err
}
if layer.chunkBloomIndex == nil || layer.chunkBloomData == nil || layer.bloomSettings == nil {
return nil, &BloomUnavailableError{Pos: pos}
}
start, end, err := bloomRange(layer, pos.Index)
if err != nil {
return nil, err
}
filter := bloom.NewFilter(
layer.chunkBloomData[bloom.DataHeaderSize+start:bloom.DataHeaderSize+end],
*layer.bloomSettings,
)
return filter, nil
}
func bloomRange(layer *layer, commitIndex uint32) (int, int, error) {
off64 := uint64(commitIndex) * 4
off, err := intconv.Uint64ToInt(off64)
if err != nil {
return 0, 0, err
}
end := binary.BigEndian.Uint32(layer.chunkBloomIndex[off : off+4])
var start uint32
if commitIndex > 0 {
prevOff64 := uint64(commitIndex-1) * 4
prevOff, err := intconv.Uint64ToInt(prevOff64)
if err != nil {
return 0, 0, err
}
start = binary.BigEndian.Uint32(layer.chunkBloomIndex[prevOff : prevOff+4])
}
if end < start {
return 0, 0, &MalformedError{Path: layer.path, Reason: "invalid BIDX range"}
}
bdatLen := len(layer.chunkBloomData) - bloom.DataHeaderSize
bdatLenU32, err := intconv.IntToUint32(bdatLen)
if err != nil {
return 0, 0, err
}
if end > bdatLenU32 {
return 0, 0, &MalformedError{Path: layer.path, Reason: "BIDX range out of BDAT bounds"}
}
startInt, err := intconv.Uint64ToInt(uint64(start))
if err != nil {
return 0, 0, err
}
endInt, err := intconv.Uint64ToInt(uint64(end))
if err != nil {
return 0, 0, err
}
return startInt, endInt, nil
}