#[derive(ConstEach)]
{
// Attributes available to this derive:
#[value]
#[armtype]
}
Expand description
Add’s constants of any type to each arm of an enum
To get the value, the type must be explicitly passed
as a generic to [<enum_name>::value
]. This will automatically
try to convert constant to the expected type using std::any::Any
and [downcast_ref
]. Currently TryFrom
is not supported, so typing
is fairly strict. Upon failure, it will return None
.
- To get the value as a reference, call the function [
<enum_name>::value
] - Unlike
Const
, this macro does not enable direct comparison usingPartialEq
when imported using theeq
feature.
The #[armtype = ...]
attribute is NOT* required for this macro to function,
but *CAN be applied to each individual arm of the enum, since values
are not expected to share a type. If no type is given, then the type is
inferred from the literal value in the #[value = ...]
attribute.
All values set will return a [Option<&'static T>
] reference. To the input type,
of [T
] AND [&T
]. If multiple references are used (e.g. &&T
), then
the return type will be [Option<&'static &T>
].
§Example
use thisenum::ConstEach;
#[derive(ConstEach, Debug)]
enum MyEnum {
#[armtype(u8)]
#[value = 0xAA]
A,
#[value = "test3"]
B,
}
#[derive(ConstEach, Debug)]
enum Tags {
#[value = b"\x00\x01"]
Key,
#[armtype(u16)]
#[value = 24250]
Length,
#[armtype(&[u8])]
#[value = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"]
Data,
}
fn main() {
// [`ConstEach`] examples
assert!(MyEnum::A.value::<u8>().is_some());
assert!(MyEnum::A.value::<Vec<f32>>().is_none());
assert!(MyEnum::B.value::<u8>().is_none());
assert!(MyEnum::B.value::<&str>().is_some());
assert!(Tags::Data.value::<&[u8]>().is_some());
// An infered type. This will be as strict as possible,
// therefore [`&[u8]`] will fail but [`&[u8; 2]`] will succeed
assert!(Tags::Key.value::<&[u8; 2]>().is_some());
assert!(Tags::Key.value::<&[u8; 5]>().is_none());
assert!(Tags::Key.value::<&[u8]>().is_none());
assert!(u16::from_le_bytes(**Tags::Key.value::<&[u8; 2]>().unwrap()) == 0x0100);
// casting as anything other than the defined / inferred type will
// fail, since this uses [`downcast_ref`] from [`std::any::Any`]
assert!(Tags::Length.value::<u16>().is_some());
assert!(Tags::Length.value::<u32>().is_none());
assert!(Tags::Length.value::<u64>().is_none());
// however, can always convert to a different type
// after value is successfully acquired
assert!(*Tags::Length.value::<u16>().unwrap() as u32 == 24250);
}