src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

builder.go (14983B)


      1 // Copyright 2021 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package trie
      6 
      7 // Collision functions combine a left and right hand side (lhs and rhs) values
      8 // the two values are associated with the same key and produces the value that
      9 // will be stored for the key.
     10 //
     11 // Collision functions must be idempotent:
     12 //
     13 //	collision(x, x) == x for all x.
     14 //
     15 // Collisions functions may be applied whenever a value is inserted
     16 // or two maps are merged, or intersected.
     17 type Collision func(lhs any, rhs any) any
     18 
     19 // TakeLhs always returns the left value in a collision.
     20 func TakeLhs(lhs, rhs any) any { return lhs }
     21 
     22 // TakeRhs always returns the right hand side in a collision.
     23 func TakeRhs(lhs, rhs any) any { return rhs }
     24 
     25 // Builder creates new Map. Each Builder has a unique Scope.
     26 //
     27 // IMPORTANT:  Nodes are hash-consed internally to reduce memory consumption. To
     28 // support hash-consing Builders keep an internal Map of all of the Maps that they
     29 // have created. To GC any of the Maps created by the Builder, all references to
     30 // the Builder must be dropped. This includes MutMaps.
     31 type Builder struct {
     32 	scope Scope
     33 
     34 	// hash-consing maps for each node type.
     35 	empty    *empty
     36 	leaves   map[leaf]*leaf
     37 	branches map[branch]*branch
     38 	// It may be possible to support more types of patricia tries
     39 	// (e.g. non-hash-consed) by making Builder an interface and abstracting
     40 	// the mkLeaf and mkBranch functions.
     41 }
     42 
     43 // NewBuilder creates a new Builder with a unique Scope.
     44 func NewBuilder() *Builder {
     45 	s := newScope()
     46 	return &Builder{
     47 		scope:    s,
     48 		empty:    &empty{s},
     49 		leaves:   make(map[leaf]*leaf),
     50 		branches: make(map[branch]*branch),
     51 	}
     52 }
     53 
     54 func (b *Builder) Scope() Scope { return b.scope }
     55 
     56 // Rescope changes the builder's scope to a new unique Scope.
     57 //
     58 // Any Maps created using the previous scope need to be Cloned
     59 // before any operation.
     60 //
     61 // This makes the old internals of the Builder eligible to be GC'ed.
     62 func (b *Builder) Rescope() {
     63 	s := newScope()
     64 	b.scope = s
     65 	b.empty = &empty{s}
     66 	b.leaves = make(map[leaf]*leaf)
     67 	b.branches = make(map[branch]*branch)
     68 }
     69 
     70 // Empty is the empty map.
     71 func (b *Builder) Empty() Map { return Map{b.Scope(), b.empty} }
     72 
     73 // InsertWith inserts a new association from k to v into the Map m to create a new map
     74 // in the current scope and handle collisions using the collision function c.
     75 //
     76 // This is roughly corresponds to updating a map[uint64]interface{} by:
     77 //
     78 //	if _, ok := m[k]; ok { m[k] = c(m[k], v} else { m[k] = v}
     79 //
     80 // An insertion or update happened whenever Insert(m, ...) != m .
     81 func (b *Builder) InsertWith(c Collision, m Map, k uint64, v any) Map {
     82 	m = b.Clone(m)
     83 	return Map{b.Scope(), b.insert(c, m.n, b.mkLeaf(key(k), v), false)}
     84 }
     85 
     86 // Inserts a new association from key to value into the Map m to create
     87 // a new map in the current scope.
     88 //
     89 // If there was a previous value mapped by key, keep the previously mapped value.
     90 // This is roughly corresponds to updating a map[uint64]interface{} by:
     91 //
     92 //	if _, ok := m[k]; ok { m[k] = val }
     93 //
     94 // This is equivalent to b.Merge(m, b.Create({k: v})).
     95 func (b *Builder) Insert(m Map, k uint64, v any) Map {
     96 	return b.InsertWith(TakeLhs, m, k, v)
     97 }
     98 
     99 // Updates a (key, value) in the map. This is roughly corresponds to
    100 // updating a map[uint64]interface{} by:
    101 //
    102 //	m[key] = val
    103 func (b *Builder) Update(m Map, key uint64, val any) Map {
    104 	return b.InsertWith(TakeRhs, m, key, val)
    105 }
    106 
    107 // Merge two maps lhs and rhs to create a new map in the current scope.
    108 //
    109 // Whenever there is a key in both maps (a collision), the resulting value mapped by
    110 // the key will be `c(lhs[key], rhs[key])`.
    111 func (b *Builder) MergeWith(c Collision, lhs, rhs Map) Map {
    112 	lhs, rhs = b.Clone(lhs), b.Clone(rhs)
    113 	return Map{b.Scope(), b.merge(c, lhs.n, rhs.n)}
    114 }
    115 
    116 // Merge two maps lhs and rhs to create a new map in the current scope.
    117 //
    118 // Whenever there is a key in both maps (a collision), the resulting value mapped by
    119 // the key will be the value in lhs `b.Collision(lhs[key], rhs[key])`.
    120 func (b *Builder) Merge(lhs, rhs Map) Map {
    121 	return b.MergeWith(TakeLhs, lhs, rhs)
    122 }
    123 
    124 // Clone returns a Map that contains the same (key, value) elements
    125 // within b.Scope(), i.e. return m if m.Scope() == b.Scope() or return
    126 // a deep copy of m within b.Scope() otherwise.
    127 func (b *Builder) Clone(m Map) Map {
    128 	if m.Scope() == b.Scope() {
    129 		return m
    130 	} else if m.n == nil {
    131 		return Map{b.Scope(), b.empty}
    132 	}
    133 	return Map{b.Scope(), b.clone(m.n)}
    134 }
    135 func (b *Builder) clone(n node) node {
    136 	switch n := n.(type) {
    137 	case *empty:
    138 		return b.empty
    139 	case *leaf:
    140 		return b.mkLeaf(n.k, n.v)
    141 	case *branch:
    142 		return b.mkBranch(n.prefix, n.branching, b.clone(n.left), b.clone(n.right))
    143 	default:
    144 		panic("unreachable")
    145 	}
    146 }
    147 
    148 // Remove a key from a Map m and return the resulting Map.
    149 func (b *Builder) Remove(m Map, k uint64) Map {
    150 	m = b.Clone(m)
    151 	return Map{b.Scope(), b.remove(m.n, key(k))}
    152 }
    153 
    154 // Intersect Maps lhs and rhs and returns a map with all of the keys in
    155 // both lhs and rhs and the value comes from lhs, i.e.
    156 //
    157 //	{(k, lhs[k]) | k in lhs, k in rhs}.
    158 func (b *Builder) Intersect(lhs, rhs Map) Map {
    159 	return b.IntersectWith(TakeLhs, lhs, rhs)
    160 }
    161 
    162 // IntersectWith take lhs and rhs and returns the intersection
    163 // with the value coming from the collision function, i.e.
    164 //
    165 //	{(k, c(lhs[k], rhs[k]) ) | k in lhs, k in rhs}.
    166 //
    167 // The elements of the resulting map are always { <k, c(lhs[k], rhs[k]) > }
    168 // for each key k that a key in both lhs and rhs.
    169 func (b *Builder) IntersectWith(c Collision, lhs, rhs Map) Map {
    170 	l, r := b.Clone(lhs), b.Clone(rhs)
    171 	return Map{b.Scope(), b.intersect(c, l.n, r.n)}
    172 }
    173 
    174 // MutMap is a convenient wrapper for a Map and a *Builder that will be used to create
    175 // new Maps from it.
    176 type MutMap struct {
    177 	B *Builder
    178 	M Map
    179 }
    180 
    181 // MutEmpty is an empty MutMap for a builder.
    182 func (b *Builder) MutEmpty() MutMap {
    183 	return MutMap{b, b.Empty()}
    184 }
    185 
    186 // Insert an element into the map using the collision function for the builder.
    187 // Returns true if the element was inserted.
    188 func (mm *MutMap) Insert(k uint64, v any) bool {
    189 	old := mm.M
    190 	mm.M = mm.B.Insert(old, k, v)
    191 	return old != mm.M
    192 }
    193 
    194 // Updates an element in the map. Returns true if the map was updated.
    195 func (mm *MutMap) Update(k uint64, v any) bool {
    196 	old := mm.M
    197 	mm.M = mm.B.Update(old, k, v)
    198 	return old != mm.M
    199 }
    200 
    201 // Removes a key from the map. Returns true if the element was removed.
    202 func (mm *MutMap) Remove(k uint64) bool {
    203 	old := mm.M
    204 	mm.M = mm.B.Remove(old, k)
    205 	return old != mm.M
    206 }
    207 
    208 // Merge another map into the current one using the collision function
    209 // for the builder. Returns true if the map changed.
    210 func (mm *MutMap) Merge(other Map) bool {
    211 	old := mm.M
    212 	mm.M = mm.B.Merge(old, other)
    213 	return old != mm.M
    214 }
    215 
    216 // Intersect another map into the current one using the collision function
    217 // for the builder. Returns true if the map changed.
    218 func (mm *MutMap) Intersect(other Map) bool {
    219 	old := mm.M
    220 	mm.M = mm.B.Intersect(old, other)
    221 	return old != mm.M
    222 }
    223 
    224 func (b *Builder) Create(m map[uint64]any) Map {
    225 	var leaves []*leaf
    226 	for k, v := range m {
    227 		leaves = append(leaves, b.mkLeaf(key(k), v))
    228 	}
    229 	return Map{b.Scope(), b.create(leaves)}
    230 }
    231 
    232 // Merge another map into the current one using the collision function
    233 // for the builder. Returns true if the map changed.
    234 func (mm *MutMap) MergeWith(c Collision, other Map) bool {
    235 	old := mm.M
    236 	mm.M = mm.B.MergeWith(c, old, other)
    237 	return old != mm.M
    238 }
    239 
    240 // creates a map for a collection of leaf nodes.
    241 func (b *Builder) create(leaves []*leaf) node {
    242 	n := len(leaves)
    243 	if n == 0 {
    244 		return b.empty
    245 	} else if n == 1 {
    246 		return leaves[0]
    247 	}
    248 	// Note: we can do a more sophisticated algorithm by:
    249 	// - sorting the leaves ahead of time,
    250 	// - taking the prefix and branching bit of the min and max key,
    251 	// - binary searching for the branching bit,
    252 	// - splitting exactly where the branch will be, and
    253 	// - making the branch node for this prefix + branching bit.
    254 	// Skipping until this is a performance bottleneck.
    255 
    256 	m := n / 2 // (n >= 2) ==> 1 <= m < n
    257 	l, r := leaves[:m], leaves[m:]
    258 	return b.merge(nil, b.create(l), b.create(r))
    259 }
    260 
    261 // mkLeaf returns the hash-consed representative of (k, v) in the current scope.
    262 func (b *Builder) mkLeaf(k key, v any) *leaf {
    263 	rep, ok := b.leaves[leaf{k, v}]
    264 	if !ok {
    265 		rep = &leaf{k, v} // heap-allocated copy
    266 		b.leaves[leaf{k, v}] = rep
    267 	}
    268 	return rep
    269 }
    270 
    271 // mkBranch returns the hash-consed representative of the tuple
    272 //
    273 //	(prefix, branch, left, right)
    274 //
    275 // in the current scope.
    276 func (b *Builder) mkBranch(p prefix, bp bitpos, left node, right node) *branch {
    277 	br := branch{
    278 		sz:        left.size() + right.size(),
    279 		prefix:    p,
    280 		branching: bp,
    281 		left:      left,
    282 		right:     right,
    283 	}
    284 	rep, ok := b.branches[br]
    285 	if !ok {
    286 		rep = new(branch) // heap-allocated copy
    287 		*rep = br
    288 		b.branches[br] = rep
    289 	}
    290 	return rep
    291 }
    292 
    293 // join two maps with prefixes p0 and p1 that are *known* to disagree.
    294 func (b *Builder) join(p0 prefix, t0 node, p1 prefix, t1 node) *branch {
    295 	m := branchingBit(p0, p1)
    296 	var left, right node
    297 	if zeroBit(p0, m) {
    298 		left, right = t0, t1
    299 	} else {
    300 		left, right = t1, t0
    301 	}
    302 	prefix := mask(p0, m)
    303 	return b.mkBranch(prefix, m, left, right)
    304 }
    305 
    306 // collide two leaves with the same key to create a leaf
    307 // with the collided value.
    308 func (b *Builder) collide(c Collision, left, right *leaf) *leaf {
    309 	if left == right {
    310 		return left // c is idempotent: c(x, x) == x
    311 	}
    312 	val := left.v // keep the left value by default if c is nil
    313 	if c != nil {
    314 		val = c(left.v, right.v)
    315 	}
    316 	switch val {
    317 	case left.v:
    318 		return left
    319 	case right.v:
    320 		return right
    321 	default:
    322 		return b.mkLeaf(left.k, val)
    323 	}
    324 }
    325 
    326 // inserts a leaf l into a map m and returns the resulting map.
    327 // When lhs is true, l is the left hand side in a collision.
    328 // Both l and m are in the current scope.
    329 func (b *Builder) insert(c Collision, m node, l *leaf, lhs bool) node {
    330 	switch m := m.(type) {
    331 	case *empty:
    332 		return l
    333 	case *leaf:
    334 		if m.k == l.k {
    335 			left, right := l, m
    336 			if !lhs {
    337 				left, right = right, left
    338 			}
    339 			return b.collide(c, left, right)
    340 		}
    341 		return b.join(prefix(l.k), l, prefix(m.k), m)
    342 	case *branch:
    343 		// fallthrough
    344 	}
    345 	// m is a branch
    346 	br := m.(*branch)
    347 	if !matchPrefix(prefix(l.k), br.prefix, br.branching) {
    348 		return b.join(prefix(l.k), l, br.prefix, br)
    349 	}
    350 	var left, right node
    351 	if zeroBit(prefix(l.k), br.branching) {
    352 		left, right = b.insert(c, br.left, l, lhs), br.right
    353 	} else {
    354 		left, right = br.left, b.insert(c, br.right, l, lhs)
    355 	}
    356 	if left == br.left && right == br.right {
    357 		return m
    358 	}
    359 	return b.mkBranch(br.prefix, br.branching, left, right)
    360 }
    361 
    362 // merge two maps in the current scope.
    363 func (b *Builder) merge(c Collision, lhs, rhs node) node {
    364 	if lhs == rhs {
    365 		return lhs
    366 	}
    367 	switch lhs := lhs.(type) {
    368 	case *empty:
    369 		return rhs
    370 	case *leaf:
    371 		return b.insert(c, rhs, lhs, true)
    372 	case *branch:
    373 		switch rhs := rhs.(type) {
    374 		case *empty:
    375 			return lhs
    376 		case *leaf:
    377 			return b.insert(c, lhs, rhs, false)
    378 		case *branch:
    379 			// fallthrough
    380 		}
    381 	}
    382 
    383 	// Last remaining case is branch merging.
    384 	// For brevity, we adopt the Okasaki and Gill naming conventions
    385 	// for branching and prefixes.
    386 	s, t := lhs.(*branch), rhs.(*branch)
    387 	p, m := s.prefix, s.branching
    388 	q, n := t.prefix, t.branching
    389 
    390 	if m == n && p == q { // prefixes are identical.
    391 		left, right := b.merge(c, s.left, t.left), b.merge(c, s.right, t.right)
    392 		return b.mkBranch(p, m, left, right)
    393 	}
    394 	if !prefixesOverlap(p, m, q, n) {
    395 		return b.join(p, s, q, t) // prefixes are disjoint.
    396 	}
    397 	// prefixesOverlap(p, m, q, n) && !(m ==n && p == q)
    398 	// By prefixesOverlap(...), either:
    399 	//   higher(m, n) && matchPrefix(q, p, m), or
    400 	//   higher(n, m) && matchPrefix(p, q, n)
    401 	// So either s or t may can be merged with one branch or the other.
    402 	switch {
    403 	case ord(m, n) && zeroBit(q, m):
    404 		return b.mkBranch(p, m, b.merge(c, s.left, t), s.right)
    405 	case ord(m, n) && !zeroBit(q, m):
    406 		return b.mkBranch(p, m, s.left, b.merge(c, s.right, t))
    407 	case ord(n, m) && zeroBit(p, n):
    408 		return b.mkBranch(q, n, b.merge(c, s, t.left), t.right)
    409 	default:
    410 		return b.mkBranch(q, n, t.left, b.merge(c, s, t.right))
    411 	}
    412 }
    413 
    414 func (b *Builder) remove(m node, k key) node {
    415 	switch m := m.(type) {
    416 	case *empty:
    417 		return m
    418 	case *leaf:
    419 		if m.k == k {
    420 			return b.empty
    421 		}
    422 		return m
    423 	case *branch:
    424 		// fallthrough
    425 	}
    426 	br := m.(*branch)
    427 	kp := prefix(k)
    428 	if !matchPrefix(kp, br.prefix, br.branching) {
    429 		// The prefix does not match. kp is not in br.
    430 		return br
    431 	}
    432 	// the prefix matches. try to remove from the left or right branch.
    433 	left, right := br.left, br.right
    434 	if zeroBit(kp, br.branching) {
    435 		left = b.remove(left, k) // k may be in the left branch.
    436 	} else {
    437 		right = b.remove(right, k) // k may be in the right branch.
    438 	}
    439 	if left == br.left && right == br.right {
    440 		return br // no update
    441 	} else if _, ok := left.(*empty); ok {
    442 		return right // left updated and is empty.
    443 	} else if _, ok := right.(*empty); ok {
    444 		return left // right updated and is empty.
    445 	}
    446 	// Either left or right updated. Both left and right are not empty.
    447 	// The left and right branches still share the same prefix and disagree
    448 	// on the same branching bit. It is safe to directly create the branch.
    449 	return b.mkBranch(br.prefix, br.branching, left, right)
    450 }
    451 
    452 func (b *Builder) intersect(c Collision, l, r node) node {
    453 	if l == r {
    454 		return l
    455 	}
    456 	switch l := l.(type) {
    457 	case *empty:
    458 		return b.empty
    459 	case *leaf:
    460 		if rleaf := r.find(l.k); rleaf != nil {
    461 			return b.collide(c, l, rleaf)
    462 		}
    463 		return b.empty
    464 	case *branch:
    465 		switch r := r.(type) {
    466 		case *empty:
    467 			return b.empty
    468 		case *leaf:
    469 			if lleaf := l.find(r.k); lleaf != nil {
    470 				return b.collide(c, lleaf, r)
    471 			}
    472 			return b.empty
    473 		case *branch:
    474 			// fallthrough
    475 		}
    476 	}
    477 	// Last remaining case is branch intersection.
    478 	s, t := l.(*branch), r.(*branch)
    479 	p, m := s.prefix, s.branching
    480 	q, n := t.prefix, t.branching
    481 
    482 	if m == n && p == q {
    483 		// prefixes are identical.
    484 		left, right := b.intersect(c, s.left, t.left), b.intersect(c, s.right, t.right)
    485 		if _, ok := left.(*empty); ok {
    486 			return right
    487 		} else if _, ok := right.(*empty); ok {
    488 			return left
    489 		}
    490 		// The left and right branches are both non-empty.
    491 		// They still share the same prefix and disagree on the same branching bit.
    492 		// It is safe to directly create the branch.
    493 		return b.mkBranch(p, m, left, right)
    494 	}
    495 
    496 	if !prefixesOverlap(p, m, q, n) {
    497 		return b.empty // The prefixes share no keys.
    498 	}
    499 	// prefixesOverlap(p, m, q, n) && !(m ==n && p == q)
    500 	// By prefixesOverlap(...), either:
    501 	//   ord(m, n) && matchPrefix(q, p, m), or
    502 	//   ord(n, m) && matchPrefix(p, q, n)
    503 	// So either s or t may be a strict subtree of the other.
    504 	var lhs, rhs node
    505 	switch {
    506 	case ord(m, n) && zeroBit(q, m):
    507 		lhs, rhs = s.left, t
    508 	case ord(m, n) && !zeroBit(q, m):
    509 		lhs, rhs = s.right, t
    510 	case ord(n, m) && zeroBit(p, n):
    511 		lhs, rhs = s, t.left
    512 	default:
    513 		lhs, rhs = s, t.right
    514 	}
    515 	return b.intersect(c, lhs, rhs)
    516 }