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  }