CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/go-protoc-gen-validate

Protoc plugin to generate polyglot message validators for protocol buffers

Pending
Overview
Eval results
Files

code-generation.mddocs/

Code Generation Templates

The code generation template system provides language-specific templates for generating validation code from protocol buffer files with validation rules. It uses Go's text/template package with custom functions for multi-language code generation.

Template System Architecture

Template Registration

type RegisterFn func(tpl *template.Template, params pgs.Parameters)

Function type for registering language-specific template functions and helpers.

Parameters:

  • tpl *template.Template: Template instance to register functions with
  • params pgs.Parameters: PGS parameters for configuration

File Path Generation

type FilePathFn func(f pgs.File, ctx pgsgo.Context, tpl *template.Template) *pgs.FilePath

Function type for generating output file paths for templates.

Parameters:

  • f pgs.File: Source proto file
  • ctx pgsgo.Context: Go language context
  • tpl *template.Template: Template being processed

Returns: *pgs.FilePath - Output file path for generated code

Template Factory

func Template(params pgs.Parameters) map[string][]*template.Template

Creates template map for all supported languages with registered functions.

Parameters:

  • params pgs.Parameters: PGS parameters for template configuration

Returns: map[string][]*template.Template - Map of language to templates

Supported languages and their templates:

  • "go": Single Go template with validation methods
  • "java": Single Java template with validation classes
  • "cc": Header (.h) and implementation (.cc) templates
  • "ccnop": No-op C++ templates for compatibility

File Path Resolution

func FilePathFor(tpl *template.Template) FilePathFn

Returns appropriate file path generation function for template type.

Parameters:

  • tpl *template.Template: Template to get path function for

Returns: FilePathFn - File path generation function

Behavior:

  • "h" templates → C++ header file paths
  • "cc" templates → C++ implementation file paths
  • "java" templates → Java file paths with package structure
  • Default → .validate.{ext} extension pattern

Language-Specific Templates

Go Templates

Go templates generate validation methods directly on protobuf message types.

Template Name: "go" Registration: golang.Register(tpl, params) Output Extension: .pb.validate.go

Generated code pattern:

func (m *Message) Validate() error {
  // validation logic
  return nil
}

func (m *Message) ValidateAll() error {
  // collect all validation errors
  return errors
}

Features:

  • Validates nested messages recursively
  • Returns first error (Validate) or all errors (ValidateAll)
  • Zero runtime dependencies
  • Full integration with existing protobuf Go code

Java Templates

Java templates generate validation classes with reflection-based validation.

Template Name: "java" Registration: java.Register(tpl, params) Output Extension: .java

Generated code pattern:

public class MessageValidator implements Validator<Message> {
  public void assertValid(Message message) throws ValidationException {
    // validation logic
  }
}

Java Template Functions

func Register(tpl *template.Template, params pgs.Parameters)

Main Java template registration function with full validation template functions.

func RegisterIndex(tpl *template.Template, params pgs.Parameters)

Index template registration for validator discovery and caching functionality.

func JavaMultiFilePath(f pgs.File, m pgs.Message) pgs.FilePath

Generates file paths for multi-file Java generation when java_multiple_files = true option is set.

Parameters:

  • f pgs.File: Source proto file
  • m pgs.Message: Message to generate validator for

Returns: pgs.FilePath - Path for individual message validator class

Features:

  • ReflectiveValidatorIndex for validator discovery
  • gRPC interceptor support
  • Exception-based error reporting
  • Multi-file generation support for large proto files

C++ Templates

C++ templates generate header and implementation files.

Template Names: "h", "cc" Registration: cc.RegisterHeader(tpl, params), cc.RegisterModule(tpl, params) Output Extensions: .pb.validate.h, .pb.validate.cc

Generated code pattern:

// Header
namespace validate {
  bool Validate(const Message& msg, std::string* error);
}

