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  }