diff options
| author | Nick Khyl <nickk@tailscale.com> | 2024-12-05 13:16:48 -0600 |
|---|---|---|
| committer | Nick Khyl <nickk@tailscale.com> | 2024-12-05 13:16:48 -0600 |
| commit | 0267fe83b200f1702a2fa0a395442c02a053fadb (patch) | |
| tree | 63654c55225eeb834de59a5a0bc8d19033c6145b /util/deephash/pointer_race.go | |
| parent | 87546a5edf6b6503a87eeb2d666baba57398a066 (diff) | |
| download | tailscale-1.78.0.tar.xz tailscale-1.78.0.zip | |
VERSION.txt: this is v1.78.0v1.78.0
Signed-off-by: Nick Khyl <nickk@tailscale.com>
Diffstat (limited to 'util/deephash/pointer_race.go')
| -rw-r--r-- | util/deephash/pointer_race.go | 198 |
1 files changed, 99 insertions, 99 deletions
diff --git a/util/deephash/pointer_race.go b/util/deephash/pointer_race.go index c638c7d39..93a358b6d 100644 --- a/util/deephash/pointer_race.go +++ b/util/deephash/pointer_race.go @@ -1,99 +1,99 @@ -// 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...)) - } -} +// 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...))
+ }
+}
|