// Implementation  
bool Validate(const Message& msg, std::string* error) {
  // validation logic
  return true;
}

Features:

  • Separate header and implementation files
  • String-based error reporting
  • Integration with existing C++ protobuf code

C++ No-Op Templates

C++ no-op templates generate stub validation functions that always return valid.

Template Names: "h", "cc" (ccnop variant) Registration: ccnop.RegisterHeader(tpl, params), ccnop.RegisterModule(tpl, params) Output Extensions: .pb.validate.h, .pb.validate.cc

Generated code pattern:

// No-op validation - always returns true
bool Validate(const Message& msg, std::string* error) {
  return true;
}

Use Cases:

  • Placeholder validation during development
  • Disabling validation for performance-critical code
  • Maintaining API compatibility while bypassing validation

Features:

  • Same interface as full C++ templates
  • Zero validation logic - always passes
  • Minimal code generation overhead

Python Runtime

Python uses runtime code generation rather than compile-time templates.

Module: protoc_gen_validate.validator Approach: JIT code generation with caching

Generated functions are created dynamically:

def validate_Message(msg):
    # dynamically generated validation logic
    pass

Features:

  • JIT compilation of validation functions
  • LRU cache for performance
  • Dynamic code execution with exec()
  • Exception-based error reporting

Template Utilities

Shared Functions

All templates have access to shared utility functions:

func RegisterFunctions(tpl *template.Template, params pgs.Parameters)

Registers common template functions for:

  • Type conversion and formatting
  • Rule processing and validation
  • Code generation helpers
  • Language-specific formatting

Common template functions include:

  • String manipulation functions
  • Type checking functions
  • Rule evaluation helpers
  • Import path generation

Template Parameters

Templates receive PGS parameters for configuration:

Common Parameters:

  • lang: Target language
  • module: Go module path for imports
  • paths: Path configuration for output

Language-Specific Parameters:

  • Go: Module path, import style
  • Java: Package structure, multi-file options
  • C++: Namespace configuration
  • Python: Runtime validation options

Code Generation Process

Template Processing Flow

  1. PGS framework calls Execute() on validator module
  2. Module determines target language and gets templates
  3. For each proto file with validation rules:
    • Module calls CheckRules() to validate rule consistency
    • Templates are applied to generate code
    • File paths are determined using FilePathFor()
    • Generated code is added as artifacts

Multi-File Generation

Java supports multi-file generation for better organization:

func JavaMultiFilePath(f pgs.File, msg pgs.Message) *pgs.FilePath

Generates separate Java files for each message with validation rules.

Parameters:

  • f pgs.File: Source proto file
  • msg pgs.Message: Message to generate validator for

Returns: *pgs.FilePath - Path for message-specific validator file

Template Customization

Templates can be customized through:

  • Custom RegisterFn implementations
  • Parameter-based configuration
  • Language-specific template extensions
  • Custom file path generation

Error Handling

Template processing includes comprehensive error handling:

  • Rule Validation Errors: Inconsistent or contradictory rules
  • Template Processing Errors: Syntax or execution errors
  • File Generation Errors: Output path or permission issues
  • Language-Specific Errors: Type incompatibilities or feature limitations

All errors are reported through the PGS framework and cause protoc to exit with appropriate error codes.

Performance Considerations

Template Caching

Templates are created once per invocation and reused across files for performance.

Code Generation Optimization

  • Go: Uses efficient validation patterns with early returns
  • Java: Leverages reflection caching for performance
  • C++: Generates optimized validation loops
  • Python: Uses LRU caching for compiled validation functions

Memory Management

Templates are designed to minimize memory usage during generation:

  • Streaming code generation where possible
  • Efficient data structures for rule processing
  • Cleanup of temporary data structures

Install with Tessl CLI

npx tessl i tessl/go-protoc-gen-validate

docs

code-generation.md

core-plugin.md

generated-code.md

index.md

runtime-libraries.md

validation-rules.md

tile.json