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 }