mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 00:01:40 +01:00 
			
		
		
		
	This updates all source files to use a new standard header for copyright and license declaration. Notably, copyright no longer includes a date, and we now use the standard SPDX-License-Identifier header. This commit was done almost entirely mechanically with perl, and then some minimal manual fixes. Updates #6865 Signed-off-by: Will Norris <will@tailscale.com>
		
			
				
	
	
		
			100 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) Tailscale Inc & AUTHORS
 | |
| // SPDX-License-Identifier: BSD-3-Clause
 | |
| 
 | |
| //go:build race
 | |
| 
 | |
| package deephash
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net/netip"
 | |
| 	"reflect"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| // pointer is a typed pointer that performs safety checks for every operation.
 | |
| type pointer struct {
 | |
| 	unsafePointer
 | |
| 	t reflect.Type // type of pointed-at value; may be nil
 | |
| 	n uintptr      // size of valid memory after p
 | |
| }
 | |
| 
 | |
| // pointerOf returns a pointer from v, which must be a reflect.Pointer.
 | |
| func pointerOf(v reflect.Value) pointer {
 | |
| 	assert(v.Kind() == reflect.Pointer, "got %v, want pointer", v.Kind())
 | |
| 	te := v.Type().Elem()
 | |
| 	return pointer{unsafePointerOf(v), te, te.Size()}
 | |
| }
 | |
| 
 | |
| func (p pointer) pointerElem() pointer {
 | |
| 	assert(p.t.Kind() == reflect.Pointer, "got %v, want pointer", p.t.Kind())
 | |
| 	te := p.t.Elem()
 | |
| 	return pointer{p.unsafePointer.pointerElem(), te, te.Size()}
 | |
| }
 | |
| 
 | |
| func (p pointer) sliceLen() int {
 | |
| 	assert(p.t.Kind() == reflect.Slice, "got %v, want slice", p.t.Kind())
 | |
| 	return p.unsafePointer.sliceLen()
 | |
| }
 | |
| 
 | |
| func (p pointer) sliceArray() pointer {
 | |
| 	assert(p.t.Kind() == reflect.Slice, "got %v, want slice", p.t.Kind())
 | |
| 	n := p.sliceLen()
 | |
| 	assert(n >= 0, "got negative slice length %d", n)
 | |
| 	ta := reflect.ArrayOf(n, p.t.Elem())
 | |
| 	return pointer{p.unsafePointer.sliceArray(), ta, ta.Size()}
 | |
| }
 | |
| 
 | |
| func (p pointer) arrayIndex(index int, size uintptr) pointer {
 | |
| 	assert(p.t.Kind() == reflect.Array, "got %v, want array", p.t.Kind())
 | |
| 	assert(0 <= index && index < p.t.Len(), "got array of size %d, want to access element %d", p.t.Len(), index)
 | |
| 	assert(p.t.Elem().Size() == size, "got element size of %d, want %d", p.t.Elem().Size(), size)
 | |
| 	te := p.t.Elem()
 | |
| 	return pointer{p.unsafePointer.arrayIndex(index, size), te, te.Size()}
 | |
| }
 | |
| 
 | |
| func (p pointer) structField(index int, offset, size uintptr) pointer {
 | |
| 	assert(p.t.Kind() == reflect.Struct, "got %v, want struct", p.t.Kind())
 | |
| 	assert(p.n >= offset, "got size of %d, want excessive start offset of %d", p.n, offset)
 | |
| 	assert(p.n >= offset+size, "got size of %d, want excessive end offset of %d", p.n, offset+size)
 | |
| 	if index < 0 {
 | |
| 		return pointer{p.unsafePointer.structField(index, offset, size), nil, size}
 | |
| 	}
 | |
| 	sf := p.t.Field(index)
 | |
| 	t := sf.Type
 | |
| 	assert(sf.Offset == offset, "got offset of %d, want offset %d", sf.Offset, offset)
 | |
| 	assert(t.Size() == size, "got size of %d, want size %d", t.Size(), size)
 | |
| 	return pointer{p.unsafePointer.structField(index, offset, size), t, t.Size()}
 | |
| }
 | |
| 
 | |
| func (p pointer) asString() *string {
 | |
| 	assert(p.t.Kind() == reflect.String, "got %v, want string", p.t)
 | |
| 	return p.unsafePointer.asString()
 | |
| }
 | |
| 
 | |
| func (p pointer) asTime() *time.Time {
 | |
| 	assert(p.t == timeTimeType, "got %v, want %v", p.t, timeTimeType)
 | |
| 	return p.unsafePointer.asTime()
 | |
| }
 | |
| 
 | |
| func (p pointer) asAddr() *netip.Addr {
 | |
| 	assert(p.t == netipAddrType, "got %v, want %v", p.t, netipAddrType)
 | |
| 	return p.unsafePointer.asAddr()
 | |
| }
 | |
| 
 | |
| func (p pointer) asValue(typ reflect.Type) reflect.Value {
 | |
| 	assert(p.t == typ, "got %v, want %v", p.t, typ)
 | |
| 	return p.unsafePointer.asValue(typ)
 | |
| }
 | |
| 
 | |
| func (p pointer) asMemory(size uintptr) []byte {
 | |
| 	assert(p.n >= size, "got size of %d, want excessive size of %d", p.n, size)
 | |
| 	return p.unsafePointer.asMemory(size)
 | |
| }
 | |
| 
 | |
| func assert(b bool, f string, a ...any) {
 | |
| 	if !b {
 | |
| 		panic(fmt.Sprintf(f, a...))
 | |
| 	}
 | |
| }
 |