expose symm diff iterator state in companion object

This commit is contained in:
Roy Crihfield 2023-08-27 01:15:58 +08:00
parent 2f540104d1
commit 66f7637086

View File

@ -8,23 +8,8 @@ import (
) )
type symmDiffIterator struct { type symmDiffIterator struct {
a, b iterState // Nodes returned are those in b - a and a - b (keys only) a, b iterState // Nodes returned are those in b - a and a - b (keys only)
yieldFromA bool // Whether next node comes from a SymmDiffAux
count int // Number of nodes scanned on either trie
eqPathIndex int // Count index of last pair of equal paths, to detect an updated key
}
// NewSymmetricDifferenceIterator constructs a trie.NodeIterator that iterates over the symmetric difference
// of elements in a and b, i.e., the elements in a that are not in b, and vice versa.
// Returns the iterator, and a pointer to an integer recording the number of nodes seen.
func NewSymmetricDifferenceIterator(a, b trie.NodeIterator) (*symmDiffIterator, *int) {
it := &symmDiffIterator{
a: iterState{a, true},
b: iterState{b, true},
// common paths are detected by a distance <=1 from this index, so put it out of reach
eqPathIndex: -2,
}
return it, &it.count
} }
// pairs an iterator with a cache of its valid status // pairs an iterator with a cache of its valid status
@ -33,11 +18,49 @@ type iterState struct {
valid bool valid bool
} }
// SymmDiffAux exposes state specific to symmetric difference iteration, which is not accessible
// from the NodeIterator interface. This includes the number of nodes seen, whether the current key
// is common to both A and B, and whether the current node is sourced from A or B.
type SymmDiffAux struct {
yieldFromA bool // Whether next node comes from a
count int // Number of nodes scanned on either trie
eqPathIndex int // Count index of last pair of equal paths, to detect an updated key
}
// NewSymmetricDifferenceIterator constructs a trie.NodeIterator that iterates over the symmetric difference
// of elements in a and b, i.e., the elements in a that are not in b, and vice versa.
// Returns the iterator, and a pointer to an auxiliary object for accessing the state not exposed by the NodeIterator interface recording the number of nodes seen.
func NewSymmetricDifferenceIterator(a, b trie.NodeIterator) (trie.NodeIterator, *SymmDiffAux) {
it := &symmDiffIterator{
a: iterState{a, true},
b: iterState{b, true},
// common paths are detected by a distance <=1 between count and this index, so we start at -2
SymmDiffAux: SymmDiffAux{eqPathIndex: -2},
}
return it, &it.SymmDiffAux
}
func (st *iterState) Next(descend bool) bool { func (st *iterState) Next(descend bool) bool {
st.valid = st.NodeIterator.Next(descend) st.valid = st.NodeIterator.Next(descend)
return st.valid return st.valid
} }
// FromA returns true if the current node is sourced from A.
func (it *SymmDiffAux) FromA() bool {
return it.yieldFromA
}
// CommonPath returns true if a node with the current path exists in each sub-iterator - i.e. it
// represents an updated node.
func (it *SymmDiffAux) CommonPath() bool {
return it.count-it.eqPathIndex <= 1
}
// Count returns the number of nodes seen.
func (it *SymmDiffAux) Count() int {
return it.count
}
func (it *symmDiffIterator) curr() *iterState { func (it *symmDiffIterator) curr() *iterState {
if it.yieldFromA { if it.yieldFromA {
return &it.a return &it.a
@ -45,17 +68,6 @@ func (it *symmDiffIterator) curr() *iterState {
return &it.b return &it.b
} }
// FromA returns true if the current node is sourced from A.
func (it *symmDiffIterator) FromA() bool {
return it.yieldFromA
}
// CommonPath returns true if a node with the current path exists in each sub-iterator - i.e. it
// represents an updated node.
func (it *symmDiffIterator) CommonPath() bool {
return it.count-it.eqPathIndex <= 1
}
func (it *symmDiffIterator) Hash() common.Hash { func (it *symmDiffIterator) Hash() common.Hash {
return it.curr().Hash() return it.curr().Hash()
} }