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

Side by Side 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: Cleanup :( Created 5 years, 4 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package frame
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "io"
11 )
12
13 // ErrFrameTooLarge is an error that is returned if a frame that is larger than
14 // the maximum allowed size (not including the frame header) is read.
15 var ErrFrameTooLarge = fmt.Errorf("frame: frame size exceeds maximum")
16
17 // Reader reads individual frames from a frame-formatted input Reader.
18 type Reader interface {
19 // ReadFrame reads the next frame, returning the frame's size and an io. Reader
20 // for that frame's data. The io.Reader is restricted such that it canno t read
21 // past the frame.
22 //
23 // The frame must be fully read before another Reader call can be made.
24 // Failure to do so will cause the Reader to become unsynchronized.
25 ReadFrame() (int64, io.Reader, error)
26
27 // ReadFrame returns the contents of the next frame. If there are no mor e
28 // frames available, ReadFrame will return io.EOF.
29 ReadFrameAll() ([]byte, error)
30 }
31
32 // reader is an implementation of a Reader that uses an underlying
33 // io.Reader and io.ByteReader to read frames.
34 //
35 // The io.Reader and io.ByteReader must read from the same source.
36 type reader struct {
37 io.Reader
38 io.ByteReader
39
40 maxSize int64
41 }
42
43 // NewReader creates a new Reader which reads frame data from the
44 // supplied Reader instance.
45 //
46 // If the Reader instance is also an io.ByteReader, its ReadByte method will
47 // be used directly.
48 func NewReader(r io.Reader, maxSize int64) Reader {
49 br, ok := r.(io.ByteReader)
50 if !ok {
51 br = &simpleByteReader{Reader: r}
52 }
53 return &reader{
54 Reader: r,
55 ByteReader: br,
56 maxSize: maxSize,
57 }
58 }
59
60 func (r *reader) ReadFrame() (int64, io.Reader, error) {
61 // Read the frame size.
62 count, err := binary.ReadUvarint(r)
63 if err != nil {
64 return 0, nil, err
65 }
66
67 if count > uint64(r.maxSize) {
68 return 0, nil, ErrFrameTooLarge
69 }
70
71 lr := &io.LimitedReader{
72 R: r.Reader,
73 N: int64(count),
74 }
75 return int64(count), lr, nil
76 }
77
78 func (r *reader) ReadFrameAll() ([]byte, error) {
79 count, fr, err := r.ReadFrame()
80 if err != nil {
81 return nil, err
82 }
83 if count == 0 {
84 return nil, nil
85 }
86
87 data := make([]byte, count)
88 if _, err := fr.Read(data); err != nil {
89 return nil, err
90 }
91 return data, nil
iannucci 2015/08/04 17:13:50 I think ioutils.ReadAll is what you want
dnj 2015/08/04 17:51:41 No wai! ioutils.ReadAll has no a priori knowledge
92 }
93
94 // simpleByteReader implements the io.ByteReader interface for an io.Reader.
95 type simpleByteReader struct {
96 io.Reader
97
98 buf [1]byte
99 }
100
101 func (r *simpleByteReader) ReadByte() (byte, error) {
102 _, err := r.Read(r.buf[:])
103 return r.buf[0], err
104 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698