pointer API

pointer

package

API reference for the pointer package.

S
struct

FieldInfo

FieldInfo holds identity and tag metadata for a struct field.

pkg/pointer/registry.go:12-17
type FieldInfo struct

Fields

Name Type Description
Name string
Offset uintptr
Type reflect.Type
Tags map[string][]string
S
struct

typeMap

pkg/pointer/registry.go:19-22
type typeMap struct

Fields

Name Type Description
fields []FieldInfo
byOff map[uintptr]*FieldInfo
S
struct

Registry

Registry manages the mapping of struct types to their field offsets.

pkg/pointer/registry.go:25-30
type Registry struct

Methods

Register
Method

Register inspects a struct type and builds the field mapping.

Parameters

v any
func (*Registry) Register(v any)
{
	t := reflect.TypeOf(v)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct {
		panic(fmt.Sprintf("pointer.Register: expected struct, got %s", t.Kind()))
	}

	r.mu.Lock()
	defer r.mu.Unlock()

	if _, ok := r.cache[t]; ok {
		return
	}

	tm := &typeMap{byOff: make(map[uintptr]*FieldInfo)}

	for i := 0; i < t.NumField(); i++ {
		sf := t.Field(i)
		if !sf.IsExported() {
			continue
		}

		fi := FieldInfo{
			Name:   sf.Name,
			Offset: sf.Offset,
			Type:   sf.Type,
		}

		if r.tagName != "" {
			tagStr := sf.Tag.Get(r.tagName)
			if tagStr != "" {
				fi.Tags = r.parser.Parse(tagStr)
			}
		}

		tm.fields = append(tm.fields, fi)
		tm.byOff[sf.Offset] = &tm.fields[len(tm.fields)-1]
	}

	r.cache[t] = tm
}
Resolve
Method

Resolve retrieves field info for a given base struct and field pointer.

Parameters

base any
fieldPtr any

Returns

error
func (*Registry) Resolve(base any, fieldPtr any) (*FieldInfo, error)
{
	bv := reflect.ValueOf(base)
	if bv.Kind() != reflect.Ptr || bv.Elem().Kind() != reflect.Struct {
		return nil, fmt.Errorf("base must be a pointer to a struct")
	}

	fv := reflect.ValueOf(fieldPtr)
	if fv.Kind() != reflect.Ptr {
		return nil, fmt.Errorf("fieldPtr must be a pointer")
	}

	baseAddr := bv.Pointer()
	fieldAddr := fv.Pointer()
	offset := fieldAddr - baseAddr

	r.mu.RLock()
	tm, ok := r.cache[bv.Elem().Type()]
	r.mu.RUnlock()

	if !ok {
		return nil, fmt.Errorf("type %s not registered", bv.Elem().Type())
	}

	fi, ok := tm.byOff[offset]
	if !ok {
		return nil, fmt.Errorf("offset %d not found in type %s", offset, bv.Elem().Type())
	}

	return fi, nil
}

Fields

Name Type Description
tagName string
parser *tags.Parser
mu sync.RWMutex
cache map[reflect.Type]*typeMap
F
function

NewRegistry

NewRegistry creates a new Registry that parses the given tagName.

Parameters

tagName
string

Returns

pkg/pointer/registry.go:33-43
func NewRegistry(tagName string) *Registry

{
	return &Registry{
		tagName: tagName,
		parser: tags.NewParser(tagName,
			tags.WithPairDelimiter(";"),
			tags.WithKVSeparator(":"),
			tags.WithValueDelimiter(","),
		),
		cache: make(map[reflect.Type]*typeMap),
	}
}
F
function

FieldName

FieldName returns the Go field name for a field pointer.

Parameters

base
*B
fieldPtr
*F

Returns

string
pkg/pointer/registry.go:123-129
func FieldName[B any, F any](r *Registry, base *B, fieldPtr *F) string

{
	fi, err := r.Resolve(base, fieldPtr)
	if err != nil {
		panic(fmt.Sprintf("pointer.FieldName: %v", err))
	}
	return fi.Name
}
F
function

TagValue

TagValue returns the first value of a tag key for a field pointer.

Parameters

base
*B
fieldPtr
*F
key
string

Returns

string
pkg/pointer/registry.go:132-141
func TagValue[B any, F any](r *Registry, base *B, fieldPtr *F, key string) string

{
	fi, err := r.Resolve(base, fieldPtr)
	if err != nil {
		panic(fmt.Sprintf("pointer.TagValue: %v", err))
	}
	if vals, ok := fi.Tags[key]; ok && len(vals) > 0 {
		return vals[0]
	}
	return ""
}
F
function

HasTag

HasTag returns true if the tag key exists for a field pointer.

Parameters

base
*B
fieldPtr
*F
key
string

Returns

bool
pkg/pointer/registry.go:144-151
func HasTag[B any, F any](r *Registry, base *B, fieldPtr *F, key string) bool

{
	fi, err := r.Resolve(base, fieldPtr)
	if err != nil {
		panic(fmt.Sprintf("pointer.HasTag: %v", err))
	}
	_, ok := fi.Tags[key]
	return ok
}