structlayout

package
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package structlayout holds the pure, pipeline-agnostic helpers for deciding whether a C struct can be surfaced as a plain Go value struct that reproduces the C ABI, and for width-correcting struct field Go types.

These functions operate only on strings, []string, and ints — they have no dependency on the frameworks (purego) or libraries (cgo) metadata models or type mappers — so both pipelines can share them. Struct emission itself stays pipeline-specific; only the ABI/layout reasoning lives here.

SCOPE — shared: used by both the frameworks (purego) and libraries (cgo) pipelines. Keep it dependency-free of either pipeline's mapper/metadata.

Index

Constants

This section is empty.

Variables

View Source
var Primitives = map[string]bool{
	"bool": true, "byte": true, "rune": true, "uintptr": true,
	"int": true, "int8": true, "int16": true, "int32": true, "int64": true,
	"uint": true, "uint8": true, "uint16": true, "uint32": true, "uint64": true,
	"float32": true, "float64": true,
}

Primitives is the set of Go primitive types a value-struct field may use directly. A field of any other bare type must be another emittable struct in the same package (checked via the emittable fixpoint in the caller).

Functions

func AlignElem

func AlignElem(align int, packed bool) string

AlignElem returns the Go type of a leading `_ [0]<elem>` field that forces a byte-array backing struct's alignment to the C alignment, or "" when none is needed. A packed struct is C-aligned to 1 (a plain [N]byte already matches). Go has no scalar wider than 8-byte alignment, so a 16-byte-aligned C type (rare SIMD) is aligned to 8 — the authoritative size is always a multiple of the C alignment, so a Go struct rounded up to <=8 never changes the size. Both the frameworks idiomatic and raw emitters share this.

func GoStructLayout

func GoStructLayout(goTypes []string, packed bool, sizer FieldSizer) (offsets []int, size int, ok bool)

GoStructLayout computes each field's byte offset and the total size of a Go struct with the given (width-corrected) field types, under Go's natural alignment (packed=false) or tight packing (packed=true). ok is false if any field's size is unknown.

func IsPrimitiveOrArrayOf

func IsPrimitiveOrArrayOf(goType string, ok func(elem string) bool) bool

IsPrimitiveOrArrayOf reports whether goType is a bare identifier (or a fixed-size array, possibly multi-dimensional, of one) whose element satisfies ok. A slice "[]T", a pointer, or a qualified/expression type is rejected.

func LayoutMatchesAuthoritative

func LayoutMatchesAuthoritative(size int, packed bool, fieldOffsets []int, goTypes []string, sizer FieldSizer) bool

LayoutMatchesAuthoritative verifies the width-corrected Go layout reproduces clang's authoritative record layout (per-field offsets + total size) when one was captured (size != 0). It returns true when no authoritative layout exists (nothing to cross-check — clang only lays out value-used structs) or when the Go layout matches exactly. A mismatch means the Go struct would not reproduce the C ABI, so the caller should keep the struct opaque.

fieldOffsets holds the authoritative byte offset of each field (in field order); its length is the struct's field count.

func LayoutSafeFromGoTypes

func LayoutSafeFromGoTypes(packed bool, goTypes []string) bool

LayoutSafeFromGoTypes reports whether a plain Go struct reproduces the C ABI field offsets of a struct — the condition under which reading fields through a pointer to the C data is correct. An unpacked struct always qualifies (Go and C use the same natural alignment for these scalar fields). A packed struct qualifies when every field is already naturally aligned at its packed offset, so Go inserts no inter-field padding. Trailing padding is deliberately NOT required: a packed struct ending on an odd size (e.g. IOUSBConfiguration Descriptor's 9 bytes) makes the Go value one byte larger, which is immaterial for pointer field access (the only way these are surfaced) though it means the value should not be bulk-copied out of a tightly-sized C allocation. A field whose Go type is not a fixed-width scalar makes the result false (conservative: the opaque path handles it).

func ScalarGoSizeAlign

func ScalarGoSizeAlign(goType string) (size, align int, ok bool)

ScalarGoSizeAlign returns the size and alignment (in bytes, arm64/amd64 LP64) of a hermetic scalar Go type, and ok=false for anything else (a nested struct, pointer, slice, or unresolved type). Only fixed-width types are admitted; notably Go int/uint/uintptr are 8 bytes here, so a field the mapper resolved to a platform-width int is treated as 8 — matching the LP64 C `long`/pointer it came from.

func StructFieldGoType

func StructFieldGoType(objcType, mapped string) string

StructFieldGoType corrects a struct field's Go type to the exact C ABI width where the type mapper widened a native C int to Go int/uint (8 bytes) even though a C int is 4. Struct fields — unlike function parameters — must match the C width exactly, or the Go struct would mislay every field after the first int. Arrays are corrected element-wise (int[4] → [4]int32). Other types (short→int16, long→int, stdint) already match and pass through.

Types

type FieldSizer

type FieldSizer func(goType string) (size, align int, ok bool)

FieldSizer resolves the size and alignment (bytes) of a non-primitive field Go type — an enum (by its underlying integer width) or a nested value struct (by its own layout) — and ok=false when goType is neither. It lets the layout helpers validate structs whose fields are not plain scalars. May be nil.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL