Crate concrete_type

Crate concrete_type 

Source
Expand description

§Concrete Type

A procedural macro library for mapping enum variants to concrete types.

This crate provides two main derive macros:

  • Concrete - For enums where each variant maps to a specific concrete type
  • ConcreteConfig - For enums where each variant has associated configuration data and maps to a specific concrete type

These macros enable type-level programming based on runtime enum values by generating helper methods and macros that provide access to the concrete types associated with enum variants.

§Path Resolution

When specifying concrete types, you can use two path formats:

  • crate::path::to::Type - Use this for types defined in the same crate as the enum. The macro will transform this to $crate::path::to::Type for proper hygiene, allowing the generated macro to work both within the defining crate and from external crates.

  • other_crate::path::to::Type - Use this for types from external crates. The path is used as-is.

§Examples

§Basic Usage with Concrete

use concrete_type::Concrete;

#[derive(Concrete, Clone, Copy)]
enum Exchange {
    #[concrete = "crate::exchanges::Binance"]
    Binance,
    #[concrete = "crate::exchanges::Coinbase"]
    Coinbase,
}

mod exchanges {
    pub struct Binance;
    pub struct Coinbase;

    impl Binance {
        pub fn new() -> Self { Binance }
        pub fn name(&self) -> &'static str { "binance" }
    }

    impl Coinbase {
        pub fn new() -> Self { Coinbase }
        pub fn name(&self) -> &'static str { "coinbase" }
    }
}

// Use the auto-generated exchange! macro for type-level dispatch
let exchange = Exchange::Binance;
let name = exchange!(exchange; ExchangeImpl => {
    // ExchangeImpl is aliased to the concrete type
    let instance = ExchangeImpl::new();
    instance.name()
});
assert_eq!(name, "binance");

§Using ConcreteConfig with Configuration Data

use concrete_type::ConcreteConfig;

// Define concrete types and configuration types
mod exchanges {
    pub trait ExchangeApi {
        type Config;
        fn new(config: Self::Config) -> Self;
        fn name(&self) -> &'static str;
    }

    pub struct Binance;
    pub struct BinanceConfig {
        pub api_key: String,
    }

    impl ExchangeApi for Binance {
        type Config = BinanceConfig;
        fn new(_: Self::Config) -> Self { Self }
        fn name(&self) -> &'static str { "binance" }
    }
}

// Define the enum with concrete type mappings and config data
#[derive(ConcreteConfig)]
enum ExchangeConfig {
    #[concrete = "crate::exchanges::Binance"]
    Binance(exchanges::BinanceConfig),
}

// Using the auto-generated macro with access to both type and config
let config = ExchangeConfig::Binance(
    exchanges::BinanceConfig { api_key: "secret".to_string() }
);

let name = exchange_config!(config; (Exchange, cfg) => {
    // Inside this block:
    // - Exchange is the concrete type
    // - cfg is the configuration instance (BinanceConfig)
    use exchanges::ExchangeApi;
    Exchange::new(cfg).name()
});

See the crate documentation and examples for more details.

Derive Macros§

Concrete
A derive macro that implements the mapping between enum variants and concrete types.
ConcreteConfig
A derive macro that implements the mapping between enum variants with associated data and concrete types.