github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/reader/binaryReader.go (about)

     1  package reader
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"github.com/Microsoft/azure-vhd-utils/vhdcore/common"
     7  	"io"
     8  )
     9  
    10  // bufferSizeInBytes is the size of the buffer used by BinaryReader
    11  //
    12  const bufferSizeInBytes = 16
    13  
    14  // ReadAtReader interface that composes io.ReaderAt and io.Reader interfaces.
    15  //
    16  type ReadAtReader interface {
    17  	io.ReaderAt
    18  	io.Reader
    19  }
    20  
    21  // BinaryReader is the reader which can be used to read values of primitive types from a reader
    22  // The reader supports reading data stored both in little-endian or big-endian format.
    23  //
    24  type BinaryReader struct {
    25  	buffer []byte
    26  	order  binary.ByteOrder
    27  	from   ReadAtReader
    28  	Size   int64
    29  }
    30  
    31  // NewBinaryReader creates a new instance of BinaryReader, from is the underlying data source
    32  // to read from, order is the byte order used to encode the data in the source, size is the
    33  // length of the data source in bytes.
    34  //
    35  func NewBinaryReader(from ReadAtReader, order binary.ByteOrder, size int64) *BinaryReader {
    36  	return &BinaryReader{
    37  		buffer: make([]byte, bufferSizeInBytes),
    38  		order:  order,
    39  		from:   from,
    40  		Size:   size,
    41  	}
    42  }
    43  
    44  // ReadBytes reads exactly len(buf) bytes from r into buf. It returns the number of bytes
    45  // copied and an error if fewer bytes were read. The error is EOF only if no bytes were
    46  // read. If an EOF happens after reading some but not all the bytes, ReadBytes returns
    47  // ErrUnexpectedEOF. On return, n == len(buf) if and only if err == nil.
    48  //
    49  func (b *BinaryReader) ReadBytes(offset int64, buf []byte) (int, error) {
    50  	return b.from.ReadAt(buf, offset)
    51  }
    52  
    53  // ReadByte reads a byte from underlying source starting at byte offset off and returns it.
    54  //
    55  func (b *BinaryReader) ReadByte(offset int64) (byte, error) {
    56  	if _, err := b.readToBuffer(1, offset); err != nil {
    57  		return 0, err
    58  	}
    59  
    60  	return b.buffer[0], nil
    61  }
    62  
    63  // ReadBoolean reads a byte from underlying source starting at byte offset off and
    64  // returns it as a bool.
    65  //
    66  func (b *BinaryReader) ReadBoolean(offset int64) (bool, error) {
    67  	if _, err := b.readToBuffer(1, offset); err != nil {
    68  		return false, err
    69  	}
    70  	return b.buffer[0] != 0, nil
    71  }
    72  
    73  // ReadUInt16 reads an encoded unsigned 2 byte integer from underlying source starting
    74  // at byte offset off and return it as a uint16.
    75  //
    76  func (b *BinaryReader) ReadUInt16(offset int64) (uint16, error) {
    77  	if _, err := b.readToBuffer(2, offset); err != nil {
    78  		return 0, err
    79  	}
    80  	return b.order.Uint16(b.buffer), nil
    81  }
    82  
    83  // ReadInt16 reads an encoded signed 2 byte integer from underlying source starting
    84  // at byte offset off returns it as a int16.
    85  //
    86  func (b *BinaryReader) ReadInt16(off int64) (int16, error) {
    87  	if _, err := b.readToBuffer(2, off); err != nil {
    88  		return 0, err
    89  	}
    90  	return int16(b.order.Uint16(b.buffer)), nil
    91  }
    92  
    93  // ReadUInt32 reads an encoded unsigned 4 byte integer from underlying source starting
    94  // at byte offset off returns it as a uint32.
    95  //
    96  func (b *BinaryReader) ReadUInt32(off int64) (uint32, error) {
    97  	if _, err := b.readToBuffer(4, off); err != nil {
    98  		return 0, err
    99  	}
   100  	return b.order.Uint32(b.buffer), nil
   101  }
   102  
   103  // ReadInt32 reads an encoded signed 4 byte integer from underlying source starting
   104  // at byte offset off and returns it as a int32.
   105  //
   106  func (b *BinaryReader) ReadInt32(off int64) (int32, error) {
   107  	if _, err := b.readToBuffer(4, off); err != nil {
   108  		return 0, err
   109  	}
   110  	return int32(b.order.Uint32(b.buffer)), nil
   111  }
   112  
   113  // ReadUInt64 reads an encoded unsigned 8 byte integer from underlying source starting
   114  // at byte offset off and returns it as a uint64.
   115  //
   116  func (b *BinaryReader) ReadUInt64(off int64) (uint64, error) {
   117  	if _, err := b.readToBuffer(8, off); err != nil {
   118  		return 0, err
   119  	}
   120  	return b.order.Uint64(b.buffer), nil
   121  }
   122  
   123  // ReadInt64 reads an encoded signed 4 byte integer from underlying source starting
   124  // at byte offset off and and returns it as a int64.
   125  //
   126  func (b *BinaryReader) ReadInt64(off int64) (int64, error) {
   127  	if _, err := b.readToBuffer(8, off); err != nil {
   128  		return 0, err
   129  	}
   130  	return int64(b.order.Uint64(b.buffer)), nil
   131  }
   132  
   133  // ReadUUID reads 16 byte character sequence from underlying source starting
   134  // at byte offset off and returns it as a UUID.
   135  //
   136  func (b *BinaryReader) ReadUUID(off int64) (*common.UUID, error) {
   137  	if _, err := b.readToBuffer(16, off); err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	return common.NewUUID(b.buffer)
   142  }
   143  
   144  // readToBuffer reads numBytes bytes from the source starting at byte offset off.
   145  // This function uses ReadAt to read the bytes. It returns the number of bytes read
   146  // and the error, if any.
   147  // ReadAt always returns a non-nil error when n < len(numBytes). At end of file, that
   148  // error is io.EOF.
   149  //
   150  func (b *BinaryReader) readToBuffer(numBytes int, off int64) (int, error) {
   151  	if numBytes > bufferSizeInBytes {
   152  		return 0, fmt.Errorf("Expected (0-%d) however found: %d", bufferSizeInBytes, numBytes)
   153  	}
   154  
   155  	return b.from.ReadAt(b.buffer[:numBytes], off)
   156  }