github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/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 "internal/unsafeheader" 10 "unsafe" 11 ) 12 13 // This file contains the helper "SliceReader", a utility for 14 // reading values from a byte slice that may or may not be backed 15 // by a read-only mmap'd region. 16 17 type Reader struct { 18 b []byte 19 readonly bool 20 off int64 21 } 22 23 func NewReader(b []byte, readonly bool) *Reader { 24 r := Reader{ 25 b: b, 26 readonly: readonly, 27 } 28 return &r 29 } 30 31 func (r *Reader) Read(b []byte) (int, error) { 32 amt := len(b) 33 toread := r.b[r.off:] 34 if len(toread) < amt { 35 amt = len(toread) 36 } 37 copy(b, toread) 38 r.off += int64(amt) 39 return amt, nil 40 } 41 42 func (r *Reader) SeekTo(off int64) { 43 r.off = off 44 } 45 46 func (r *Reader) Offset() int64 { 47 return r.off 48 } 49 50 func (r *Reader) ReadUint8() uint8 { 51 rv := uint8(r.b[int(r.off)]) 52 r.off += 1 53 return rv 54 } 55 56 func (r *Reader) ReadUint32() uint32 { 57 end := int(r.off) + 4 58 rv := binary.LittleEndian.Uint32(r.b[int(r.off):end:end]) 59 r.off += 4 60 return rv 61 } 62 63 func (r *Reader) ReadUint64() uint64 { 64 end := int(r.off) + 8 65 rv := binary.LittleEndian.Uint64(r.b[int(r.off):end:end]) 66 r.off += 8 67 return rv 68 } 69 70 func (r *Reader) ReadULEB128() (value uint64) { 71 var shift uint 72 73 for { 74 b := r.b[r.off] 75 r.off++ 76 value |= (uint64(b&0x7F) << shift) 77 if b&0x80 == 0 { 78 break 79 } 80 shift += 7 81 } 82 return 83 } 84 85 func (r *Reader) ReadString(len int64) string { 86 b := r.b[r.off : r.off+len] 87 r.off += len 88 if r.readonly { 89 return toString(b) // backed by RO memory, ok to make unsafe string 90 } 91 return string(b) 92 } 93 94 func toString(b []byte) string { 95 if len(b) == 0 { 96 return "" 97 } 98 99 var s string 100 hdr := (*unsafeheader.String)(unsafe.Pointer(&s)) 101 hdr.Data = unsafe.Pointer(&b[0]) 102 hdr.Len = len(b) 103 104 return s 105 }