Skip to content

Conversation

@Debarshi-Gupta
Copy link
Contributor

@Debarshi-Gupta Debarshi-Gupta commented Sep 3, 2025

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

Overview of the Three Crates

1. smithy crate (Procedural Macro)

This is a procedural macro crate that provides the #[derive(SmithyModel)] attribute. It's the entry point for developers who want to generate Smithy models from their Rust structs.

Key characteristics:

  • Type: Procedural macro library (proc-macro = true)
  • Location: crates/smithy/
  • Dependencies: proc-macro2, quote, syn, smithy-core
  • Main export: SmithyModel derive macro

2. smithy-core crate (Core Logic)

This contains the fundamental types and logic for Smithy model generation. It acts as the shared foundation between the macro and the generator.

Key characteristics:

  • Type: Library crate

  • Location: crates/smithy-core/

  • Dependencies: serde, serde_json, syn, proc-macro2

  • Main modules:

    • types.rs - Core data structures (SmithyModel, SmithyShape, SmithyTrait, etc.)
    • generator.rs - SmithyGenerator for converting models to IDL files

3. smithy-generator crate (Code Generation Tool)

This is an executable that scans the entire workspace for structs annotated with #[derive(SmithyModel)] and generates the corresponding Smithy IDL files.

Key characteristics:

  • Type: Binary crate with build script

  • Location: crates/smithy-generator/

  • Dependencies: smithy-core, workspace crates (api_models, common_enums, etc.)

  • Components:

    • build.rs - Workspace scanner and registry generator
    • main.rs - IDL file generator

How They Work Together

Step 1: Developer Annotation

A developer annotates their Rust struct or enum with the derive macro:

#[derive(SmithyModel)]
#[smithy(namespace = "com.hyperswitch.payments")]
pub struct PaymentRequest {
    #[smithy(value_type = "String", required)]
    pub payment_id: String,
    
    #[smithy(value_type = "Option<i64>")]
    pub amount: Option<i64>,
}

Step 2: Procedural Macro Processing (smithy crate)

