compiler

package
v0.72.0 Latest Latest
Warning

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

Go to latest
Published: May 19, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package compiler wraps protocompile to provide namespace-scoped compilation of proto source files. It handles normalization, SHA-256 hashing for content-addressable storage, and builds the resolver chain that enforces namespace isolation (chroot model).

Index

Constants

View Source
const (
	// DefaultCompileTimeout caps wall-clock time spent inside protocompile.
	DefaultCompileTimeout = 30 * time.Second

	// DefaultMaxFileSourceBytes caps the size of any individual proto
	// source the compiler will accept. Enforced before any AST work.
	DefaultMaxFileSourceBytes = 8 * 1024 * 1024 // 8 MiB

	// DefaultMaxFiles caps the number of files in a single Compile call.
	DefaultMaxFiles = 1000
)

Default resource caps. Compile is the user-facing entry point and these numbers bound worst-case CPU and memory consumption per call. The server applies tighter validation upstream; these are the library-level safety net so the compiler is also safe to embed in non-server callers.

Variables

This section is empty.

Functions

func ComputeFingerprint

func ComputeFingerprint(files []FileResult) string

ComputeFingerprint computes a fingerprint over a sorted set of (filename, hash) pairs. Used to detect whether a new submission actually changes anything compared to the current version.

func IsWellKnownType

func IsWellKnownType(filename string) bool

IsWellKnownType reports whether filename matches a standard import provided by protocompile (e.g., google/protobuf/timestamp.proto).

func Version

func Version() string

Version returns a string identifying the compiler and its dependencies, used to detect when cached compiled descriptors may be stale.

Types

type ChainTier added in v0.71.0

type ChainTier struct {
	// NamespaceID of this tier, for diagnostics and downstream attribution.
	NamespaceID string
	// Files contributed by this namespace at the pinned/current versions.
	Files []DepSource
}

ChainTier is one tier of the parent-namespace resolver chain. Each tier represents one ancestor namespace's contribution to filename resolution. Tiers are ordered nearest-first by the caller; the compiler walks them in order and the first match wins (filename-based resolution per D7).

type CompileResult

type CompileResult struct {
	// Snapshot is the compiled, immutable descriptor set.
	Snapshot *snapshot.Snapshot
	// Compiled is the serialized FileDescriptorSet for storage.
	Compiled []byte
	// Files is the list of normalized file hashes, for blob storage.
	Files []FileResult
	// Deps records which dependency versions were used during compilation.
	Deps []Dep
}

CompileResult holds the output of a compilation.

type Compiler

type Compiler struct {
	// contains filtered or unexported fields
}

Compiler wraps protocompile for namespace-scoped compilation.

func New

func New(opts ...CompilerOption) *Compiler

New creates a new Compiler with default caps. Pass options to override.

func (*Compiler) Compile

func (c *Compiler) Compile(
	ctx context.Context,
	version uint64,
	sources map[string][]byte,
	deps []DepSource,
	parentChain []ChainTier,
	builtins []DepSource,
) (*CompileResult, error)

Compile compiles the given proto sources within a namespace scope.

Parameters:

  • sources: filename → content for the schema being compiled (the child).
  • deps: files from other schemas in the *same* namespace, available for import. Each DepSource's Namespace should equal the publishing namespace.
  • parentChain: ancestor namespaces in resolution order (nearest first). Each tier's files are tried after the child's own namespace tier. Pass nil or empty for namespaces without a parent.
  • builtins: files from the __builtins__ namespace, available to every namespace; resolve after the parent chain but before Google WKT.

Resolution order: child sources & same-ns deps → parent chain tiers (nearest first) → builtins → Google well-known types. First file whose path matches wins (decision D7).

Compile does not perform cross-tier FQN collision detection (D2). Callers that need it should invoke DetectFQNConflicts on the resulting snapshot against each ancestor's snapshot.

type CompilerOption

type CompilerOption func(*Compiler)

CompilerOption customises a Compiler.

func WithMaxFileSourceBytes

func WithMaxFileSourceBytes(n int64) CompilerOption

WithMaxFileSourceBytes sets the per-file size cap.

func WithMaxFiles

func WithMaxFiles(n int) CompilerOption

