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

generated-code.mddocs/

Generated Code API

The generated code API provides validation methods and utilities for each target language. The specific API varies by language but provides consistent validation functionality across all supported platforms.

Go Generated Code

Go code generation produces validation methods directly on protobuf message types with zero runtime dependencies.

Validation Methods

func (m *Message) Validate() error

Validates the message according to its validation rules, returning the first error encountered.

Returns: error - First validation error, or nil if valid

Behavior:

  • Returns immediately on first validation failure
  • Validates nested messages recursively (unless skipped)
  • Provides detailed error messages with field context
  • Zero allocations for valid messages

Usage:

user := &User{Email: "invalid-email"}
if err := user.Validate(); err != nil {
  log.Printf("Validation failed: %v", err)
}
func (m *Message) ValidateAll() error

Validates the message and collects all validation errors into a single error.

Returns: error - Combined validation errors, or nil if valid

Behavior:

  • Continues validation after first error
  • Collects all validation failures
  • Returns structured error with all field errors
  • Useful for form validation scenarios

Usage:

user := &User{Email: "invalid", Age: -1}
if err := user.ValidateAll(); err != nil {
  // err contains both email and age validation errors
  log.Printf("All validation errors: %v", err)
}

Error Types

Generated Go code uses standard error interface with descriptive messages:

// Example error messages
"invalid User.Email: value must be a valid email address"
"invalid User.Age: value must be greater than 0"
"invalid User.Name: value length must be at least 1 characters"

Integration

Generated validation integrates seamlessly with existing Go protobuf code:

import (
  "github.com/example/proto/user"
  // validation methods are automatically available
)

func processUser(u *user.User) error {
  if err := u.Validate(); err != nil {
    return fmt.Errorf("invalid user: %w", err)
  }
  // process valid user
  return nil
}

Java Generated Code

Java code generation produces validator classes with reflection-based validation and gRPC integration support.

Validator Interface

interface Validator<T> {
  void assertValid(T message) throws ValidationException;
}

Base interface for all generated validators.

Type Parameters:

  • T: Message type being validated

Methods:

  • assertValid(T message): Validates message, throws on failure

Validator Index

class ReflectiveValidatorIndex {
  public Validator validatorFor(Class<?> clazz);
}

Main entry point for accessing validators by message class.

Methods:

  • validatorFor(Class<?> clazz): Returns validator for message class

Usage:

ValidatorIndex index = new ReflectiveValidatorIndex();
Validator<User> userValidator = index.validatorFor(User.class);
userValidator.assertValid(user); // throws ValidationException if invalid

gRPC Integration

class ValidatingClientInterceptor implements ClientInterceptor
class ValidatingServerInterceptor implements ServerInterceptor

gRPC interceptors for automatic request/response validation.

Usage:

// Client-side validation
clientStub = clientStub.withInterceptors(new ValidatingClientInterceptor(index));

// Server-side validation  
serverBuilder.addService(
  ServerInterceptors.intercept(service, new ValidatingServerInterceptor(index))
);

Exception Handling

class ValidationException extends Exception {
  public ValidationException(String message);
  public String getFieldPath();
  public Object getInvalidValue();
}

Exception thrown when validation fails.

Methods:

  • getFieldPath(): Returns field path that failed validation
  • getInvalidValue(): Returns the invalid value

C++ Generated Code

C++ code generation produces validation functions with string-based error reporting.

Validation Functions

bool Validate(const Message& msg, std::string* error = nullptr);

Validates a message and optionally returns error details.

Parameters:

  • msg: Const reference to message to validate
  • error: Optional pointer to string for error details

Returns: bool - true if valid, false if invalid

Usage:

User user;
user.set_email("invalid-email");

std::string error;
if (!Validate(user, &error)) {
  std::cerr << "Validation failed: " << error << std::endl;
}

Namespace Organization

Generated C++ code is organized in the validate namespace:

namespace validate {
  bool Validate(const example::User& msg, std::string* error);
  bool Validate(const example::Order& msg, std::string* error);  
  // ... other message validators
}

Header/Implementation Split

C++ generation produces separate header and implementation files:

Header (.pb.validate.h):

  • Function declarations
  • Include dependencies
  • Namespace definitions

Implementation (.pb.validate.cc):

  • Function implementations
  • Validation logic
  • Error message generation

Python Runtime API

Python uses runtime code generation with dynamic validation function creation.

Validation Function

def validate(msg) -> None

Validates a protobuf message instance, raising exception on failure.

Parameters:

  • msg: Protobuf message instance to validate

Raises: ValidationFailed - When validation fails

Usage:

from entities_pb2 import User
from protoc_gen_validate.validator import validate, ValidationFailed

user = User(email="invalid-email")
try:
    validate(user)
except ValidationFailed as e:
    print(f"Validation failed: {e}")

Debug Function

def print_validate(msg) -> None

Prints the generated validation code for debugging purposes.

Parameters:

  • msg: Protobuf message instance

Behavior:

  • Generates validation function code dynamically
  • Prints the generated Python code to stdout
  • Useful for debugging validation logic

Usage:

from protoc_gen_validate.validator import print_validate

user = User()
print_validate(user)  # Prints generated validation function

Exception Type

class ValidationFailed(Exception):
  """Raised when message validation fails"""
  pass

Exception raised when validation fails.

Inheritance: Standard Python Exception

Usage:

try:
    validate(message)
except ValidationFailed as e:
    logger.error(f"Invalid message: {e}")

Performance Features

Python runtime includes performance optimizations:

  • LRU Cache: Compiled validation functions are cached by message descriptor
  • JIT Compilation: Validation functions generated on-demand using exec()
  • Lazy Loading: Functions only generated when first needed

Cross-Language Consistency

All generated code maintains consistent behavior across languages:

Validation Semantics

  • Same validation rules produce same results
  • Consistent error detection and reporting
  • Identical handling of edge cases and special values

Error Messages

  • Similar error message patterns across languages
  • Field path information included where possible
  • Descriptive error text for debugging

Performance Characteristics

  • Minimal overhead for valid messages
  • Early termination on first error (where applicable)
  • Efficient nested message validation

Integration Patterns

Framework Integration

Go:

  • HTTP middleware for request validation
  • gRPC interceptors
  • Database model validation

Java:

  • Spring Boot validation integration
  • JAX-RS request validation
  • gRPC service validation

C++:

  • Service layer validation
  • Protocol buffer message verification
  • API boundary checking

Python:

  • Django/Flask request validation
  • Celery task parameter validation
  • API endpoint validation

Testing Support

All generated code supports testing scenarios:

  • Mock validation for unit tests
  • Validation bypass for test data setup
  • Error injection for negative testing
  • Performance benchmarking utilities

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