github.com/bir3/gocompiler@v0.9.2202/src/internal/coverage/slicereader/slicereader.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package slicereader 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "io" 11 "unsafe" 12 ) 13 14 // This file contains the helper "SliceReader", a utility for 15 // reading values from a byte slice that may or may not be backed 16 // by a read-only mmap'd region. 17 18 type Reader struct { 19 b []byte 20 readonly bool 21 off int64 22 } 23 24 func NewReader(b []byte, readonly bool) *Reader { 25 r := Reader{ 26 b: b, 27 readonly: readonly, 28 } 29 return &r 30 } 31 32 func (r *Reader) Read(b []byte) (int, error) { 33 amt := len(b) 34 toread := r.b[r.off:] 35 if len(toread) < amt { 36 amt = len(toread) 37 } 38 copy(b, toread) 39 r.off += int64(amt) 40 return amt, nil 41 } 42 43 func (r *Reader) Seek(offset int64, whence int) (ret int64, err error) { 44 switch whence { 45 case io.SeekStart: 46 if offset < 0 || offset > int64(len(r.b)) { 47 return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", offset, len(r.b)) 48 } 49 r.off = offset 50 return offset, nil 51 case io.SeekCurrent: 52 newoff := r.off + offset 53 if newoff < 0 || newoff > int64(len(r.b)) { 54 return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", newoff, len(r.b)) 55 } 56 r.off = newoff 57 return r.off, nil 58 case io.SeekEnd: 59 newoff := int64(len(r.b)) + offset 60 if newoff < 0 || newoff > int64(len(r.b)) { 61 return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", newoff, len(r.b)) 62 } 63 r.off = newoff 64 return r.off, nil 65 } 66 // other modes are not supported 67 return 0, fmt.Errorf("unsupported seek mode %d", whence) 68 } 69 70 func (r *Reader) Offset() int64 { 71 return r.off 72 } 73 74 func (r *Reader) ReadUint8() uint8 { 75 rv := uint8(r.b[int(r.off)]) 76 r.off += 1 77 return rv 78 } 79 80 func (r *Reader) ReadUint32() uint32 { 81 end := int(r.off) + 4 82 rv := binary.LittleEndian.Uint32(r.b[int(r.off):end:end]) 83 r.off += 4 84 return rv 85 } 86 87 func (r *Reader) ReadUint64() uint64 { 88 end := int(r.off) + 8 89 rv := binary.LittleEndian.Uint64(r.b[int(r.off):end:end]) 90 r.off += 8 91 return rv 92 } 93 94 func (r *Reader) ReadULEB128() (value uint64) { 95 var shift uint 96 97 for { 98 b := r.b[r.off] 99 r.off++ 100 value |= (uint64(b&0x7F) << shift) 101 if b&0x80 == 0 { 102 break 103 } 104 shift += 7 105 } 106 return 107 } 108 109 func (r *Reader) ReadString(len int64) string { 110 b := r.b[r.off : r.off+len] 111 r.off += len 112 if r.readonly { 113 return toString(b) // backed by RO memory, ok to make unsafe string 114 } 115 return string(b) 116 } 117 118 func toString(b []byte) string { 119 if len(b) == 0 { 120 return "" 121 } 122 return unsafe.String(&b[0], len(b)) 123 }