oneof 0.2.0

Enum variant projection — access one variant at a time
Documentation
//! Example for inspecting generated assembly with `cargo asm`.
//!
//! ```bash
//! # Compare OneOf-generated vs hand-written match assembly:
//! cargo +nightly asm --example chain_projection get_timeout_oneof
//! cargo +nightly asm --example chain_projection get_timeout_hand
//! cargo +nightly asm --example chain_projection get_timeout_hand_multi
//!
//! # With LTO (more aggressive inlining):
//! cargo +nightly asm --example chain_projection --release get_timeout_oneof
//! ```

use oneof::OneOf;

#[allow(dead_code)]
#[derive(OneOf)]
enum Event {
    Error(Error),
    Ignored,
}

#[allow(dead_code)]
#[derive(OneOf)]
enum Error {
    Network(NetworkError),
    Io(String),
}

#[allow(dead_code)]
#[derive(OneOf)]
enum NetworkError {
    Timeout,
    Dns(String),
    Refused,
}

/// Generated by `#[derive(OneOf)]` — chained projection via `?`.
fn get_timeout_oneof(event: &Event) -> Option<()> {
    event.error()?.network()?.timeout()
}

/// Hand-written — flat pattern, single match arm.
fn get_timeout_hand(event: &Event) -> Option<()> {
    match event {
        Event::Error(Error::Network(NetworkError::Timeout)) => Some(()),
        _ => None,
    }
}

/// Hand-written — nested match, three levels deep.
fn get_timeout_hand_multi(event: &Event) -> Option<()> {
    match event {
        Event::Error(e) => match e {
            Error::Network(n) => match n {
                NetworkError::Timeout => Some(()),
                _ => None,
            },
            _ => None,
        },
        _ => None,
    }
}

fn main() {
    let event = Event::Error(Error::Network(NetworkError::Timeout));

    let a = get_timeout_oneof(&event);
    let b = get_timeout_hand(&event);
    let c = get_timeout_hand_multi(&event);

    assert_eq!(a, b);
    assert_eq!(b, c);
    println!("All functions return the same result: {a:?}");
}