github.com/m3db/m3@v1.5.0/src/dbnode/persist/fs/msgpack/stream.go (about) 1 // Copyright (c) 2017 Uber Technologies, Inc 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE 20 21 package msgpack 22 23 import ( 24 "bytes" 25 "fmt" 26 "io" 27 ) 28 29 // DecoderStream is a data stream that is read by the decoder, 30 // it takes both a reader and the underlying backing bytes. 31 // This is constructed this way since the decoder needs access 32 // to the backing bytes when taking refs directly for decoding byte 33 // slices without allocating bytes itself but also needs to progress 34 // the reader (for instance when a reader is a ReaderWithDigest that 35 // is calculating a digest as its being read). 36 type DecoderStream interface { 37 io.Reader 38 39 // ReadByte reads the next byte. 40 ReadByte() (byte, error) 41 42 // UnreadByte unreads the last read byte or returns error if none read 43 // yet. Only a single byte can be unread at a time, a consecutive call 44 // to UnreadByte will result in an error. 45 UnreadByte() error 46 } 47 48 // ByteDecoderStream is an additional interface that some decoder streams 49 // can implement if they are backed by a byte slice. 50 type ByteDecoderStream interface { 51 DecoderStream 52 ByteStream 53 } 54 55 // ByteStream is the interface that contains the additional methods which 56 // can be implemented by streams that are backed by byte slices. 57 type ByteStream interface { 58 // Bytes returns the ref to the bytes provided when Reset(...) is 59 // called. To get the current position into the byte slice use: 60 // len(s.Bytes()) - s.Remaining() 61 Bytes() []byte 62 63 // Remaining returns the remaining bytes in the stream. 64 Remaining() int64 65 66 // Reset resets the decoder stream for decoding a new byte slice. 67 Reset(b []byte) 68 69 // Skip progresses the reader by a certain amount of bytes, useful 70 // when taking a ref to some of the bytes and progressing the reader 71 // itself. 72 Skip(length int64) error 73 74 // Offset returns the current offset in the byte stream. 75 Offset() int 76 } 77 78 type byteDecoderStream struct { 79 reader *bytes.Reader 80 bytes []byte 81 // Store so we don't have to keep calling len() 82 bytesLen int 83 lastReadByte int 84 unreadByte int 85 } 86 87 // NewByteDecoderStream creates a new decoder stream from a bytes ref. 88 func NewByteDecoderStream(b []byte) ByteDecoderStream { 89 return &byteDecoderStream{ 90 reader: bytes.NewReader(b), 91 bytes: b, 92 lastReadByte: -1, 93 unreadByte: -1, 94 bytesLen: len(b), 95 } 96 } 97 98 func (s *byteDecoderStream) Reset(b []byte) { 99 s.reader.Reset(b) 100 s.bytes = b 101 s.lastReadByte = -1 102 s.unreadByte = -1 103 s.bytesLen = len(b) 104 } 105 106 func (s *byteDecoderStream) Read(p []byte) (int, error) { 107 if len(p) == 0 { 108 return 0, nil 109 } 110 111 ref := p 112 113 var numUnreadByte int 114 if s.unreadByte >= 0 { 115 p[0] = byte(s.unreadByte) 116 p = p[1:] 117 s.unreadByte = -1 118 numUnreadByte = 1 119 } 120 n, err := s.reader.Read(p) 121 n += numUnreadByte 122 if n > 0 { 123 s.lastReadByte = int(ref[n-1]) 124 } 125 if err == io.EOF && n > 0 { 126 return n, nil // return EOF next time, might be returning last byte still 127 } 128 return n, err 129 } 130 131 func (s *byteDecoderStream) ReadByte() (byte, error) { 132 if s.unreadByte >= 0 { 133 r := byte(s.unreadByte) 134 s.unreadByte = -1 135 return r, nil 136 } 137 b, err := s.reader.ReadByte() 138 if err == nil { 139 s.lastReadByte = int(b) 140 } 141 return b, err 142 } 143 144 func (s *byteDecoderStream) UnreadByte() error { 145 if s.lastReadByte < 0 { 146 return fmt.Errorf("no previous read byte or already unread byte") 147 } 148 s.unreadByte = s.lastReadByte 149 s.lastReadByte = -1 150 return nil 151 } 152 153 func (s *byteDecoderStream) Bytes() []byte { 154 return s.bytes 155 } 156 157 func (s *byteDecoderStream) Skip(length int64) error { 158 defer func() { 159 if length > 0 { 160 s.unreadByte = -1 161 s.lastReadByte = -1 162 } 163 }() 164 _, err := s.reader.Seek(length, io.SeekCurrent) 165 return err 166 } 167 168 func (s *byteDecoderStream) Remaining() int64 { 169 var unreadBytes int64 170 if s.unreadByte != -1 { 171 unreadBytes = 1 172 } 173 return int64(s.reader.Len()) + unreadBytes 174 } 175 176 func (s *byteDecoderStream) Offset() int { 177 return s.bytesLen - int(s.Remaining()) 178 }