github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/modinstaller/byte_sequence.go (about) 1 package modinstaller 2 3 import ( 4 "sort" 5 ) 6 7 type ChangeOperation int 8 9 const ( 10 Insert ChangeOperation = iota 11 Delete 12 Replace 13 ) 14 15 type Change struct { 16 Content []byte 17 Operation ChangeOperation 18 OffsetStart int 19 OffsetEnd int 20 } 21 22 type ChangeSet []*Change 23 24 func EmptyChangeSet() ChangeSet { return ChangeSet{} } 25 26 // MergeChangeSet creates a ChangeSet by merging the given ChangeSets in order 27 func MergeChangeSet(changeSets ...ChangeSet) ChangeSet { 28 changeSet := ChangeSet{} 29 for _, cs := range changeSets { 30 changeSet = append(changeSet, cs...) 31 } 32 return changeSet 33 } 34 35 // NewChangeSet creates a ChangeSet from the given changes 36 func NewChangeSet(changes ...*Change) ChangeSet { 37 return ChangeSet(changes) 38 } 39 40 func (c ChangeSet) SortByOffset() { 41 // sort the changes into descending order of byte offset 42 // this way, when a change is applied, even if it's replacement 43 // does not have the exact same bytes, we don't lose the offset information 44 // of the changes preceeding it 45 sort.Slice(c, func(i, j int) bool { 46 return c[i].OffsetStart > c[j].OffsetStart 47 }) 48 } 49 50 type OperatorFunc func(*Change, []byte) []byte 51 52 type ByteSequence struct { 53 operators map[ChangeOperation]OperatorFunc 54 _underlying []byte 55 } 56 57 func NewByteSequence(b []byte) *ByteSequence { 58 byteSequence := new(ByteSequence) 59 byteSequence._underlying = make([]byte, len(b)) 60 copy(byteSequence._underlying, b) 61 62 byteSequence.operators = map[ChangeOperation]OperatorFunc{ 63 Insert: insert, 64 Delete: clear, 65 Replace: replace, 66 } 67 68 return byteSequence 69 } 70 71 func (b *ByteSequence) ApplyChanges(changeSet ChangeSet) { 72 changeSet.SortByOffset() 73 for _, change := range changeSet { 74 operation := change.Operation 75 if operator, ok := b.operators[operation]; ok { 76 b._underlying = operator(change, b._underlying) 77 } 78 } 79 } 80 81 // Apply applies the given function on the byte sequence 82 func (bseq *ByteSequence) Apply(apply func([]byte) []byte) { 83 bseq._underlying = apply(bseq._underlying) 84 } 85 86 // Bytes returns the current underlying byte sequence 87 func (bseq *ByteSequence) Bytes() []byte { 88 return bseq._underlying 89 } 90 91 func clear(change *Change, source []byte) []byte { 92 left := source[:change.OffsetStart] 93 right := source[change.OffsetEnd:] 94 return append(left, right...) 95 } 96 97 func insert(change *Change, source []byte) []byte { 98 left := source[:change.OffsetStart] 99 right := source[change.OffsetStart:] 100 // prepend the content before the right part 101 right = append(change.Content, right...) 102 return append(left, right...) 103 } 104 105 func replace(change *Change, source []byte) []byte { 106 return insert(change, clear(change, source)) 107 }