mirror of
https://github.com/ipfs/kubo.git
synced 2025-08-15 20:01:44 +08:00

1. Use a custom bitfield type instead of bigints. 2. Make iterating over a hamt *significantly* faster. License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
53 lines
1.1 KiB
Go
53 lines
1.1 KiB
Go
package hamt
|
|
|
|
import (
|
|
"fmt"
|
|
"math/bits"
|
|
)
|
|
|
|
// hashBits is a helper that allows the reading of the 'next n bits' as an integer.
|
|
type hashBits struct {
|
|
b []byte
|
|
consumed int
|
|
}
|
|
|
|
func mkmask(n int) byte {
|
|
return (1 << uint(n)) - 1
|
|
}
|
|
|
|
// Next returns the next 'i' bits of the hashBits value as an integer
|
|
func (hb *hashBits) Next(i int) int {
|
|
curbi := hb.consumed / 8
|
|
leftb := 8 - (hb.consumed % 8)
|
|
|
|
curb := hb.b[curbi]
|
|
if i == leftb {
|
|
out := int(mkmask(i) & curb)
|
|
hb.consumed += i
|
|
return out
|
|
} else if i < leftb {
|
|
a := curb & mkmask(leftb) // mask out the high bits we don't want
|
|
b := a & ^mkmask(leftb-i) // mask out the low bits we don't want
|
|
c := b >> uint(leftb-i) // shift whats left down
|
|
hb.consumed += i
|
|
return int(c)
|
|
} else {
|
|
out := int(mkmask(leftb) & curb)
|
|
out <<= uint(i - leftb)
|
|
hb.consumed += leftb
|
|
out += hb.Next(i - leftb)
|
|
return out
|
|
}
|
|
}
|
|
|
|
func logtwo(v int) (int, error) {
|
|
if v <= 0 {
|
|
return 0, fmt.Errorf("hamt size should be a power of two")
|
|
}
|
|
lg2 := bits.TrailingZeros(uint(v))
|
|
if 1<<uint(lg2) != v {
|
|
return 0, fmt.Errorf("hamt size should be a power of two")
|
|
}
|
|
return lg2, nil
|
|
}
|