assert_struct

Macro assert_struct 

Source
assert_struct!() { /* proc-macro */ }
Expand description

Structural assertion macro for testing complex data structures.

This procedural macro generates efficient runtime assertions that check structural patterns against actual values, providing detailed error messages when assertions fail. The macro transforms pattern-based syntax into optimized comparison code at compile time.

See the crate-level documentation for comprehensive guides and learning examples. This documentation serves as a complete specification reference.

§Syntax Specification

assert_struct!(expression, TypePattern);

TypePattern ::= TypeName '{' FieldPatternList '}'
             | '_' '{' FieldPatternList '}'  // Wildcard pattern
FieldPatternList ::= (FieldPattern ',')* ('..')?
FieldPattern ::= FieldName ':' Pattern
             | FieldName FieldOperation ':' Pattern  
FieldOperation ::= ('*')+ | ('.' Identifier '(' ArgumentList? ')')
Pattern ::= Value | ComparisonPattern | RangePattern | RegexPattern
         | EnumPattern | TuplePattern | SlicePattern | NestedPattern

§Complete Pattern Reference

§Basic Value Patterns

PatternSyntaxDescriptionConstraints
Exact Valuefield: valueDirect equality comparisonMust implement PartialEq
String Literalfield: "text"String comparison (no .to_string() needed)String or &str fields
Explicit Equalityfield: == valueSame as exact value but explicitMust implement PartialEq
Inequalityfield: != valueNot equal comparisonMust implement PartialEq

§Comparison Patterns

PatternSyntaxDescriptionConstraints
Greater Thanfield: > valueNumeric greater thanMust implement PartialOrd
Greater Equalfield: >= valueNumeric greater or equalMust implement PartialOrd
Less Thanfield: < valueNumeric less thanMust implement PartialOrd
Less Equalfield: <= valueNumeric less or equalMust implement PartialOrd

§Range Patterns

PatternSyntaxDescriptionConstraints
Inclusive Rangefield: start..=endValue in inclusive rangeMust implement PartialOrd
Exclusive Rangefield: start..endValue in exclusive rangeMust implement PartialOrd
Range Fromfield: start..Value greater or equal to startMust implement PartialOrd
Range Tofield: ..endValue less than endMust implement PartialOrd
Range Fullfield: ..Matches any valueNo constraints

§String Pattern Matching

PatternSyntaxDescriptionConstraints
Regex Literalfield: =~ r"pattern"Regular expression matchRequires regex feature, String/&str
Like Traitfield: =~ expressionCustom pattern matchingMust implement Like<T>

§Field Operations

OperationSyntaxDescriptionConstraints
Dereference*field: patternDereference smart pointerMust implement Deref
Multiple Deref**field: patternMultiple dereferenceMust implement Deref (nested)
Method Callfield.method(): patternCall method and match resultMethod must exist and return compatible type
Method with Argsfield.method(args): patternCall method with argumentsMethod must exist with compatible signature
Tuple Method(index.method(): pattern, _)Method on tuple elementValid index, method exists

§Enum Patterns

PatternSyntaxDescriptionConstraints
Option Somefield: Some(pattern)Match Some variant with inner patternOption<T> field
Option Nonefield: NoneMatch None variantOption<T> field
Result Okfield: Ok(pattern)Match Ok variant with inner patternResult<T, E> field
Result Errfield: Err(pattern)Match Err variant with inner patternResult<T, E> field
Unit Variantfield: EnumType::VariantMatch unit enum variantEnum with unit variant
Tuple Variantfield: EnumType::Variant(patterns...)Match tuple enum variantEnum with tuple variant
Struct Variantfield: EnumType::Variant { fields... }Match struct enum variantEnum with struct variant

§Wildcard Struct Patterns

PatternSyntaxDescriptionConstraints
Wildcard Structvalue: _ { fields... }Match struct without naming typeMust use .. for partial matching
Nested Wildcard_ { field: _ { ... }, .. }Nested anonymous structsAvoids importing nested types

§Collection Patterns

PatternSyntaxDescriptionConstraints
Exact Slicefield: [pattern, pattern, ...]Match exact slice elementsVec<T> or slice
Partial Headfield: [pattern, ..]Match prefix elementsVec<T> or slice
Partial Tailfield: [.., pattern]Match suffix elementsVec<T> or slice
Head and Tailfield: [pattern, .., pattern]Match first and lastVec<T> or slice
Empty Slicefield: []Match empty collectionVec<T> or slice

§Tuple Patterns

PatternSyntaxDescriptionConstraints
Exact Tuplefield: (pattern, pattern, ...)Match all tuple elementsTuple type
Wildcard Elementfield: (pattern, _, pattern)Ignore specific elementsTuple type
Indexed Methodfield: (0.method(): pattern, _)Method call on tuple elementValid index

§Parameters

  • expression: Any expression that evaluates to a struct instance. The expression is borrowed, not consumed, so the value remains available after the assertion.
  • TypeName: The struct type name. Must exactly match the runtime type of the expression.
  • { fields }: Pattern specification for struct fields. Can be partial (with ..) or exhaustive.

§Runtime Behavior

§Evaluation Semantics

  • Non-consuming: The macro borrows the value, leaving it available after the assertion
  • Expression evaluation: The expression is evaluated exactly once before pattern matching
  • Short-circuit evaluation: Patterns are evaluated left-to-right, failing fast on first mismatch
  • Field order independence: Fields can be specified in any order in the pattern
  • Type requirements: All fields must have types compatible with their patterns

§Pattern Matching Rules

