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