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:
traits::TryAsRef
- likeAsRef<T>
, but allowed to failtraits::TryAsMut
- likeAsMut<T>
, but allowed to failtraits::TypedContainer
- inspect types of a container
And a set of macros that derive implementations from these and some standard traits, namely:
macros::From
to convert from the types to the enummacros::TryInto
to convert from the enum back into the typesmacros::TryAsMut
to get references of the values of the enummacros::TryAsRef
to get mutable references of the values of the enummacros::TypedContainer
to inspect the type in the enum
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:
- crate
macros
(re-export oftry_as_macros
) - crate
traits
(re-export oftry_as_traits
)
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;