unistructgen 0.2.2

A powerful Rust code generator
Documentation
# Getting Started with UniStructGen

UniStructGen makes it easy to generate type-safe Rust structs from various sources. This guide will walk you through the most common use cases.

## Table of Contents

1. [Quick Start with Proc Macros]#quick-start-with-proc-macros
2. [External API Integration]#external-api-integration
3. [CLI Usage]#cli-usage
4. [Advanced Features]#advanced-features

## Quick Start with Proc Macros

The fastest way to get started is using the procedural macros for compile-time code generation.

### Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
unistructgen-macro = "0.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

### Basic Usage

```rust
use unistructgen_macro::generate_struct_from_json;

// Generate a struct from inline JSON
generate_struct_from_json! {
    name = "User",
    json = r#"{
        "id": 42,
        "name": "Alice",
        "email": "alice@example.com",
        "is_active": true
    }"#
}

fn main() {
    // Now you can use the generated struct!
    let user = User {
        id: 1,
        name: "Bob".to_string(),
        email: "bob@example.com".to_string(),
        is_active: true,
    };

    println!("User: {} ({})", user.name, user.email);
}
```

### With Nested Objects

UniStructGen automatically generates nested structs:

```rust
generate_struct_from_json! {
    name = "Product",
    json = r#"{
        "id": 1,
        "name": "Laptop",
        "price": 999.99,
        "manufacturer": {
            "name": "TechCorp",
            "country": "USA"
        }
    }"#
}

// This generates both Product and Manufacturer structs!
```

## External API Integration

Generate structs directly from API responses at compile time:

```rust
use unistructgen_macro::struct_from_external_api;

// Fetch and generate from a real API during compilation
struct_from_external_api! {
    struct_name = "GithubUser",
    url_api = "https://api.github.com/users/octocat"
}

fn main() {
    // The GithubUser struct is now available with all fields from the API
    let user = GithubUser {
        login: "octocat".to_string(),
        id: 1,
        // ... all other fields from the GitHub API response
    };
}
```

### Advanced API Options

```rust
struct_from_external_api! {
    struct_name = "Post",
    url_api = "https://jsonplaceholder.typicode.com/posts/1",

    // Optional: Limit nested depth
    max_depth = 3,

    // Optional: Custom timeout in milliseconds
    request_timeout = 5000,

    // Optional: Make all fields optional
    optional = true,

    // Optional: Add Default derive
    default = true
}
```

## CLI Usage

For build scripts or CI/CD pipelines, use the CLI tool:

### Installation

```bash
cargo install unistructgen
```

### Basic Usage

```bash
# Generate from a JSON file
unistructgen generate --input user.json --name User --output src/models/user.rs

# With optional fields
unistructgen generate --input user.json --name User --optional

# With additional derives
unistructgen generate --input user.json --name User --serde true --default true
```

### Example: Build Script Integration

Create `build.rs`:

```rust
use std::process::Command;

fn main() {
    // Generate structs during build
    Command::new("unistructgen")
        .args(&[
            "generate",
            "--input", "schemas/api_response.json",
            "--name", "ApiResponse",
            "--output", "src/generated/api.rs"
        ])
        .status()
        .expect("Failed to generate structs");

    println!("cargo:rerun-if-changed=schemas/api_response.json");
}
```

## Advanced Features

### Compile-Time Fetch Controls

For macros that fetch remote content at compile time (`struct_from_external_api!`, `openapi_to_rust!` with `url`, `env_file` over HTTP), you can control networking behavior:

- `UNISTRUCTGEN_FETCH_OFFLINE=1` — disable network access (cache only)
- `UNISTRUCTGEN_FETCH_CACHE=0` — disable caching
- `UNISTRUCTGEN_FETCH_CACHE_DIR=/path` — custom cache directory
- `UNISTRUCTGEN_FETCH_TIMEOUT_MS=60000` — override timeout (ms)

### Smart Type Inference

UniStructGen automatically detects and converts special types:

```json
{
  "id": 12345,
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2023-01-15T10:30:00Z",
  "price": 19.99,
  "count": 42,
  "is_active": true,
  "tags": ["rust", "codegen"],
  "metadata": {
    "key": "value"
  }
}
```

Generates:

```rust
pub struct Generated {
    pub id: i64,
    pub uuid: uuid::Uuid,                    // Detected UUID
    pub created_at: chrono::DateTime<Utc>,  // Detected DateTime
    pub price: f64,
    pub count: i64,
    pub is_active: bool,
    pub tags: Vec<String>,                   // Detected array
    pub metadata: Metadata,                  // Nested struct
}
```

### Customizing Field Types

You can customize the generated code by editing after generation or using transformers (advanced).

### Working with Arrays

When your JSON contains arrays, UniStructGen analyzes the first element:

```rust
generate_struct_from_json! {
    name = "UserList",
    json = r#"{
        "users": [
            {
                "id": 1,
                "name": "Alice"
            },
            {
                "id": 2,
                "name": "Bob"
            }
        ]
    }"#
}

// Generates:
// struct UserList { users: Vec<User> }
// struct User { id: i64, name: String }
```

### Field Name Conversion

UniStructGen automatically converts field names to Rust conventions:

- `camelCase``snake_case`
- `PascalCase``snake_case`
- Preserves `snake_case`

Using `#[serde(rename = "...")]` to maintain original names.

## Best Practices

### 1. Use Proc Macros for Static Data

When your schema is known at compile time, use proc macros:

```rust
// ✅ Good - compile-time validation
generate_struct_from_json! {
    name = "Config",
    json = r#"{"host": "localhost", "port": 8080}"#
}
```

### 2. Use External API Macros Cautiously

External API calls happen at compile time. Use them for:
- Schema exploration
- Development/prototyping
- When the API schema is stable

```rust
// ⚠️ Runs during every compilation
struct_from_external_api! {
    struct_name = "Schema",
    url_api = "https://api.example.com/schema"
}
```

### 3. Use CLI for Build Pipelines

For production builds, generate code once and commit:

```bash
# Generate and commit the code
unistructgen generate --input schema.json --output src/models.rs
git add src/models.rs
```

### 4. Handle Optional Fields

If your API may omit fields, use the `optional` flag:

```rust
struct_from_external_api! {
    struct_name = "ApiResponse",
    url_api = "https://api.example.com/data",
    optional = true  // Makes all fields Option<T>
}
```

## Troubleshooting

### Compilation Errors

If you get compilation errors about missing types:

1. Add required dependencies to `Cargo.toml`:
```toml
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"] }  # For DateTime
uuid = { version = "1.0", features = ["serde", "v4"] }  # For UUID
```

### API Timeout

If external API calls timeout:

```rust
struct_from_external_api! {
    struct_name = "Data",
    url_api = "https://slow-api.example.com/data",
    request_timeout = 30000  // 30 seconds
}
```

## Next Steps

- Check out the [examples]examples/ directory for more use cases
- Read the [API documentation]https://docs.rs/unistructgen
- Explore advanced features like custom transformers
- Join our community discussions

## Need Help?

- 📖 [Full Documentation]https://docs.rs/unistructgen
- 💬 [GitHub Discussions]https://github.com/maxBogovick/unistructgen/discussions
- 🐛 [Report Issues]https://github.com/maxBogovick/unistructgen/issues