add.go 937 Bytes
Newer Older
Petar Maymounkov's avatar
Petar Maymounkov committed
1 2 3 4 5
package trie

import (
	"github.com/libp2p/go-libp2p-xor/key"
)
Petar Maymounkov's avatar
Petar Maymounkov committed
6 7 8

// Add adds the key q to trie, returning a new trie.
// Add is immutable/non-destructive: The original trie remains unchanged.
Petar Maymounkov's avatar
Petar Maymounkov committed
9
func Add(trie *XorTrie, q key.Key) *XorTrie {
Petar Maymounkov's avatar
Petar Maymounkov committed
10 11 12
	return add(0, trie, q)
}

Petar Maymounkov's avatar
Petar Maymounkov committed
13
func add(depth int, trie *XorTrie, q key.Key) *XorTrie {
Petar Maymounkov's avatar
Petar Maymounkov committed
14 15 16
	dir := q.BitAt(depth)
	if !trie.isLeaf() {
		s := &XorTrie{}
Petar Maymounkov's avatar
Petar Maymounkov committed
17 18
		s.Branch[dir] = add(depth+1, trie.Branch[dir], q)
		s.Branch[1-dir] = trie.Branch[1-dir]
Petar Maymounkov's avatar
Petar Maymounkov committed
19 20
		return s
	} else {
Petar Maymounkov's avatar
Petar Maymounkov committed
21 22
		if trie.Key == nil {
			return &XorTrie{Key: q}
Petar Maymounkov's avatar
Petar Maymounkov committed
23
		} else {
Petar Maymounkov's avatar
Petar Maymounkov committed
24
			if key.Equal(trie.Key, q) {
Petar Maymounkov's avatar
Petar Maymounkov committed
25 26 27
				return trie
			} else {
				s := &XorTrie{}
Petar Maymounkov's avatar
Petar Maymounkov committed
28 29 30
				if q.BitAt(depth) == trie.Key.BitAt(depth) {
					s.Branch[dir] = add(depth+1, &XorTrie{Key: trie.Key}, q)
					s.Branch[1-dir] = &XorTrie{}
Petar Maymounkov's avatar
Petar Maymounkov committed
31 32
					return s
				} else {
Petar Maymounkov's avatar
Petar Maymounkov committed
33 34
					s.Branch[dir] = add(depth+1, &XorTrie{Key: trie.Key}, q)
					s.Branch[1-dir] = &XorTrie{}
Petar Maymounkov's avatar
Petar Maymounkov committed
35 36 37 38 39 40
				}
				return s
			}
		}
	}
}