cdd-rust is a compiler-driven development toolchain designed to enable "Surgical" Compiler-Driven Development.
Unlike traditional generators that blindly overwrite files or dump code into "generated" folders, cdd-rust understands
the Abstract Syntax Tree (AST) of your Rust code. It uses ra_ap_syntax (the underlying parser of rust-analyzer) to
read, understand, and safely patch your existing source code to match your OpenAPI specifications (and vice-versa).
The core engine features a non-destructive patcher (cdd-core/patcher) capable of merging OpenAPI definitions into an
existing codebase.
- AST-Aware: It preserves your comments, whitespace, and manual formatting.
- Smart Routing: It can parse your existing
actix_webconfiguration functions and inject missing.service()calls without duplicating existing ones. - Type Safety: OpenAPI types are strictly mapped to Rust constraints:
format: uuid➔uuid::Uuidformat: date-time➔chrono::DateTime<Utc>format: password➔Secret<String>
- Typed Queries: Query parameters are generated as dedicated structs (with
serderenames) and injected into handler signatures for strong typing.
Keep your code as the single source of truth. The sync workflow ensures your Rust models match your Postgres database
and are ready for OpenAPI generation.
- DB Inspection: Uses
dsyncto generate strictly typed Diesel structs from the DB schema. - Attribute Injection: Automatically parses generated structs to inject
#[derive(ToSchema, Serialize, Deserialize)]and necessary imports, ensuring compatibility with utoipa.
Generate strictly typed integration tests (tests/api_contracts.rs) that treat your application as a black box to
verify compliance with the spec.
- Smart Mocking: Automatically creates dummy values for Path, Query, and Body parameters based on strict type definitions.
- Non-JSON Bodies: Serializes
application/x-www-form-urlencoded,multipart/*, text, and binary request bodies using OAS encoding rules (examples and encoding metadata respected). - Runtime Expression Resolution: supports OAS 3.2 runtime expressions and embedded templates
(e.g.,
{$request.body#/id}andhttps://example.com?x={$request.path.id}) for HATEOAS link validation. - Schema Validation: Verifies that API responses strictly match the JSON Schema defined in your OpenAPI document
using
jsonschema. - Status & Header Checks: Fails tests on undocumented status codes and validates response headers against primitive schema types (integer/number/boolean) when specified.
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#20344b',
'primaryBorderColor': '#20344b',
'lineColor': '#20344b',
'fontFamily': 'Google Sans, sans-serif'
}
}}%%
graph TD
%% --- Section 1: Route Logic ---
%% Node: OpenAPI Path
OasPath("<strong>OpenAPI Path (YAML)</strong><br/>/users/{id}:<br/> get:<br/> parameters:<br/> - name: id<br/> in: path<br/> schema: {format: uuid}"):::yellow
%% Node: Actix Handler
Actix("<strong>Handler (Rust)</strong><br/>async fn get_user(<br/> id: web::Path<Uuid><br/>) -> impl Responder {<br/> /* Logic */<br/>}"):::blue
%% Flow: Down (Scaffold) & Up (Reflect)
OasPath ==>|"1. SCAFFOLD / PATCH<br/>(Injects Handler & Route Signature)"| Actix
Actix -.->|"2. REFLECT / GENERATE<br/>(Extracts Paths via AST)"| OasPath
%% --- Spacer to force vertical layout ---
Actix ~~~ OasSchema
%% --- Section 2: Data Models ---
%% Node: OpenAPI Schema
OasSchema("<strong>OpenAPI Schema (YAML)</strong><br/>components:<br/> schemas:<br/> User:<br/> type: object<br/> properties:<br/> email: {type: string}"):::yellow
%% Node: Diesel Model
Diesel("<strong>Data Model (Rust)</strong><br/>#[derive(ToSchema)]<br/>struct User {<br/> id: Uuid,<br/> email: String<br/>}"):::green
%% Flow: Down (Scaffold) & Up (Reflect)
OasSchema ==>|"1. SCAFFOLD / PATCH<br/>(Injects Fields & Types)"| Diesel
Diesel -.->|"2. REFLECT / GENERATE<br/>(Derives Attributes)"| OasSchema
%% --- Styles ---
classDef yellow fill:#f9ab00,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Consolas',font-size:14px,text-align:left;
classDef blue fill:#4285f4,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Consolas',font-size:14px,text-align:left;
classDef green fill:#34a853,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Consolas',font-size:14px,text-align:left;
linkStyle default stroke:#20344b,stroke-width:2px;
The internal architecture separates the core AST/OpenAPI parsing logic from the target code generation. This allows the
tool to support multiple web frameworks and ORMs through the BackendStrategy and ModelMapper traits.
graph LR
%% --- NODES ---
InputOAS(<strong>OpenAPI Spec</strong><br/><em>YAML</em>)
InputSrc(<strong>Rust Source</strong><br/><em>Files / Schema</em>)
subgraph Core [Layer 1: Core]
direction TB
P_OAS(<strong>OAS Parser</strong><br/><em>serde_yaml</em>)
P_AST(<strong>AST Parser</strong><br/><em>ra_ap_syntax</em>)
end
subgraph Analysis [Layer 2: Analysis]
IR(<strong>Intermediate Representation</strong><br/><em>ParsedRoute / ParsedStruct</em>)
end
subgraph Gen [Layer 3: Generation]
Base(<strong>Generator Engine</strong><br/><em>Traits: BackendStrategy & ModelMapper</em>)
%% The Fork
subgraph Targets [Targets]
direction TB
T_Actix(<strong>Actix</strong><br/><em>ActixStrategy</em>)
T_Diesel(<strong>Diesel</strong><br/><em>DieselMapper</em>)
T_OutputOAS(<strong>OpenAPI</strong><br/><em>Spec Generation</em>)
T_Future(<strong>Axum / SQLx</strong><br/><em>Future Strategies</em>)
end
end
%% --- EDGES ---
InputOAS --> P_OAS
InputSrc --> P_AST
P_OAS --> IR
P_AST --> IR
IR --> Base
Base -- "Scaffold / Test" --> T_Actix
Base -- "Sync Models" --> T_Diesel
Base -- "Reflect" --> T_OutputOAS
Base -. "Extension" .-> T_Future
%% --- STYLING ---
classDef blue fill:#4285f4,stroke:#ffffff,color:#ffffff,stroke-width:0px
classDef yellow fill:#f9ab00,stroke:#ffffff,color:#20344b,stroke-width:0px
classDef green fill:#34a853,stroke:#ffffff,color:#ffffff,stroke-width:0px
classDef white fill:#ffffff,stroke:#20344b,color:#20344b,stroke-width:2px
classDef future fill:#f1f3f4,stroke:#20344b,color:#20344b,stroke-width:2px,stroke-dasharray: 5 5
class InputOAS,InputSrc white
class P_OAS,P_AST blue
class IR yellow
class Base green
class T_Actix,T_Diesel,T_OutputOAS white
class T_Future future
The project is workspace-based to separate core logic from the command-line interface.
| Crate | Purpose |
|---|---|
cdd-core |
The Engine. Contains the ra_ap_syntax parsers, the OpenAPI 3.x parser (with 3.2 shims), AST diffing logic, and the Backend Strategy traits (currently implementing ActixStrategy). |
cdd-cli |
The Interface. Provides the sync and test-gen commands. |
cdd-web |
The Reference. An Actix+Diesel implementation demonstrating the generated code and tests in action. |
Synchronize Diesel models and inject OpenAPI attributes.
cargo run -p cdd-cli -- sync \
--schema-path web/src/schema.rs \
--model-dir web/src/modelsThis performs the following:
- Reads
schema.rs. - Generates rust structs in
models/usingdiesel/dsynclogic. - Patches the files to add
#![allow(missing_docs)],use utoipa::ToSchema;, and derive macros.
Scaffold integration tests to verify your implementation meets the contract.
cargo run -p cdd-cli -- test-gen \
--openapi-path docs/openapi.yaml \
--output-path web/tests/api_contracts.rs \
--app-factory crate::create_appThis generates a test file that:
- Initializes your App factory.
- Iterates through every route in your OpenAPI spec.
- Sensibly mocks requests.
- Validates that your Rust implementation returns the headers and bodies defined in the YAML.
Emit a minimal OpenAPI 3.2 document from a Rust struct/enum with optional info metadata.
cargo run -p cdd-cli -- schema-gen \
--source-path web/src/models/user.rs \
--name User \
--openapi \
--info-title "User API" \
--info-version "1.0.0" \
--info-summary "User service schema" \
--info-terms-of-service "https://example.com/terms" \
--info-contact-name "API Support" \
--info-contact-email "support@example.com" \
--info-license-name "Apache 2.0" \
--info-license-identifier "Apache-2.0"cdd-rust features a highly compliant custom parser found in core/src/oas.
- Versions: Supports OpenAPI 3.0 and 3.1 directly.
- Compatibility: Implements shims for OpenAPI 3.2, specifically handling the
$selfkeyword for Base URI determination (Appendix F) and downgrading version strings for library compatibility. - Relative
$self: Resolves relative$selfvalues (including dot-segment normalization) when matching local$reftargets andoperationRefpointers. - Validation: Enforces required
info, URI/email formatting for Info/Contact/License, leading-slashpaths, uniqueoperationIdvalues, templated path conflicts, component key naming rules, response status code keys, security scheme definitions, security requirement resolution, non-emptyresponse.descriptionandrequestBody.content, mutual exclusivity ofexamplevsexamplesfor parameters/headers, sequential-only use ofitemSchema, and rejectsadditionalOperationsthat reuse reserved HTTP methods. - Resolution: Local
$refresolution plus base-URI-aware absolute/relative self-references (no external fetch). - Multi-Document
$ref: OptionalDocumentRegistryresolves external OpenAPI/Schema documents (path items, parameters, request bodies, responses, headers, links, media types, and security schemes) plus schema$id/$anchortargets. - Schema
$idReferences: Resolves schema$refvalues that match component or inline$idURIs (absolute or resolved against$self). - Schema Anchors: Resolves
$anchor/$dynamicAnchortargets for component or inline schemas and resolves$dynamicRefusing dynamic anchor scope (falling back to standard$refresolution). - Relative Server URLs: Resolves relative
servers.urlvalues (e.g.,.,./v1,v1) into base paths with RFC3986 dot-segment normalization, using the retrieval URI when provided. - Polymorphism: handles
oneOf,anyOf, andallOf(flattening) into Rust Enums and Structs. - Discriminator Defaults: supports
discriminator.defaultMappingfor OAS 3.2 polymorphic schemas. - Extractors: Maps OAS parameters to backend-specific extractors (e.g.,
web::Query,web::Path,web::Json,SecurityScheme). - Media Types: Recognizes vendor
+jsonmedia types,text/*, and binary request bodies with dedicated extractors. - Media Type References: Resolves
components.mediaTypes$refentries insidecontent(request bodies, responses, and headers). - Parameter Content Media Types: Resolves
components.mediaTypes$refin parametercontent, supportsitemSchemafor sequential media types, and honorsserializedValue/externalValueexamples. - Content Schema Mapping: Uses
contentSchema(for JSON-encoded string payloads) to drive strong typing for parameters and request bodies. - Sequential Multipart: supports
multipart/mixedandmultipart/byterangesitemSchemanormalization. - Positional Encoding: parses
prefixEncoding/itemEncodingfor multipart media types (OAS 3.2). - Nested Encoding: parses and emits nested Encoding Object
encoding/prefixEncoding/itemEncodingfields. - Examples: Uses parameter
contentexamples when generating contract tests, and honorsdataValue/serializedValue/externalValuefor parameters and request bodies (serialized examples bypass re-encoding). - Sequential Media Types: Supports
itemSchemafor sequential JSON request bodies (e.g.,jsonl,ndjson) and maps toVec<T>. - Sequential Response Types: Uses
itemSchemafor sequential media types (includingtext/event-streamandmultipart/*) to inferVec<T>when noschemais present. - Sequential Vendor Suffixes: Treats
+jsonl,+ndjson, and+json-seqmedia types as sequential foritemSchematyping. - Response Validation: Contract tests validate JSON, vendor
+json, sequential JSON, andtext/event-streamresponses. - Response Headers: Resolves response header
$refandcontentdefinitions when extracting response metadata. - Response Header Content Priority: Prefers
content(or preservedx-cdd-content) over injectedschemawhen parsing response header media types, ensuringcontent-based headers round-trip correctly. - Response Header Content Round-Trip: Preserves header
contentmedia types (and examples) when generating OpenAPI. - Response Summary: Preserves Response Object
summaryduring parsing and OpenAPI generation (including callbacks). - Schema Dialects: Contract tests select JSON Schema draft via
jsonSchemaDialector per-schema$schema(defaults to Draft 2020-12 for OAS 3.1/3.2, Draft 4 for OAS 3.0/Swagger 2.0). - Header Arrays/Objects: Contract tests validate
schema-based header arrays/objects usingstyle: simple(explode and non-explode). - Reference Overrides: Honors Reference Object
descriptionoverrides for responses during validation and resolution. - Set-Cookie Handling: Validates
Set-Cookieheaders without comma-splitting, preserving cookie values that contain commas. - Querystring: Serializes
querystringparams as JSON when the media type isapplication/json(RFC3986-encoded). - Querystring Extractors: Non-form querystring parameters are surfaced as raw
Stringvalues in generated handlers to avoid incorrect form decoding; form-encoded querystrings remain typed. - Header/Cookie Params: Contract tests serialize header/cookie parameters using OAS
style/exploderules orcontentmedia types. - Header Validation: Enforces Header Object constraints (
schemavscontent,style: simple, noallowEmptyValue), and ignoresContent-Typeheaders. - Media Type Examples: Validates
examplevsexamplesmutual exclusivity in request/response content. - Component Media Types: Validates
components.mediaTypesexample conflicts and encoding field compatibility. - Serialized/External Examples: Preserves
serializedValueandexternalValueexamples when generating OpenAPI for parameters and request bodies. - Example Metadata: Preserves Example Object
summaryanddescriptionwhen round-tripping examples. - Example Ref Overrides: Applies Reference Object
summary/descriptionoverrides when resolving Example$refvalues. - Boolean Schemas: Handles
schema: true/falsein request/response bodies and response headers (rejects requiredfalsebodies). - Nullable Normalization: Converts
nullable/x-nullableintotype: [..., "null"]for OpenAPI → Rust typing. - Byte/Binary Formats: Maps
format: byte/format: binarytoVec<u8>in OpenAPI → Rust type mapping. - Boolean Parameter Schemas: Accepts
schema: truefor parameters (maps toString) and rejectsschema: false. - Example Precedence: Honors
serializedValue/externalValueexamples for parameters even whenvalueis present. - Style Validation: Enforces type constraints for
deepObject,spaceDelimited, andpipeDelimitedparameter styles. - Schema ExternalDocs: emits
externalDocsmetadata when generating OpenAPI schemas from Rust models. - Schema ExternalDocs Validation: Validates
externalDocs.urlon schema objects (including nested schemas). - Schema XML Validation: Validates schema
xmlobjects, includingnodeTypevalues and conflicts with deprecatedattribute/wrappedfields. - Serde Mapping: respects
rename_allanddeny_unknown_fieldswhen generating OpenAPI schemas from Rust models. - Link Servers: Applies Link Object
serveroverrides (including defaulted variables) when generating HATEOAS link construction code. - Link Server Metadata: Preserves Link Object
serverdetails (name/description/variables) when generating OpenAPI. - Link Validation: Resolves
operationRefpointers to concrete path+method targets and errors on unknownoperationIdlinks. - Link Components: Resolves
operationRefpointers tocomponents.pathItemswhen the component is referenced by a unique path (errors on ambiguity). - Link Round-Trip: Resolves
operationId/operationReftargets for codegen without mutating the original Link Object, avoiding invalidoperationId+operationRefemissions during OpenAPI generation. - Link Validation (Local Ref): Errors when a local
operationReffails to resolve to a known operation. - Link Object Validation: Enforces exactly one of
operationIdoroperationRef, validates Link Objectserverdefinitions, enforces link name key patterns, and detects link$refcycles. - Link Parameter Keys: Validates qualified Link
parameterskeys (e.g.,path.id) and substitutes them into link templates using the unqualified parameter name. - Link Parsing: Accepts normalized snake_case link keys (
operation_id,operation_ref,request_body) during YAML preprocessing. - OAuth2/OIDC Schemes: Preserves OAuth2 flows (including device authorization) and OpenID Connect discovery URLs when generating OpenAPI.
- Contract Tests: Skips webhook routes (inbound) during test generation.
- Contract Tests (Multipart): Builds multipart request payloads from example values and per-part
contentTypehints. - Contract Tests (Encoding Headers): Applies
Encodingobject headers to multipart parts (excludingContent-Type) and respectsEncoding.contentTypefor JSON-form-urlencoded fields. - Encoding Header Refs: Resolves
Encoding.headers$refentries againstcomponents.headerswhen extracting request body definitions. - Callbacks: Enforces
operationIduniqueness across callbacks and top-level operations. - Callback Parameters: Parses callback Path Item and Operation parameters, merging them for callback operations and emitting them during OpenAPI generation.
- Top-Level Security: Preserves root-level
securityrequirements when generating OpenAPI documents. - Operation Security Overrides: Preserves explicit operation-level
security(including empty arrays) without leaking global security into each operation during OpenAPI round-trips. - Callback Security: Parses and emits callback operation
securityrequirements (including inherited defaults). - Header Parameter Case: Treats header parameter names as case-insensitive when detecting duplicates.
- OpenAPI Generation: Emits top-level
tagsandservers(or per-operationservers) from parsed routes. - Round-Trip Metadata: Preserves original
operationIdvalues and selected response status/description/media type in generated OpenAPI (including callbacks). - Document Metadata Round-Trip:
parse_openapi_documentextracts$self,jsonSchemaDialect,info,servers,tags,externalDocs, and root-levelx-extensions for OpenAPI → Rust → OpenAPI workflows. - Component Preservation: Can merge existing
components(responses, examples, mediaTypes, etc.) when generating OpenAPI. - Schema Keyword Passthrough: Preserves advanced JSON Schema keywords (
if/then/else,dependentSchemas,unevaluatedProperties,contentSchema) across parameters, request/response bodies, and component schemas during OpenAPI ↔ Rust round-trips. - Paths/Webhooks Extensions: Accepts
x-keys at thepathsandwebhooksobject level without treating them as path items, and preserves them during OpenAPI generation. - Path Item Extensions: Preserves
x-extensions on Path Item Objects during OpenAPI ↔ Rust round-trips. - Server Override Round-Trip: Preserves path/operation-level
serversobjects (including variables) instead of collapsing to base paths. - Server URL Validation: Rejects invalid URI references in
servers.url(including whitespace in literal segments).
- Rust (Nightly toolchain required for
ra_ap_syntaxcompatibility feature flags in some contexts). - PostgreSQL (if running the reference web implementation).
git clone https://github.com/offscale/cdd-rust
cd cdd-rust
cargo build# Run unit tests
cargo test
# Run the generated contract tests (requires web/tests/api_contracts.rs to be generated)
cargo test -p cdd-webLicensed under either of Apache License, Version 2.0 or MIT license at your option.
Install the latest version of Rust. We tend to use nightly versions. CLI tool for installing Rust.
We use rust-clippy linters to improve code quality.
# Install Rust (nightly)
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain nightly
# Install cargo-make (cross-platform feature-rich reimplementation of Make)
$ cargo install --force cargo-make
# Install rustfmt (Rust formatter)
$ rustup component add rustfmt
# Clone this repo
$ git clone https://github.com/offscale/cdd-rust && cd cdd-rust
# Run tests
$ cargo test
# Format, build and test
$ cargo makeLicensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.