When the code is compiled, the smithy crate's procedural macro:

  1. Parses the struct/enum definition using syn

  2. Extracts metadata from #[smithy(...)] attributes (namespace, constraints, field types)

  3. Generates implementation of the SmithyModelGenerator trait for the annotated type

  4. Handles complex scenarios like:

    • Flattened fields (#[serde(flatten)])
    • Optional types (Option<T>)
    • Collections (Vec<T>, HashMap<K,V>)
    • Enum variants (both string enums and unions)
    • Constraint validation (patterns, ranges, lengths)

The generated code implements SmithyModelGenerator::generate_smithy_model() which returns a SmithyModel containing the structure definition.

Step 3: Build-Time Discovery (smithy-generator build script)

The smithy-generator crate has a build script (build.rs) that:

  1. Scans the entire workspace recursively through all crates/ subdirectories

  2. Uses regex parsing to find structs/enums with #[derive(SmithyModel)]

  3. Generates a registry file (model_registry.rs) containing:

    • Import statements for all discovered types
    • A discover_smithy_models() function that calls generate_smithy_model() on each type

Step 4: IDL Generation (smithy-generator executable)

When the smithy-generator binary runs:

  1. Loads the generated registry and calls discover_smithy_models()
  2. Collects all SmithyModel instances from across the workspace
  3. Groups models by namespace for organized file generation
  4. Uses SmithyGenerator from smithy-core to convert models to Smithy IDL syntax
  5. Writes .smithy files to smithy/models/ directory

Step 5: Smithy IDL Output

The final output is proper Smithy IDL files like:

$version: "2"

namespace com.hyperswitch.payments

/// Payment request structure
structure PaymentRequest {
    @required
    payment_id: String
    
    amount: Long
}

Key Design Patterns

Type Resolution System

The smithy-core/types.rs contains sophisticated type resolution logic that:

  • Maps Rust primitive types to Smithy equivalents (Stringsmithy.api#String)
  • Handles generic types recursively (Vec<T>List shapes, Option<T> → optional members)
  • Resolves custom types and manages cross-namespace references
  • Generates intermediate shapes for complex nested types

Constraint System

The framework supports rich constraint modeling:

  • Validation constraints: pattern, range, length
  • HTTP binding constraints: httpLabel, httpQuery
  • Structural constraints: required, mixin

Workspace Integration

The build script approach allows:

  • Zero-configuration discovery of models across the entire workspace
  • Compile-time validation that all referenced types exist
  • Automatic regeneration when models change
  • Selective inclusion of only relevant crates (excludes smithy crates themselves)

This architecture provides a seamless developer experience where you simply derive SmithyModel on your types, and the toolchain automatically discovers them and generates proper Smithy IDL files during the build process.

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

There are no test cases for this PR, since this is just addition of the Smithy Model generation framework to Hyperswitch. The only way to test this PR is to add the derive macros in structs and check the model generation, but that will be done in subsequent PRs.

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@Debarshi-Gupta Debarshi-Gupta requested a review from a team as a code owner September 3, 2025 05:11
@semanticdiff-com
Copy link

semanticdiff-com bot commented Sep 3, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  Cargo.lock Unsupported file format
  crates/smithy-core/Cargo.toml Unsupported file format
  crates/smithy-core/src/generator.rs  0% smaller
  crates/smithy-core/src/lib.rs  0% smaller
  crates/smithy-core/src/types.rs  0% smaller
  crates/smithy-generator/Cargo.toml Unsupported file format
  crates/smithy-generator/build.rs  0% smaller
  crates/smithy-generator/src/main.rs  0% smaller
  crates/smithy/Cargo.toml Unsupported file format
  crates/smithy/src/lib.rs  0% smaller

@Debarshi-Gupta Debarshi-Gupta self-assigned this Sep 3, 2025
@Debarshi-Gupta Debarshi-Gupta changed the title Added smithy, smithy-core and smithy-generator crates feat(framework): Added smithy, smithy-core and smithy-generator crates Sep 3, 2025
jarnura
jarnura previously approved these changes Sep 16, 2025
fn generate_shape_definition(
&self,
name: &str,
shape: &crate::types::SmithyShape,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
shape: &crate::types::SmithyShape,
shape: &types::SmithyShape,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved, thanks.

|target: &str| self.resolve_type(target, current_namespace, shape_to_namespace);

match shape {
crate::types::SmithyShape::Structure {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
crate::types::SmithyShape::Structure {
types::SmithyShape::Structure {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved, thanks.

def.push('}');
def
}
crate::types::SmithyShape::Union {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
crate::types::SmithyShape::Union {
types::SmithyShape::Union {

import and use it, fix in other places too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved, thanks.

@Debarshi-Gupta Debarshi-Gupta added the A-framework Area: Framework label Sep 22, 2025
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Sep 23, 2025
auto-merge was automatically disabled September 23, 2025 16:38

Pull Request is not mergeable

@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 23, 2025
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Sep 25, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Sep 25, 2025
@likhinbopanna likhinbopanna added this pull request to the merge queue Sep 26, 2025
Merged via the queue into main with commit 0baae33 Sep 26, 2025
21 of 25 checks passed
@likhinbopanna likhinbopanna deleted the smithy_framrwork_crate_impl branch September 26, 2025 08:06
pixincreate added a commit that referenced this pull request Sep 30, 2025
…pay-new-field

* 'main' of github.com:juspay/hyperswitch: (21 commits)
  feat(payments): add tokenization action handling to payment flow for braintree (#9506)
  feat(connector): [Loonio] Add template code (#9586)
  fix(connector): [paysafe] make `eci_indicator` field optional (#9591)
  fix(core): add should_call_connector_customer function to connector specification (#9569)
  feat(ucs): Add profile ID to lineage tracking in Unified Connector Service (#9559)
  feat(core): Add support for partial auth in proxy payments [V2] (#9503)
  chore(version): 2025.09.30.0
  fix(authorizedotnet): refund via ucs missing connector_metadata (#9581)
  feat(auth): add new authentication to communicate between microservices (#9547)
  Fix: Ideal Giropay Country Currency Config (#9552)
  feat(connector): [ACI] cypress added (#9502)
  feat(connector): Add Peachpayments Cypress (#9573)
  chore(version): 2025.09.29.0
  feat(finix): template code (#9557)
  feat(cypress): add cypress test-cases for manual retry (#9505)
  feat(core): update additional payment method data in psync response (#9519)
  feat(connector): [Checkout] Add Google Pay Predecrypt Flow (#9130)
  feat(framework): Added smithy, smithy-core and smithy-generator crates (#9249)
  fix(core): add request_extended_authorization in the payment attempt and populate it in the payment response (#9492)
  chore(version): 2025.09.26.0
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-framework Area: Framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants