Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Unified Diff: common/recordio/reader.go

Issue 1834123002: common/recordio: Add zero-copy buffer split. (Closed) Base URL: https://github.com/luci/luci-go@symlink-clean
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | common/recordio/reader_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: common/recordio/reader.go
diff --git a/common/recordio/reader.go b/common/recordio/reader.go
index 97ae03237a5810997c07bef53af43c0151da9ea8..b71d1d266f4ebc72c775b8619977304e15d71dd3 100644
--- a/common/recordio/reader.go
+++ b/common/recordio/reader.go
@@ -5,6 +5,7 @@
package recordio
import (
+ "bytes"
"encoding/binary"
"fmt"
"io"
@@ -102,3 +103,35 @@ func (r *simpleByteReader) ReadByte() (byte, error) {
_, err := r.Read(r.buf[:])
return r.buf[0], err
}
+
+// Split splits the supplied buffer into its component records.
+//
+// This method implements zero-copy segmentation, so the individual records are
+// slices of the original data set.
+func Split(data []byte) (records [][]byte, err error) {
+ br := bytes.NewReader(data)
+
+ for br.Len() > 0 {
+ var size uint64
+ size, err = binary.ReadUvarint(br)
+ if err != nil {
+ return
+ }
+ if size > uint64(br.Len()) {
+ err = ErrFrameTooLarge
+ return
+ }
+
+ // Pull out the record from the original byte stream without copying.
+ // Casting size to an integer is safe at this point, since we have asserted
+ // that it is less than the remaining length in the buffer, which is an int.
+ offset := len(data) - br.Len()
+ records = append(records, data[offset:offset+int(size)])
+
+ if _, err := br.Seek(int64(size), 1); err != nil {
+ // Our measurements should protect us from this being an invalid seek.
+ panic(err)
+ }
+ }
+ return records, nil
+}
« no previous file with comments | « no previous file | common/recordio/reader_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698