Skip to content

Commit

Permalink
NodeID.SetRight (#1667)
Browse files Browse the repository at this point in the history
* SetRight impl

* SetRight test

* Improved API
  • Loading branch information
gdbelvin authored Jun 11, 2019
1 parent 97074a1 commit 5362a0a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
24 changes: 24 additions & 0 deletions storage/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,30 @@ func (n *NodeID) MaskLeft(depth int) *NodeID {
}
}

// SetLowerBits sets the lower bits after depth to val.
// eg. To set the last nibble of 0x0000 to 1, call SetLowerBits(12, 0xFF).
// SetLowerBits does not change the depth value.
func (n *NodeID) SetLowerBits(depth int, val byte) *NodeID {
r := make([]byte, len(n.Path))
// Set the right bytes to val, excluding the overlap byte
depthBytes := bytesForBits(depth)
vals := bytes.Repeat([]byte{val}, len(n.Path)-depthBytes)
copy(r[depthBytes:], vals)

if depth > 0 {
// Copy the first depthBytes-1.
copy(r, n.Path[:depthBytes-1])
// Set the first leftmask bits of the last byte.
left := n.Path[depthBytes-1] & leftmask[depth%8]
right := val &^ leftmask[depth%8]
r[depthBytes-1] = left | right
}
return &NodeID{
Path: r,
PrefixLenBits: n.PrefixLenBits,
}
}

// Neighbor returns a new copy of a node, applying a LeftMask operation and
// with the bit at PrefixLenBits in the copy flipped.
// In terms of a tree traversal, this is the parent node's other child node
Expand Down
53 changes: 53 additions & 0 deletions storage/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,59 @@ import (

var h2b = testonly.MustHexDecode

func TestSetLowerBits(t *testing.T) {
for _, tc := range []struct {
val byte
index []byte
depth int
want []byte
}{
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 0, want: h2b("0000000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 1, want: h2b("8000000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 2, want: h2b("C000000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 3, want: h2b("E000000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 4, want: h2b("F000000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 5, want: h2b("F800000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 6, want: h2b("FC00000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 7, want: h2b("FE00000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 8, want: h2b("FF00000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 9, want: h2b("FF80000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 10, want: h2b("FFC0000000000000000000000000000000000000")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 159, want: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")},
{val: 0x00, index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 160, want: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0x00, index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 1, want: h2b("0000000000000000000000000000000000000000")},
{val: 0x00, index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 17, want: h2b("0001000000000000000000000000000000000000")},
{val: 0x00, index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 159, want: h2b("000102030405060708090A0B0C0D0E0F10111212")},
{val: 0x00, index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 160, want: h2b("000102030405060708090A0B0C0D0E0F10111213")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 0, want: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 1, want: h2b("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 2, want: h2b("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 3, want: h2b("1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 4, want: h2b("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 5, want: h2b("07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 6, want: h2b("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 7, want: h2b("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 8, want: h2b("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 9, want: h2b("007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 10, want: h2b("003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 159, want: h2b("0000000000000000000000000000000000000001")},
{val: 0xFF, index: h2b("0000000000000000000000000000000000000000"), depth: 160, want: h2b("0000000000000000000000000000000000000000")},
{val: 0xFF, index: h2b("000102030405060708090A0B0C0D0E0F10111212"), depth: 1, want: h2b("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("000102030405060708090A0B0C0D0E0F10111212"), depth: 17, want: h2b("00017FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")},
{val: 0xFF, index: h2b("000102030405060708090A0B0C0D0E0F10111212"), depth: 159, want: h2b("000102030405060708090A0B0C0D0E0F10111213")},
{val: 0xFF, index: h2b("000102030405060708090A0B0C0D0E0F10111212"), depth: 160, want: h2b("000102030405060708090A0B0C0D0E0F10111212")},
} {
nID := NewNodeIDFromHash(tc.index)
gotNode := nID.SetLowerBits(tc.depth, tc.val)
if got, want := gotNode.Path, tc.want; !bytes.Equal(got, want) {
t.Errorf("SetLowerBits(%x, %v, 0x%X): %x, want %x", tc.index, tc.depth, tc.val, got, want)
}
if got, want := gotNode.PrefixLenBits, 160; got != want {
t.Errorf("SetLowerBits(%x, %v, 0x%X).PrefixLen: %v, want %v", tc.index, tc.depth, tc.val, got, want)
}
}
}

func TestMaskLeft(t *testing.T) {
for _, tc := range []struct {
index []byte
Expand Down

0 comments on commit 5362a0a

Please sign in to comment.