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

Unified Diff: common/logdog/frame/writer.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/writer.go
diff --git a/common/logdog/frame/writer.go b/common/logdog/frame/writer.go
new file mode 100644
index 0000000000000000000000000000000000000000..c215b1dabe3a458dd31401ec6297a770dff2d9a2
--- /dev/null
+++ b/common/logdog/frame/writer.go
@@ -0,0 +1,85 @@
+// 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 (
+ "bytes"
+ "encoding/binary"
+ "io"
+)
+
+type frameWriter interface {
+ io.WriteCloser
+
+ // Flush creates a new frame for the buffered written data.
+ Flush() error
+}
iannucci 2015/08/03 22:21:24 interface assertion
dnj 2015/08/03 22:42:58 (see above, NewWriter).
+
+// WriteFrame writes a single frame to an io.Writer.
+func WriteFrame(w io.Writer, frame []byte) (int, error) {
+ var sizeBuf [binary.MaxVarintLen64]byte
iannucci 2015/08/03 22:21:24 why not just `make([]byte, binary.MaxVarintLen64)`
dnj 2015/08/03 22:42:58 I _think_ because this is a stack allocation, and
iannucci 2015/08/04 17:13:50 No it's not... the compiler analyzes all pointers
dnj 2015/08/04 17:51:41 Oh, interesting. I didn't know that. This suggests
+ sizeBytes := binary.PutUvarint(sizeBuf[:], uint64(len(frame)))
+
+ count, err := w.Write(sizeBuf[:sizeBytes])
+ if err != nil {
+ return count, err
+ }
+
+ amount, err := w.Write(frame)
+ count += amount
+ if err != nil {
+ return count, err
+ }
+
+ return count, nil
+}
+
+// Writer implements the io.Writer interface. Data written to the Writer is
+// translated into a series of frames. Each frame is spearated by a call to
+// Flush.
+//
+// Frame boundaries are created by calling Flush or Close. Close does not close
+// the wrapped Writer.
+//
+// Flush will always write a frame, even if the frame's data size is zero.
+// Close, on the other hand, will only write a frame if at least one Write
+// (even for zero bytes) has been called for that frame.
iannucci 2015/08/03 22:21:24 I don't think this is true anymore? Looks like thi
dnj 2015/08/03 22:42:58 Oh sorry, updated.
+//
+// Data written over consecutive Write calls belongs to the same frame. It is
+// buffered until a frame boundary is created.
+type Writer interface {
+ io.Writer
+
+ // Flush writes the buffered frame
+ Flush() error
+}
+
+// writer implements the Writer interface by wrapping an io.Writer.
+type writer struct {
+ inner io.Writer
+ buf bytes.Buffer
+}
+
+// NewWriter creates a new Writer instance that data as frames to an underlying
+// io.Writer.
+func NewWriter(w io.Writer) Writer {
+ return &writer{
+ inner: w,
+ }
+}
+
+func (w *writer) Write(data []byte) (int, error) {
+ return w.buf.Write(data)
+}
+
+func (w *writer) Flush() error {
+ _, err := WriteFrame(w.inner, w.buf.Bytes())
+ if err != nil {
+ return err
+ }
+
+ w.buf.Reset()
+ return nil
+}

Powered by Google App Engine
This is Rietveld 408576698