§Exhaustive vs Partial Matching

  • Without ..: All struct fields must be specified in the pattern (exhaustive)
  • With ..: Only specified fields are checked (partial matching)
  • Multiple ..: Compilation error - only one rest pattern allowed per struct

§Field Operation Precedence

Field operations are applied in left-to-right order:

**field.method().other_method(): pattern
// Equivalent to: ((*(*field)).method()).other_method()

§String Literal Handling

  • String literals ("text") automatically work with String and &str fields
  • No .to_string() conversion needed in patterns
  • Comparison uses PartialEq implementation

§Panics

The macro panics (causing test failure) when:

§Pattern Mismatches

  • Value mismatch: Expected value doesn’t equal actual value
  • Comparison failure: Comparison operator condition fails (e.g., >, <)
  • Range mismatch: Value outside specified range
  • Enum variant mismatch: Different enum variant than expected
  • Collection length mismatch: Slice pattern length differs from actual length
  • None/Some mismatch: Expected Some but got None, or vice versa
  • Ok/Err mismatch: Expected Ok but got Err, or vice versa

§Method Call Failures

  • Method panic: Called method itself panics during execution
  • Argument evaluation panic: Method arguments panic during evaluation

§Regex Failures (when regex feature enabled)

  • Invalid regex: Malformed regular expression pattern
  • Regex evaluation panic: Regex engine encounters error

§Runtime Type Issues

Note: Type mismatches are caught at compile time, not runtime.

§Compilation Errors

§Field Validation

  • Nonexistent field: Field doesn’t exist on the struct type
  • Missing fields: Required fields not specified (without ..)
  • Duplicate fields: Same field specified multiple times
  • Invalid field operations: Operations not supported by field type

§Type Compatibility

  • Type mismatch: Pattern type incompatible with field type
  • Trait requirements: Field doesn’t implement required traits (PartialEq, PartialOrd, etc.)
  • Method signatures: Method doesn’t exist or has incompatible signature
  • Deref constraints: Field type doesn’t implement Deref for dereference operations

§Syntax Validation

  • Invalid syntax: Malformed pattern syntax
  • Invalid operators: Unsupported operator for field type
  • Invalid ranges: Malformed range expressions
  • Invalid regex syntax: Invalid regex literal (when using raw strings)
  • Multiple rest patterns: More than one .. in same struct pattern

§Feature Requirements

  • Missing regex feature: Using =~ r"pattern" without regex feature enabled
  • Like trait not implemented: Using =~ expr where Like trait not implemented

§Edge Cases and Limitations

§Method Call Constraints

  • Return type compatibility: Method return type must be compatible with pattern type
  • Argument evaluation: Method arguments are evaluated before the method call
  • No generic method inference: Generic methods may require explicit type annotations
  • Tuple indexing bounds: Tuple method calls require valid index at compile time

§Collection Pattern Limitations

  • Fixed length patterns: Slice patterns without .. require exact length match
  • Nested pattern complexity: Deeply nested slice patterns may impact compile time
  • Memory usage: Large literal slice patterns increase binary size

§Smart Pointer Behavior

  • Multiple deref levels: Each * adds one deref level, must match pointer nesting
  • Deref coercion: Standard Rust deref coercion rules apply
  • Ownership semantics: Dereferencing borrows the pointed-to value

§Performance Considerations

  • Compile time: Complex nested patterns increase compilation time
  • Runtime overhead: Pattern matching is zero-cost for simple patterns
  • Error message generation: Error formatting only occurs on failure

§Feature Dependencies

§Regex Feature (regex)

  • Default: Enabled by default
  • Required for: =~ r"pattern" syntax with string literals
  • Disable with: default-features = false in Cargo.toml
  • Alternative: Use Like trait with pre-compiled regex or custom patterns

§Like Trait Extension

  • No feature required: Always available
  • Custom implementations: Implement Like<T> for custom pattern matching
  • Regex integration: Built-in implementations for regex when feature enabled

§Error Message Format

When assertions fail, the macro generates structured error messages with:

§Error Components

  • Error type: Specific failure category (value mismatch, comparison failure, etc.)
  • Field path: Complete path to the failing field (e.g., response.user.profile.age)
  • Source location: File name and line number of the assertion
  • Actual value: The value that was found
  • Expected pattern: The pattern that was expected to match
  • Pattern context: Visual representation showing where the failure occurred

§Error Types

  • value mismatch: Direct equality comparison failed
  • comparison mismatch: Comparison operator condition failed (>, <, etc.)
  • range mismatch: Value outside specified range
  • regex mismatch: Regex pattern didn’t match
  • enum variant mismatch: Wrong enum variant
  • slice mismatch: Collection length or element pattern failure
  • method call error: Method call or result pattern failure

§Pattern Context Display

Complex patterns show visual context with failure highlighting:

assert_struct! failed:

   | Response { user: User { profile: Profile {
comparison mismatch:
  --> `response.user.profile.age` (tests/api.rs:45)
   |         age: > 18,
   |              ^^^^^ actual: 17
   | } } }

§Method Call Errors

Method calls in field paths are clearly indicated:

comparison mismatch:
  --> `data.items.len()` (tests/collections.rs:23)
  actual: 3
  expected: > 5

§Quick Reference Examples

// Basic pattern matching
assert_struct!(example, Example {
    value: 42,                    // Exact equality
    name: != "other",             // Inequality  
    items.len(): >= 2,            // Method call with comparison
    ..                            // Partial matching
});

§See Also

  • Learning Guide: See the crate-level documentation for comprehensive examples
  • Real-World Examples: Check the examples/ directory for practical usage patterns
  • Like Trait: Implement custom pattern matching with the Like trait