diff --git a/kad/key/test/util_test.go b/kad/key/test/util_test.go new file mode 100644 index 0000000..fe50b23 --- /dev/null +++ b/kad/key/test/util_test.go @@ -0,0 +1,22 @@ +package test + +import ( + "strings" + "testing" + + "github.com/probe-lab/go-libdht/kad/key" + "github.com/probe-lab/go-libdht/kad/key/bit256" + "github.com/probe-lab/go-libdht/kad/key/bitstr" + "github.com/stretchr/testify/require" +) + +func TestGenericCommonPrefixLength(t *testing.T) { + k0 := bit256.NewKey(make([]byte, 32)) // 0000...0000 + k1 := bitstr.Key(strings.Repeat("0", 256)) // 0000...0000 + k2 := bitstr.Key("01" + strings.Repeat("0", 254)) // 0100...0000 + k3 := bitstr.Key("000") // 0001 + + require.Equal(t, 256, key.CommonPrefixLength(k0, k1)) // keys are identical + require.Equal(t, 1, key.CommonPrefixLength(k0, k2)) // only first bit is common + require.Equal(t, 3, key.CommonPrefixLength(k0, k3)) // no common bits +} diff --git a/kad/key/util.go b/kad/key/util.go index 6f78cb0..5c6354a 100644 --- a/kad/key/util.go +++ b/kad/key/util.go @@ -18,6 +18,22 @@ func Equal[K kad.Key[K]](a, b K) bool { return a.Compare(b) == 0 } +// CommonPrefixLength returns the length of the common prefix of two keys. +// Note that keys can be of different types, and different lengths. +func CommonPrefixLength[K0 kad.Key[K0], K1 kad.Key[K1]](a K0, b K1) int { + minLen := a.BitLen() + if b.BitLen() < minLen { + minLen = b.BitLen() + } + + for i := 0; i < minLen; i++ { + if a.Bit(i) != b.Bit(i) { + return i + } + } + return minLen +} + // BitString returns a string containing the binary representation of a key. func BitString[K kad.Key[K]](k K) string { if bs, ok := any(k).(interface{ BitString() string }); ok {