github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/keyspan/filter.go (about) 1 // Copyright 2022 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package keyspan 6 7 // FilterFunc defines a transform from the input Span into the output Span. The 8 // function returns true if the Span should be returned by the iterator, and 9 // false if the Span should be skipped. The FilterFunc is permitted to mutate 10 // the output Span, for example, to elice certain keys, or update the Span's 11 // bounds if so desired. The output Span's Keys slice may be reused to reduce 12 // allocations. 13 type FilterFunc func(in *Span, out *Span) (keep bool) 14 15 // filteringIter is a FragmentIterator that uses a FilterFunc to select which 16 // Spans from the input iterator are returned in the output. 17 // 18 // A note on Span lifetimes: as the FilterFunc reuses a Span with a mutable 19 // slice of Keys to reduce allocations, Spans returned by this iterator are only 20 // valid until the next relative or absolute positioning method is called. 21 type filteringIter struct { 22 iter FragmentIterator 23 filterFn FilterFunc 24 25 // span is a mutable Span passed to the filterFn. The filterFn is free to 26 // mutate this Span. The slice of Keys in the Span is reused with every call 27 // to the filterFn. 28 span Span 29 } 30 31 var _ FragmentIterator = (*filteringIter)(nil) 32 33 // Filter returns a new filteringIter that will filter the Spans from the 34 // provided child iterator using the provided FilterFunc. 35 func Filter(iter FragmentIterator, filter FilterFunc) FragmentIterator { 36 return &filteringIter{iter: iter, filterFn: filter} 37 } 38 39 // SeekGE implements FragmentIterator. 40 func (i *filteringIter) SeekGE(key []byte) *Span { 41 return i.filter(i.iter.SeekGE(key), +1) 42 } 43 44 // SeekLT implements FragmentIterator. 45 func (i *filteringIter) SeekLT(key []byte) *Span { 46 return i.filter(i.iter.SeekLT(key), -1) 47 } 48 49 // First implements FragmentIterator. 50 func (i *filteringIter) First() *Span { 51 return i.filter(i.iter.First(), +1) 52 } 53 54 // Last implements FragmentIterator. 55 func (i *filteringIter) Last() *Span { 56 return i.filter(i.iter.Last(), -1) 57 } 58 59 // Next implements FragmentIterator. 60 func (i *filteringIter) Next() *Span { 61 return i.filter(i.iter.Next(), +1) 62 } 63 64 // Prev implements FragmentIterator. 65 func (i *filteringIter) Prev() *Span { 66 return i.filter(i.iter.Prev(), -1) 67 } 68 69 // Error implements FragmentIterator. 70 func (i *filteringIter) Error() error { 71 return i.iter.Error() 72 } 73 74 // Close implements FragmentIterator. 75 func (i *filteringIter) Close() error { 76 return i.iter.Close() 77 } 78 79 // filter uses the filterFn (if configured) to filter and possibly mutate the 80 // given Span. If the current Span is to be skipped, the iterator continues 81 // iterating in the given direction until it lands on a Span that should be 82 // returned, or the iterator becomes invalid. 83 func (i *filteringIter) filter(span *Span, dir int8) *Span { 84 if i.filterFn == nil { 85 return span 86 } 87 for i.Error() == nil && span != nil { 88 if keep := i.filterFn(span, &i.span); keep { 89 return &i.span 90 } 91 if dir == +1 { 92 span = i.iter.Next() 93 } else { 94 span = i.iter.Prev() 95 } 96 } 97 return span 98 }