Expand description

Derive functions on an Enum for easily accessing individual items in the Enum. This crate is intended to be used with the enum-extract-error crate.

Summary

This crate adds a EnumExtract derive macro that adds the following functions for each variant in your enum:

  1. is_[variant]: Returns a bool indicated whether the actual variant matches the expected variant.
  2. as_[variant]: Returns a Result with a reference to the data contained by the variant, or an error if the actual variant is not the expected variant type.
  3. as_[variant]_mut: Like as_[variant] but returns a mutable reference.
  4. into_[variant]: Like as_[variant] but consumes the value and returns an owned value instead of a reference.
  5. extract_as_[variant]: Calls as_[variant] and returns the data or panics if there was an error.
  6. extract_as_[variant]_mut: Calls as_[variant]_mut and returns the data or panics if there was an error.
  7. extract_into_[variant]: Calls into_[variant] and returns the data or panics if there was an error.

Notes on the extract functions

These functions are slightly different from calling as_[variant]().unwrap() because they panic with the Display output of EnumExtractError rather than the Debug output.

Since these functions can panic they are not recommended for production code. Their main use is in tests, in which they can simplify and flatten tests significantly.

Examples

Unit Variants

Check if the variant is the expected variant:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum UnitVariants {
    One,
    Two,
}

let unit = UnitVariants::One;
assert!(unit.is_one());
assert!(!unit.is_two());

Unnamed Variants

Check if the variant is the expected variant:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum UnnamedVariants {
    One(u32),
    Two(u32, i32),
}

let unnamed = UnnamedVariants::One(1);
assert!(unnamed.is_one());
assert!(!unnamed.is_two());

Get the variant’s value:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum UnnamedVariants {
    One(u32),
    Two(u32, i32),
}

fn main() -> Result<(), enum_extract_error::EnumExtractError> {
    let mut unnamed = UnnamedVariants::One(1);

    // returns a reference to the value
    let one = unnamed.as_one()?;
    assert_eq!(*one, 1);

    // returns a mutable reference to the value
    let one = unnamed.as_one_mut()?;
    assert_eq!(*one, 1);

    // returns the value by consuming the enum
    let one = unnamed.into_one()?;
    assert_eq!(one, 1);

    Ok(())
}

If the variant has multiple values, a tuple will be returned:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum UnnamedVariants {
    One(u32),
    Two(u32, i32),
}

fn main() -> Result<(), enum_extract_error::EnumExtractError> {
    let mut unnamed = UnnamedVariants::Two(1, 2);

    // returns a reference to the value
    let two = unnamed.as_two()?;
    assert_eq!(two, (&1, &2));

    // returns a mutable reference to the value
    let two = unnamed.as_two_mut()?;
    assert_eq!(two, (&mut 1, &mut 2));

    // returns the value by consuming the enum
    let two = unnamed.into_two()?;
    assert_eq!(two, (1, 2));

    Ok(())
}

Extract variants of all of the above methods will panic with a decent message if the variant is not the expected variant. Very useful for testing, but not recommended for production code.

See the enum-extract-error crate for more information on the error type.

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum UnnamedVariants {
    One(u32),
    Two(u32, i32),
}

let mut unnamed = UnnamedVariants::One(1);

// returns a reference to the value
let one = unnamed.extract_as_one();
assert_eq!(*one, 1);

// returns a mutable reference to the value
let one = unnamed.extract_as_one_mut();
assert_eq!(*one, 1);

// returns the value by consuming the enum
let one = unnamed.extract_into_one();
assert_eq!(one, 1);
use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum UnnamedVariants {
    One(u32),
    Two(u32, i32),
}

let unnamed = UnnamedVariants::One(1);

// panics with a decent message
let one = unnamed.extract_as_two();

Named Variants

Check if the variant is the expected variant:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum NamedVariants {
    One {
        first: u32
    },
    Two {
        first: u32,
        second: i32
    },
}

let named = NamedVariants::One { first: 1 };
assert!(named.is_one());
assert!(!named.is_two());

Get the variant’s value:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum NamedVariants {
    One {
        first: u32
    },
    Two {
        first: u32,
        second: i32
    },
}

fn main() -> Result<(), enum_extract_error::EnumExtractError> {
    let mut named = NamedVariants::One { first: 1 };

    // returns a reference to the value
    let one = named.as_one()?;
    assert_eq!(*one, 1);

    // returns a mutable reference to the value
    let one = named.as_one_mut()?;
    assert_eq!(*one, 1);

    // returns the value by consuming the enum
    let one = named.into_one()?;
    assert_eq!(one, 1);

    Ok(())
}

If the variant has multiple values, a tuple will be returned:

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum NamedVariants {
    One {
        first: u32
    },
    Two {
        first: u32,
        second: i32
    },
}

fn main() -> Result<(), enum_extract_error::EnumExtractError> {
    let mut unnamed = NamedVariants::Two { first: 1, second: 2 };

    // returns a reference to the value
    let two = unnamed.as_two()?;
    assert_eq!(two, (&1, &2));

    // returns a mutable reference to the value
    let two = unnamed.as_two_mut()?;
    assert_eq!(two, (&mut 1, &mut 2));

    // returns the value by consuming the enum
    let two = unnamed.into_two()?;
    assert_eq!(two, (1, 2));

    Ok(())
}

Extract variants of all of the above methods will panic with a decent message if the variant is not the expected variant. Very useful for testing, but not recommended for production code.

See the enum-extract-error crate for more information on the error type.

use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum NamedVariants {
    One {
        first: u32
    },
    Two {
        first: u32,
        second: i32
    },
}

let mut named = NamedVariants::One { first: 1 };

// returns a reference to the value
let one = named.extract_as_one();
assert_eq!(*one, 1);

// returns a mutable reference to the value
let one = named.extract_as_one_mut();
assert_eq!(*one, 1);

// returns the value by consuming the enum
let one = named.extract_into_one();
assert_eq!(one, 1);
use enum_extract_macro::EnumExtract;

#[derive(Debug, EnumExtract)]
enum NamedVariants {
    One {
        first: u32
    },
    Two {
        first: u32,
        second: i32
    },
}

let named = NamedVariants::One { first: 1 };

// panics with a decent message
let one = named.extract_as_two();

Derive Macros

  • Derive functions on an Enum for easily accessing individual items in the Enum