Source File
pointer_unsafe.go
Belonging Package
google.golang.org/protobuf/internal/impl
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !purego && !appengine
// +build !purego,!appengine
package impl
import (
)
const UnsafeEnabled = true
// Pointer is an opaque pointer type.
type Pointer unsafe.Pointer
// offset represents the offset to a struct field, accessible from a pointer.
// The offset is the byte offset to the field from the start of the struct.
type offset uintptr
// offsetOf returns a field offset for the struct field.
func ( reflect.StructField, exporter) offset {
return offset(.Offset)
}
// IsValid reports whether the offset is valid.
func ( offset) () bool { return != invalidOffset }
// invalidOffset is an invalid field offset.
var invalidOffset = ^offset(0)
// zeroOffset is a noop when calling pointer.Apply.
var zeroOffset = offset(0)
// pointer is a pointer to a message struct or field.
type pointer struct{ p unsafe.Pointer }
// pointerOf returns p as a pointer.
func ( Pointer) pointer {
return pointer{p: unsafe.Pointer()}
}
// pointerOfValue returns v as a pointer.
func ( reflect.Value) pointer {
return pointer{p: unsafe.Pointer(.Pointer())}
}
// pointerOfIface returns the pointer portion of an interface.
func ( interface{}) pointer {
type struct {
unsafe.Pointer
unsafe.Pointer
}
return pointer{p: (*)(unsafe.Pointer(&)).}
}
// IsNil reports whether the pointer is nil.
func ( pointer) () bool {
return .p == nil
}
// Apply adds an offset to the pointer to derive a new pointer
// to a specified field. The pointer must be valid and pointing at a struct.
func ( pointer) ( offset) pointer {
if .IsNil() {
panic("invalid nil pointer")
}
return pointer{p: unsafe.Pointer(uintptr(.p) + uintptr())}
}
// AsValueOf treats p as a pointer to an object of type t and returns the value.
// It is equivalent to reflect.ValueOf(p.AsIfaceOf(t))
func ( pointer) ( reflect.Type) reflect.Value {
return reflect.NewAt(, .p)
}
// AsIfaceOf treats p as a pointer to an object of type t and returns the value.
// It is equivalent to p.AsValueOf(t).Interface()
func ( pointer) ( reflect.Type) interface{} {
// TODO: Use tricky unsafe magic to directly create ifaceHeader.
return .AsValueOf().Interface()
}
func ( pointer) () *bool { return (*bool)(.p) }
func ( pointer) () **bool { return (**bool)(.p) }
func ( pointer) () *[]bool { return (*[]bool)(.p) }
func ( pointer) () *int32 { return (*int32)(.p) }
func ( pointer) () **int32 { return (**int32)(.p) }
func ( pointer) () *[]int32 { return (*[]int32)(.p) }
func ( pointer) () *int64 { return (*int64)(.p) }
func ( pointer) () **int64 { return (**int64)(.p) }
func ( pointer) () *[]int64 { return (*[]int64)(.p) }
func ( pointer) () *uint32 { return (*uint32)(.p) }
func ( pointer) () **uint32 { return (**uint32)(.p) }
func ( pointer) () *[]uint32 { return (*[]uint32)(.p) }
func ( pointer) () *uint64 { return (*uint64)(.p) }
func ( pointer) () **uint64 { return (**uint64)(.p) }
func ( pointer) () *[]uint64 { return (*[]uint64)(.p) }
func ( pointer) () *float32 { return (*float32)(.p) }
func ( pointer) () **float32 { return (**float32)(.p) }
func ( pointer) () *[]float32 { return (*[]float32)(.p) }
func ( pointer) () *float64 { return (*float64)(.p) }
func ( pointer) () **float64 { return (**float64)(.p) }
func ( pointer) () *[]float64 { return (*[]float64)(.p) }
func ( pointer) () *string { return (*string)(.p) }
func ( pointer) () **string { return (**string)(.p) }
func ( pointer) () *[]string { return (*[]string)(.p) }
func ( pointer) () *[]byte { return (*[]byte)(.p) }
func ( pointer) () **[]byte { return (**[]byte)(.p) }
func ( pointer) () *[][]byte { return (*[][]byte)(.p) }
func ( pointer) () *weakFields { return (*weakFields)(.p) }
func ( pointer) () *map[int32]ExtensionField { return (*map[int32]ExtensionField)(.p) }
func ( pointer) () pointer {
return pointer{p: *(*unsafe.Pointer)(.p)}
}
// PointerSlice loads []*T from p as a []pointer.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func ( pointer) () []pointer {
// Super-tricky - p should point to a []*T where T is a
// message type. We load it as []pointer.
return *(*[]pointer)(.p)
}
// AppendPointerSlice appends v to p, which must be a []*T.
func ( pointer) ( pointer) {
*(*[]pointer)(.p) = append(*(*[]pointer)(.p), )
}
// SetPointer sets *p to v.
func ( pointer) ( pointer) {
*(*unsafe.Pointer)(.p) = (unsafe.Pointer)(.p)
}
// Static check that MessageState does not exceed the size of a pointer.
const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{}))
func (Export) ( Pointer) *messageState {
// Super-tricky - see documentation on MessageState.
return (*messageState)(unsafe.Pointer())
}
func ( *messageState) () pointer {
// Super-tricky - see documentation on MessageState.
return pointer{p: unsafe.Pointer()}
}
func ( *messageState) () *MessageInfo {
:= .LoadMessageInfo()
if == nil {
panic("invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct")
}
return
}
func ( *messageState) () *MessageInfo {
return (*MessageInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&.atomicMessageInfo))))
}
func ( *messageState) ( *MessageInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&.atomicMessageInfo)), unsafe.Pointer())
}
type atomicNilMessage struct{ p unsafe.Pointer } // p is a *messageReflectWrapper
func ( *atomicNilMessage) ( *MessageInfo) *messageReflectWrapper {
if := atomic.LoadPointer(&.p); != nil {
return (*messageReflectWrapper)()
}
:= &messageReflectWrapper{mi: }
atomic.CompareAndSwapPointer(&.p, nil, (unsafe.Pointer)())
return (*messageReflectWrapper)(atomic.LoadPointer(&.p))
}
The pages are generated with Golds v0.4.9. (GOOS=linux GOARCH=amd64)