micro
micro is a lightweight Rust crate providing the FromDto procedural macro. It simplifies the conversion between Data Transfer Objects (DTOs) and your internal domain models by automatically generating From trait implementations.
Features
- Struct Mapping: Automatically maps named fields from a DTO to your domain struct.
- Enum Mapping: Supports Unit, Unnamed (tuple), and Named enum variants.
- Collection Support: Specialized handling for
Vec<T>andOption<T>, automatically calling.into()on inner items. - Generic Support: Correctly handles generic types (e.g.,
List<T>orResponse<T>) and generates appropriate trait bounds. - Attribute-Driven: Define multiple source types for a single domain model using the
#[from(...)]attribute.
Installation
Add this to your Cargo.toml:
[]
= "<version>" # Update <version> to latest
Usage
Basic Struct Conversion
If field names match, FromDto generates the boilerplate to convert from your DTO to your Domain model, calling .into() on every field to handle nested conversions.
use FromDto;
// The DTO (External Source)
// The Domain Model
Generic Enums
The macro handles generic parameters and complex enum structures. It automatically strips generics from paths in match arms to ensure compatibility with stable Rust.
Advanced Collections
FromDto detects Vec and Option types to ensure that inner types are converted correctly using the .into_iter().map(...).collect() pattern.
Nested Collections (Option + Vec)
Converting APIs often involves deeply nested optional collections, such as Option<Vec<T>>. Since Rust's Into trait does not automatically reach through multiple layers of containers, FromDto detects these patterns and generates the necessary mapping code automatically.
How it Works
The FromDto macro inspects your struct or enum at compile time and generates a From<Source> implementation:
- Generic Splitting: Uses
split_for_impl()to ensure trait bounds likeimpl<T> From<Source<T>>forTarget<T>are correctly declared. - Path Cleaning: It strips generic arguments from enum variants specifically within match arms. This avoids the "qualified paths in this context is experimental" error on stable Rust.
- Recursive Conversion: It assumes that inner types also implement From (or are decorated with
FromDto) and chains them using.into().