github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/core/state/snapshot/holdable_iterator.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package snapshot 18 19 import ( 20 "github.com/tirogen/go-ethereum/common" 21 "github.com/tirogen/go-ethereum/ethdb" 22 ) 23 24 // holdableIterator is a wrapper of underlying database iterator. It extends 25 // the basic iterator interface by adding Hold which can hold the element 26 // locally where the iterator is currently located and serve it up next time. 27 type holdableIterator struct { 28 it ethdb.Iterator 29 key []byte 30 val []byte 31 atHeld bool 32 } 33 34 // newHoldableIterator initializes the holdableIterator with the given iterator. 35 func newHoldableIterator(it ethdb.Iterator) *holdableIterator { 36 return &holdableIterator{it: it} 37 } 38 39 // Hold holds the element locally where the iterator is currently located which 40 // can be served up next time. 41 func (it *holdableIterator) Hold() { 42 if it.it.Key() == nil { 43 return // nothing to hold 44 } 45 it.key = common.CopyBytes(it.it.Key()) 46 it.val = common.CopyBytes(it.it.Value()) 47 it.atHeld = false 48 } 49 50 // Next moves the iterator to the next key/value pair. It returns whether the 51 // iterator is exhausted. 52 func (it *holdableIterator) Next() bool { 53 if !it.atHeld && it.key != nil { 54 it.atHeld = true 55 } else if it.atHeld { 56 it.atHeld = false 57 it.key = nil 58 it.val = nil 59 } 60 if it.key != nil { 61 return true // shifted to locally held value 62 } 63 return it.it.Next() 64 } 65 66 // Error returns any accumulated error. Exhausting all the key/value pairs 67 // is not considered to be an error. 68 func (it *holdableIterator) Error() error { return it.it.Error() } 69 70 // Release releases associated resources. Release should always succeed and can 71 // be called multiple times without causing error. 72 func (it *holdableIterator) Release() { 73 it.atHeld = false 74 it.key = nil 75 it.val = nil 76 it.it.Release() 77 } 78 79 // Key returns the key of the current key/value pair, or nil if done. The caller 80 // should not modify the contents of the returned slice, and its contents may 81 // change on the next call to Next. 82 func (it *holdableIterator) Key() []byte { 83 if it.key != nil { 84 return it.key 85 } 86 return it.it.Key() 87 } 88 89 // Value returns the value of the current key/value pair, or nil if done. The 90 // caller should not modify the contents of the returned slice, and its contents 91 // may change on the next call to Next. 92 func (it *holdableIterator) Value() []byte { 93 if it.val != nil { 94 return it.val 95 } 96 return it.it.Value() 97 }