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

Unified Diff: common/logdog/frame/reader.go

Issue 1253353008: logdog: Add frame read/write library. (Closed) Base URL: https://github.com/luci/luci-go@logdog-review-output
Patch Set: Created 5 years, 5 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
Index: common/logdog/frame/reader.go
diff --git a/common/logdog/frame/reader.go b/common/logdog/frame/reader.go
new file mode 100644
index 0000000000000000000000000000000000000000..506d790f930c128c82420c487a9a72103176d04c
--- /dev/null
+++ b/common/logdog/frame/reader.go
@@ -0,0 +1,80 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package frame
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+)
+
+// ErrFrameTooLarge is an error that is returned if a frame that is larger than
+// the maximum allowed size (not including the frame header) is read.
+var ErrFrameTooLarge = fmt.Errorf("frame: frame size exceeds maximum")
+
+// Reader reads individual frames from a frame-formatted input Reader.
+type Reader interface {
+ // ReadFrame returns the contents of the next frame. If there are no more
+ // frames available, Next will return io.EOF.
+ ReadFrame() ([]byte, error)
+}
+
+// reader is an implementation of a Reader that uses an underlying
+// io.Reader and io.ByteReader to read frames.
+//
+// The io.Reader and io.ByteReader must read from the same source.
+type reader struct {
+ io.Reader
+ io.ByteReader
+
+ maxSize int
+}
iannucci 2015/08/03 22:21:24 interface assertion?
dnj 2015/08/03 22:42:58 Going with vadimsh@ style: since NewReader returns
+
+// NewReader creates a new Reader which reads frame data from the
+// supplied Reader instance.
+//
+// If the Reader instance is also an io.ByteReader, its ReadByte method will
+// be used directly.
+func NewReader(r io.Reader, maxSize int) Reader {
+ br, ok := r.(io.ByteReader)
+ if !ok {
+ br = &simpleByteReader{Reader: r}
iannucci 2015/08/03 22:21:24 not sure if this is needed? why not just have this
dnj 2015/08/03 22:42:58 It puts the burden on the caller to implement Byte
+ }
+ return &reader{
+ Reader: r,
+ ByteReader: br,
+ maxSize: maxSize,
+ }
+}
+
+func (r *reader) ReadFrame() ([]byte, error) {
+ // Read the frame size.
+ count, err := binary.ReadUvarint(r)
+ if err != nil {
+ return nil, err
+ }
+
+ if count > uint64(r.maxSize) {
+ return nil, ErrFrameTooLarge
+ }
+
+ data := make([]byte, int(count))
+ if _, err := r.Read(data); err != nil {
+ return nil, err
+ }
+ return data, nil
+}
+
+// simpleByteReader implements the io.ByteReader interface for an io.Reader.
+type simpleByteReader struct {
+ io.Reader
+
+ buf [1]byte
iannucci 2015/08/03 22:21:24 not threadsafe? why have it in the struct at all?
dnj 2015/08/03 22:42:58 No, struct is not threadsafe :) Most readers aren'
iannucci 2015/08/04 17:13:50 Right, but you have to slice it every time, which
+}
+
+func (r *simpleByteReader) ReadByte() (byte, error) {
+ _, err := r.Read(r.buf[:])
+ return r.buf[0], err
+}

Powered by Google App Engine
This is Rietveld 408576698