Crate try_as

source ·
Expand description

Macros and traits to ease using enums whose sole purpose is to enumerate a set of types.

It exports a set of traits that help to this end:

And a set of macros that derive implementations from these and some standard traits, namely:

To derive the traits for an enum, the enum has to have the following shape:

  • Each variant must have exactly one unnamed parameter
  • Each variant argument type must appear at most once

See also:

Example

Assume we have an enum that enumerates values of i64, String and bool:

enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

And we want to convert between this enum and values of types i64, String and bool. This crate exposes the following macros to ease this conversion:

use try_as::macros;

#[derive(macros::From, macros::TryInto, Debug)]
enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

// Convert to `Value` from `i64`, `String` or `bool` using `into`/`from`:
let x = Value::from(0);
let name = Value::from("Hello".to_owned());
let yes_or_no: Value = false.into();

// Convert back with `try_into`
let maybe_i64: Result<i64, _> = x.try_into();
assert_eq!(maybe_i64.unwrap(), 0);
let maybe_i64: Result<i64, Value> = name.try_into();
assert!(maybe_i64.is_err());

If we only need a reference to the value, we can use the macros TryAsRef and TryAsMut, which derive implementations for the new traits traits::TryAsRef and traits::TryAsMut, respectively:

use try_as::{
    traits::{TryAsRef, TryAsMut},
    macros,
};

#[derive(macros::TryAsRef, macros::TryAsMut)]
enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

let mut x = Value::Number(0);

let x_ref: &i64 = x.try_as_ref().unwrap();
assert_eq!(*x_ref, 0);

let x_mut: &mut i64 = x.try_as_mut().unwrap();
*x_mut = 4;

let x_ref: &i64 = x.try_as_ref().unwrap();
assert_eq!(*x_ref, 4);

let str_ref: Option<&String> = x.try_as_ref();
assert!(str_ref.is_none());

Finally, to inspect the type, we can use the trait traits::TypedContainer, which allows us to look at the std::any::TypeId of the contained type:

use try_as::{
    traits::TypedContainer,
    macros
};

#[derive(macros::TypedContainer)]
enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

let x = Value::Number(0);
let boolean: Value = Value::Bool(false);
assert!(x.holds::<i64>());
assert!(!boolean.holds::<i64>());
assert!(std::any::TypeId::of::<bool>() == boolean.type_id());

Re-exports

pub extern crate try_as_macros as macros;
pub extern crate try_as_traits as traits;