WithMaxFiles sets the cap on the number of files per Compile call.

func WithTimeout

func WithTimeout(d time.Duration) CompilerOption

WithTimeout sets the wall-clock cap on a single Compile call. Pass 0 to disable (not recommended in server contexts).

type Dep

type Dep struct {
	DepNamespaceID string
	DepSchemaID    string
	DepFilename    string
	DepVersion     uint64
}

Dep records a dependency on another schema's file used during compilation.

DepNamespaceID identifies which namespace contributed the file. For same-namespace dependencies (cross-schema imports within the publishing namespace) this equals the publishing namespace's ID. For cross-namespace dependencies resolved via the namespace hierarchy, this is the ancestor namespace that supplied the file. See docs/design/namespace-hierarchy.md decision D3.

type DepSource

type DepSource struct {
	Namespace string
	SchemaID  string
	Version   uint64
	Filename  string
	Source    []byte
}

DepSource describes a file available to the compiler from another schema. Namespace identifies the contributing namespace. For same-namespace deps this equals the publishing namespace's ID; for parent-chain tiers this is the ancestor's ID.

func LoadBuiltIns

func LoadBuiltIns(dir string) ([]DepSource, error)

LoadBuiltIns reads all .proto files from dir recursively and returns them as DepSource entries suitable for passing to Compile as builtins. The filenames are relative to dir, matching proto import paths.

type FQNConflict added in v0.71.0

type FQNConflict struct {
	// FQN is the fully-qualified name that is defined in both snapshots.
	FQN string
	// Kind is what the FQN refers to: "message", "enum", "service",
	// "extension". For collisions where the two definitions are of
	// different kinds, Kind is "message" if either side is a message,
	// otherwise the child's kind.
	Kind string
	// ChildFile is the file in the child snapshot that defines the symbol.
	ChildFile string
	// AncestorFile is the file in the ancestor snapshot that defines it.
	AncestorFile string
}

FQNConflict describes a fully-qualified-name collision between a child and an ancestor in the namespace hierarchy. See decision D2 in docs/design/namespace-hierarchy.md.

func DetectFQNConflicts added in v0.71.0

func DetectFQNConflicts(child, ancestor *snapshot.Snapshot) []FQNConflict

DetectFQNConflicts walks every type defined in the child snapshot and returns those whose fully-qualified name is also defined in the ancestor snapshot **in a different file**. Same-file collisions are not flagged: they represent the legitimate case where the child imports a parent file, and the parent's types appear in the child's snapshot via that import — the definition is shared, not shadowed. A real D2 conflict (decision D2) is when the child redefines a parent FQN in one of its own files.

The check covers messages (including nested), enums (including nested), services, and top-level extensions. Method names within services are scoped under their service's FQN by protoreflect, so per-RPC collisions surface naturally through service-level FQN collisions.

Conflicts are returned in deterministic order (sorted by FQN) so error messages are stable across runs — important for golden tests.

type FQNConflictError added in v0.71.0

type FQNConflictError struct {
	AncestorNamespaceID string
	Conflicts           []FQNConflict
}

FQNConflictError aggregates one or more FQN collisions between a child snapshot and an ancestor. Callers (typically Registry.Publish) wrap or propagate this to surface a clear diagnostic.

func (*FQNConflictError) Error added in v0.71.0

func (e *FQNConflictError) Error() string

type FileResult

type FileResult struct {
	Filename       string
	BlobSHA256     string
	OriginalSource []byte
}

FileResult associates a filename with its content hash after normalization.

type NormalizeResult

type NormalizeResult struct {
	// SHA256 is the hex-encoded SHA-256 hash of the normalized content.
	SHA256 string
	// OriginalSource is the unmodified source as submitted.
	OriginalSource []byte
}

NormalizeResult holds the output of normalizing a proto source file.

func NormalizeAndHash

func NormalizeAndHash(filename string, source []byte) (*NormalizeResult, error)

NormalizeAndHash parses a proto file, produces a canonical (normalized) representation by printing the AST without comments or extraneous whitespace, and returns the SHA-256 hash of that normalized form.

The original source is returned unchanged for storage. The hash is used only for content-addressable deduplication and change detection.

Jump to

Keyboard shortcuts

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