Skip to content

Commit 0b7c7fa

Browse files
authored
Improve insertion point behaviour (#3092)
Small improvements on creating insertion points. Removes the need to trim the resulting file for newlines. Removes a buffer allocation to build each insertion.
1 parent 6cdc860 commit 0b7c7fa

File tree

2 files changed

+19
-30
lines changed

2 files changed

+19
-30
lines changed

private/bufpkg/bufprotoplugin/bufprotoplugin.go

-3
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ const (
3636
// an unreasonable amount of memory to reserve each time we process an insertion
3737
// point and will save a significant number of allocations.
3838
averageGeneratedFileSize = 15 * 1024
39-
// We don't use insertion points internally, but assume they are smaller than
40-
// entire generated files.
41-
averageInsertionPointSize = 1024
4239
)
4340

4441
// Generator executes the Handler using protoc's plugin execution logic.

private/bufpkg/bufprotoplugin/response_writer.go

+19-27
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"io"
2323
"io/fs"
24+
"strings"
2425
"unicode"
2526
"unicode/utf8"
2627

@@ -110,48 +111,42 @@ func writeInsertionPoint(
110111
// bufio.Scanner.Scan() inline
111112
newline := []byte{'\n'}
112113
var found bool
113-
for targetScanner.Scan() {
114+
for i := 0; targetScanner.Scan(); i++ {
115+
if i > 0 {
116+
// These writes cannot fail, they will panic if they cannot allocate.
117+
_, _ = postInsertionContent.Write(newline)
118+
}
114119
targetLine := targetScanner.Bytes()
115120
if !bytes.Contains(targetLine, match) {
116-
// these writes cannot fail, they will panic if they cannot
117-
// allocate
121+
// These writes cannot fail, they will panic if they cannot allocate.
118122
_, _ = postInsertionContent.Write(targetLine)
119-
_, _ = postInsertionContent.Write(newline)
120123
continue
121124
}
122125
// For each line in then new content, apply the
123126
// same amount of whitespace. This is important
124127
// for specific languages, e.g. Python.
125128
whitespace := leadingWhitespace(targetLine)
126129

127-
// Create another scanner so that we can seamlessly handle
128-
// newlines in a platform-agnostic manner.
129-
insertedContentScanner := bufio.NewScanner(bytes.NewBufferString(insertionPointFile.GetContent()))
130-
insertedContent := scanWithPrefixAndLineEnding(insertedContentScanner, whitespace, newline)
131-
// This write cannot fail, it will panic if it cannot
132-
// allocate
133-
_, _ = postInsertionContent.Write(insertedContent)
130+
// Insert the content from the insertion point file. Handle newlines in
131+
// a platform-agnostic manner.
132+
insertedContentReader := strings.NewReader(insertionPointFile.GetContent())
133+
writeWithPrefixAndLineEnding(postInsertionContent, insertedContentReader, whitespace, newline)
134134

135135
// Code inserted at this point is placed immediately
136136
// above the line containing the insertion point, so
137137
// we include it last.
138138
// These writes cannot fail, they will panic if they cannot
139139
// allocate
140140
_, _ = postInsertionContent.Write(targetLine)
141-
_, _ = postInsertionContent.Write(newline)
142141
found = true
143142
}
144-
145143
if err := targetScanner.Err(); err != nil {
146144
return nil, err
147145
}
148-
149146
if !found {
150147
return nil, fmt.Errorf("could not find insertion point %q in %q", insertionPointFile.GetInsertionPoint(), insertionPointFile.GetName())
151148
}
152-
// trim the trailing newline
153-
postInsertionBytes := postInsertionContent.Bytes()
154-
return bytes.TrimSuffix(postInsertionBytes, newline), nil
149+
return postInsertionContent.Bytes(), nil
155150
}
156151

157152
// leadingWhitespace iterates through the given string,
@@ -179,19 +174,16 @@ func leadingWhitespace(buf []byte) []byte {
179174
return buf
180175
}
181176

182-
// scanWithPrefixAndLineEnding iterates over each of the given scanner's lines
177+
// writeWithPrefixAndLineEnding iterates over each of the given reader's lines
183178
// prepends prefix, and appends the newline sequence.
184-
func scanWithPrefixAndLineEnding(scanner *bufio.Scanner, prefix []byte, newline []byte) []byte {
185-
result := bytes.NewBuffer(nil)
186-
result.Grow(averageInsertionPointSize)
179+
func writeWithPrefixAndLineEnding(dst *bytes.Buffer, src io.Reader, prefix, newline []byte) {
180+
scanner := bufio.NewScanner(src)
187181
for scanner.Scan() {
188-
// These writes cannot fail, they will panic if they cannot
189-
// allocate
190-
_, _ = result.Write(prefix)
191-
_, _ = result.Write(scanner.Bytes())
192-
_, _ = result.Write(newline)
182+
// These writes cannot fail, they will panic if they cannot allocate.
183+
_, _ = dst.Write(prefix)
184+
_, _ = dst.Write(scanner.Bytes())
185+
_, _ = dst.Write(newline)
193186
}
194-
return result.Bytes()
195187
}
196188

197189
type writeResponseOptions struct {

0 commit comments

Comments
 (0)