specta-swift 0.0.2

Export your Rust types to Swift
Documentation

Specta Swift

Crates.io Documentation License: MIT

A Rust crate for exporting Rust types to Swift, built on top of Specta. Generate idiomatic Swift code from your Rust type definitions with support for complex unions, generics, and nested structures.

Features

  • ๐Ÿš€ Zero Runtime Cost - Compile-time type generation
  • ๐ŸŽฏ Idiomatic Swift - Generates clean, Swift-idiomatic code
  • ๐Ÿ”„ Complex Unions - Full support for Rust enums with all variant types
  • ๐Ÿงฌ Generics - Single and multiple generic type parameters
  • ๐Ÿ”— Recursive Types - Self-referencing and circular type definitions
  • โš™๏ธ Highly Configurable - Naming conventions, indentation styles, optional syntax
  • ๐Ÿ“ฆ Type Safety - Leverages Specta's robust type introspection
  • ๐Ÿงช Well Tested - Comprehensive test suite with snapshot testing
  • ๐Ÿ•’ Special Types - Built-in support for Duration with helper structs
  • ๐Ÿ“ Documentation - Preserves and formats Rust doc comments in Swift
  • ๐Ÿ”ง Custom Codable - Automatic generation of custom Codable implementations
  • ๐ŸŽจ Protocol Conformance - Support for additional Swift protocols
  • ๐Ÿ“ File Export - Direct export to Swift files with custom headers

Quick Start

Add specta-swift and specta-serde to your Cargo.toml:

[dependencies]
specta = { version = "2.0", features = ["derive"] }
specta-serde = "0.0.11"
specta-swift = "0.1"

Define your Rust types:

use specta::{Type, Types};
use specta_swift::Swift;

#[derive(Type)]
struct User {
    id: u32,
    name: String,
    email: Option<String>,
    role: UserRole,
}

#[derive(Type)]
enum UserRole {
    Guest,
    User { permissions: Vec<String> },
    Admin { level: u8, department: String },
}

#[derive(Type)]
enum ApiResult<T> {
    Success { data: T, status: u16 },
    Error { message: String, code: u32 },
    Loading { progress: f32 },
}

Generate Swift code:

fn main() {
    let types = Types::default()
        .register::<User>()
        .register::<UserRole>()
        .register::<ApiResult<String>>();
    let resolved = specta_serde::apply(types).unwrap();

    let swift = Swift::default();
    swift.export_to("./Types.swift", &resolved).unwrap();
}

This generates:

// This file has been generated by Specta. DO NOT EDIT.
import Foundation

enum ApiResult<T>: Codable {
    case success(data: T, status: UInt16)
    case error(message: String, code: UInt32)
    case loading(progress: Float)
}

struct User: Codable {
    let id: UInt32
    let name: String
    let email: String?
    let role: UserRole
}

enum UserRole: Codable {
    case guest
    case user(permissions: [String])
    case admin(level: UInt8, department: String)
}

Advanced Features

Complex Union Types

Specta Swift supports all Rust enum variant types:

#[derive(Type)]
enum ComplexUnion {
    // Unit variant
    None,

    // Tuple variant
    Tuple(String, u32, bool),

    // Named fields variant
    NamedFields {
        id: u32,
        name: String,
        active: bool,
    },

    // Nested struct variant
    UserStruct(User),

    // Nested enum variant
    UserType(UserType),

    // Complex nested structure
    Complex {
        user: User,
        metadata: Vec<String>,
        settings: Option<Admin>,
    },
}

Generates:

enum ComplexUnion: Codable {
    case none
    case tuple(String, UInt32, Bool)
    case namedfields(id: UInt32, name: String, active: Bool)
    case userstruct(User)
    case usertype(UserType)
    case complex(user: User, metadata: [String], settings: Admin?)
}

Generic Types

Full support for generic types with multiple parameters:

#[derive(Type)]
enum DatabaseResult<T, E> {
    Ok { data: T, affected_rows: u64 },
    Err { error: E, query: String },
    ConnectionError { host: String, port: u16 },
}

Recursive Types

Self-referencing types are fully supported:

#[derive(Type)]
enum Shape {
    None,
    Point(f64, f64),
    Circle { center: Point, radius: f64 },
    Complex { shapes: Vec<Shape>, metadata: Option<String> },
}

Configuration

Naming Conventions

use specta_swift::{Swift, NamingConvention};

// PascalCase (default)
let swift = Swift::default();

