66 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			66 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package danger
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"unsafe"
 | 
						|
)
 | 
						|
 | 
						|
const maxInt = uintptr(int(^uint(0) >> 1))
 | 
						|
 | 
						|
func SubsliceOffset(data []byte, subslice []byte) int {
 | 
						|
	datap := (*reflect.SliceHeader)(unsafe.Pointer(&data))
 | 
						|
	hlp := (*reflect.SliceHeader)(unsafe.Pointer(&subslice))
 | 
						|
 | 
						|
	if hlp.Data < datap.Data {
 | 
						|
		panic(fmt.Errorf("subslice address (%d) is before data address (%d)", hlp.Data, datap.Data))
 | 
						|
	}
 | 
						|
	offset := hlp.Data - datap.Data
 | 
						|
 | 
						|
	if offset > maxInt {
 | 
						|
		panic(fmt.Errorf("slice offset larger than int (%d)", offset))
 | 
						|
	}
 | 
						|
 | 
						|
	intoffset := int(offset)
 | 
						|
 | 
						|
	if intoffset > datap.Len {
 | 
						|
		panic(fmt.Errorf("slice offset (%d) is farther than data length (%d)", intoffset, datap.Len))
 | 
						|
	}
 | 
						|
 | 
						|
	if intoffset+hlp.Len > datap.Len {
 | 
						|
		panic(fmt.Errorf("slice ends (%d+%d) is farther than data length (%d)", intoffset, hlp.Len, datap.Len))
 | 
						|
	}
 | 
						|
 | 
						|
	return intoffset
 | 
						|
}
 | 
						|
 | 
						|
func BytesRange(start []byte, end []byte) []byte {
 | 
						|
	if start == nil || end == nil {
 | 
						|
		panic("cannot call BytesRange with nil")
 | 
						|
	}
 | 
						|
	startp := (*reflect.SliceHeader)(unsafe.Pointer(&start))
 | 
						|
	endp := (*reflect.SliceHeader)(unsafe.Pointer(&end))
 | 
						|
 | 
						|
	if startp.Data > endp.Data {
 | 
						|
		panic(fmt.Errorf("start pointer address (%d) is after end pointer address (%d)", startp.Data, endp.Data))
 | 
						|
	}
 | 
						|
 | 
						|
	l := startp.Len
 | 
						|
	endLen := int(endp.Data-startp.Data) + endp.Len
 | 
						|
	if endLen > l {
 | 
						|
		l = endLen
 | 
						|
	}
 | 
						|
 | 
						|
	if l > startp.Cap {
 | 
						|
		panic(fmt.Errorf("range length is larger than capacity"))
 | 
						|
	}
 | 
						|
 | 
						|
	return start[:l]
 | 
						|
}
 | 
						|
 | 
						|
func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer {
 | 
						|
	// TODO: replace with unsafe.Add when Go 1.17 is released
 | 
						|
	//   https://github.com/golang/go/issues/40481
 | 
						|
	return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset))
 | 
						|
}
 |