From eff21aa6d0ee7fb404a6ddaf159cfc1976df4ea3 Mon Sep 17 00:00:00 2001 From: Paul Banks Date: Wed, 16 Jun 2021 12:52:49 +0100 Subject: [PATCH] Note the huge prefix/null byte gotcha in README Fixes #37 Also fixes #36 --- README.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index aca15a6..0164197 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ in a more efficient manner than performing each operation one at a time. For a mutable variant, see [go-radix](https://github.com/armon/go-radix). +## :warning: This tree implementation is low-level and can be easily used incorrectly + - **No key may be a prefix of any other.** + - This is _not_ enforced but _will cause undefined behavior_ if violated. + - The typical way to work around this is to append a null byte (`0x0`) to each key unless you know in advance your keys will never be prefixes. We don't always do this in tests if we arranged them to not be prefixes anyway! + - We could avoid this gotcha by automatically adding null bytes to all keys but that has high cost of causing re-allocation of keys for every operation that the caller might not want if they already. + Documentation ============= @@ -28,9 +34,9 @@ Below is a simple example of usage ```go // Create a tree r := iradix.New() -r, _, _ = r.Insert([]byte("foo"), 1) -r, _, _ = r.Insert([]byte("bar"), 2) -r, _, _ = r.Insert([]byte("foobar"), 2) +r, _, _ = r.Insert([]byte("foo\x00"), 1) +r, _, _ = r.Insert([]byte("bar\x00"), 2) +r, _, _ = r.Insert([]byte("foobar\x00"), 2) // Find the longest prefix match m, _, _ := r.Root().LongestPrefix([]byte("foozip")) @@ -44,17 +50,17 @@ Here is an example of performing a range scan of the keys. ```go // Create a tree r := iradix.New() -r, _, _ = r.Insert([]byte("001"), 1) -r, _, _ = r.Insert([]byte("002"), 2) -r, _, _ = r.Insert([]byte("005"), 5) -r, _, _ = r.Insert([]byte("010"), 10) -r, _, _ = r.Insert([]byte("100"), 10) +r, _, _ = r.Insert([]byte("001\x00"), 1) +r, _, _ = r.Insert([]byte("002\x00"), 2) +r, _, _ = r.Insert([]byte("005\x00"), 5) +r, _, _ = r.Insert([]byte("010\x00"), 10) +r, _, _ = r.Insert([]byte("100\x00"), 10) // Range scan over the keys that sort lexicographically between [003, 050) it := r.Root().Iterator() it.SeekLowerBound([]byte("003")) for key, _, ok := it.Next(); ok; key, _, ok = it.Next() { - if key >= "050" { + if key >= "005" { break } fmt.Println(key)