oneof 0.1.0

Enum variant projection — access one variant at a time
Documentation
#![cfg_attr(not(test), no_std)]

/// # OneOf — Enum variant projection for Rust
///
/// `OneOf` generates ergonomic methods to access individual enum variants
/// without writing repetitive `match` arms. It provides a **zero-cost abstraction**
/// — the generated code compiles to the same machine code as hand-written match.
///
/// ## Motivation
///
/// Rust enums are powerful, but accessing one variant at a time requires
/// boilerplate:
///
/// ```rust
/// # use oneof::OneOf;
/// #[derive(OneOf)]
/// enum Event {
///     Request { id: u64, path: String },
///     Error(String),
///     Timeout,
/// }
///
/// // Instead of:
/// let event = Event::Timeout;
/// let is_timeout = match &event {
///     Event::Timeout => true,
///     _ => false,
/// };
///
/// // Write:
/// assert!(event.is_timeout());
///
/// // Instead of:
/// fn get_error(e: &Event) -> Option<&String> {
///     match e {
///         Event::Error(msg) => Some(msg),
///         _ => None,
///     }
/// }
///
/// // Write:
/// let e = Event::Error("boom".into());
/// assert_eq!(e.error(), Some(&"boom".into()));
/// ```
///
/// ## Generated methods
///
/// For each variant `Foo`, `#[derive(OneOf)]` generates:
///
/// | Method | Signature | Description |
/// |--------|-----------|-------------|
/// | `foo()` | `(&self) -> Option<&Payload>` | Reference to the variant payload |
/// | `foo_mut()` | `(&mut self) -> Option<&mut Payload>` | Mutable reference |
/// | `into_foo()` | `(self) -> Option<Payload>` | Consume and extract |
/// | `is_foo()` | `(&self) -> bool` | Check variant |
///
/// The payload type depends on the variant shape:
///
/// | Variant | Return type of `foo()` |
/// |---------|----------------------|
/// | `Foo` (unit) | `Option<()>` |
/// | `Foo(T)` (single tuple) | `Option<&T>` |
/// | `Foo(T0, T1)` (multi tuple) | `Option<(&T0, &T1)>` |
/// | `Foo { field: T }` (single named) | `Option<&T>` |
/// | `Foo { f0: T0, f1: T1 }` (multi named) | `Option<(&T0, &T1)>` |
///
/// ## Real-world usage
///
/// Filtering collections becomes concise:
///
/// ```rust
/// # use oneof::OneOf;
/// #[derive(OneOf)]
/// enum Status {
///     Active(u32),
///     Inactive,
///     Error(String),
/// }
///
/// let items = vec![
///     Status::Active(1),
///     Status::Inactive,
///     Status::Active(2),
///     Status::Error("fail".into()),
/// ];
///
/// // Extract all active IDs:
/// let active_ids: Vec<&u32> = items.iter().filter_map(|x| x.active()).collect();
/// assert_eq!(active_ids, vec![&1, &2]);
///
/// // Find the first error:
/// let first_error: Option<&String> = items.iter().filter_map(|x| x.error()).next();
/// assert_eq!(first_error, Some(&"fail".into()));
/// ```
///
/// ## Generics and lifetimes
///
/// ```rust
/// # use oneof::OneOf;
/// #[derive(OneOf)]
/// enum RefOrOwned<'a, T: Clone> {
///     Ref(&'a T),
///     Owned(T),
/// }
/// ```
///
/// ## `no_std` support
///
/// This crate is `#![no_std]` compatible. The derive macro only depends on
/// `Option` and `match`, both available in `core`.
///
/// ## Comparison with `strum`
///
/// [`strum`](https://crates.io/crates/strum) is great for enum-wide operations
/// (iterating variants, converting to strings, counting). `OneOf` complements
/// it by generating per-variant accessor methods — something `strum` doesn't
/// provide. They can be used together.
pub use oneof_derive::OneOf;

/// Marker trait for enums that support variant projection.
///
/// This trait is **not automatically derived** by `#[derive(OneOf)]`.
/// Implement it manually if you need a trait bound:
///
/// ```rust
/// use oneof::{OneOf, OneOfVariant};
///
/// #[derive(OneOf)]
/// enum MyEnum { A, B }
///
/// // Manual implementation (empty trait, one line):
/// impl OneOfVariant for MyEnum {}
///
/// fn accepts_one_of<T: OneOfVariant>() { /* ... */ }
/// accepts_one_of::<MyEnum>();
/// ```
pub trait OneOfVariant {}