// camelCase
let swift = Swift::new().naming(NamingConvention::CamelCase);

// snake_case
let swift = Swift::new().naming(NamingConvention::SnakeCase);

Optional Styles

use specta_swift::{Swift, OptionalStyle};

// T? syntax (default)
let swift = Swift::default();

// Optional<T> syntax
let swift = Swift::new().optionals(OptionalStyle::Optional);

Indentation Styles

use specta_swift::{Swift, IndentStyle};

// 4 spaces (default)
let swift = Swift::default();

// 2 spaces
let swift = Swift::new().indent(IndentStyle::Spaces(2));

// Tabs
let swift = Swift::new().indent(IndentStyle::Tabs);

Custom Headers

let swift = Swift::new()
    .header("// Generated by MyApp v2.0\n// Custom header with app info\n// DO NOT EDIT MANUALLY")
    .naming(NamingConvention::SnakeCase);

Additional Protocols

let swift = Swift::new()
    .add_protocol("Equatable")
    .add_protocol("Hashable")
    .add_protocol("CustomStringConvertible");

Serde Integration

let resolved = specta_serde::apply(types).unwrap();

let swift = Swift::new()
    .add_protocol("CustomDebugStringConvertible");

let output = swift.export(&resolved).unwrap();

Type Mapping

Rust Type Swift Type Notes
i8, i16, i32, i64 Int8, Int16, Int32, Int64 Signed integers
u8, u16, u32, u64 UInt8, UInt16, UInt32, UInt64 Unsigned integers
f32, f64 Float, Double Floating point numbers
bool Bool Boolean values
char Character Single Unicode character
String String UTF-8 strings
Option<T> T? or Optional<T> Optional values (configurable)
Vec<T> [T] Arrays
Vec<Vec<T>> [[T]] Nested arrays
HashMap<K, V> [K: V] Dictionaries
(T, U) (T, U) Tuples
std::time::Duration RustDuration + helper With automatic helper struct
struct struct Structures
enum enum Enums with custom Codable

Special Features

Duration Support

std::time::Duration types are automatically converted to a RustDuration helper struct:

#[derive(Type)]
struct Metrics {
    processing_time: Duration,
    timeout: Duration,
}

Generates:

// MARK: - Duration Helper
public struct RustDuration: Codable {
    public let secs: UInt64
    public let nanos: UInt32

    public var timeInterval: TimeInterval {
        return Double(secs) + Double(nanos) / 1_000_000_000.0
    }
}

public struct Metrics: Codable {
    public let processingTime: RustDuration
    public let timeout: RustDuration
}

Documentation Support

Rust doc comments are preserved and formatted for Swift:

/// A comprehensive user account
///
/// This struct represents a complete user account with all necessary
/// information for authentication and personalization.
///
/// # Security Notes
/// - The password field should never be logged
/// - All timestamps are in UTC
#[derive(Type)]
struct User {
    /// Unique identifier
    id: u32,
    /// User's display name
    name: String,
}

Generates:

/// A comprehensive user account
///
/// This struct represents a complete user account with all necessary
/// information for authentication and personalization.
///
/// # Security Notes
/// - The password field should never be logged
/// - All timestamps are in UTC
public struct User: Codable {
    /// Unique identifier
    public let id: UInt32
    /// User's display name
    public let name: String
}

Examples

Check out the examples/ directory for comprehensive examples:

  • basic_types.rs - Basic primitive types and their Swift equivalents
  • advanced_unions.rs - Complex enum scenarios and custom Codable implementations
  • configuration_options.rs - All Swift exporter configuration settings
  • special_types.rs - Duration types and special type handling
  • string_enums.rs - String enums and custom Codable patterns
  • comprehensive_demo.rs - Complete feature showcase (28 types!)
  • simple_usage.rs - Quick start example
  • comments_example.rs - Documentation and comment support

Run any example:

cargo run --example basic_types
cargo run --example comprehensive_demo

Generated Swift files are saved to examples/generated/ for inspection.

Testing

Run the test suite:

cargo test

The test suite includes:

  • Basic type generation tests
  • Comprehensive union type tests
  • Advanced recursive type tests
  • Duration type mapping tests
  • Custom Codable implementation tests
  • Configuration option tests
  • Snapshot testing for generated code
  • String enum handling tests
  • Generic type parameter tests

Contributing

Contributions are welcome! Please see the main Specta repository for contribution guidelines.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Related Projects