Crates.io | nested_enum_utils |
lib.rs | nested_enum_utils |
version | 0.1.0 |
source | src |
created_at | 2024-07-03 16:31:10.365709 |
updated_at | 2024-07-03 16:31:10.365709 |
description | Macros to provide conversions for nested enums |
homepage | |
repository | https://github.com/n0-computer/nested-enum-utils |
max_upload_size | |
id | 1290682 |
size | 31,702 |
This crate provides a single attribute macro to provide conversions from enum cases to the enum itself or to some other type.
It only works with enums where each variant has a single unnamed element, and if each variant has a distinct type.
The most basic use is to provide conversions between the enum cases and the enum type itself. You could achieve something similar with the popular derive_more crate.
#[enum_conversions()]
enum Request {
Get(GetRequest),
Put(PutRequest),
}
A more advanced use, and the reason for this crate to exist, is to provide conversions between enum variants and any type that itself has a conversion to the enum. This allows to use nested enums, like you would in a complex protocol that has several subsystems.
#[enum_conversions(Request)]
enum StoreRequest {
Get(GetRequest),
Put(PutRequest),
}
#[enum_conversions(Request)]
enum NetworkRequest {
Ping(PingRequest),
}
#[enum_conversions()]
enum Request {
Store(StoreRequest),
Network(NetworkRequest),
}
Here we define conversions from GetRequest
to StoreRequest
, from StoreRequest
to Request
, and then directly from GetRequest
to Request
, and corresponding TryFrom conversions in the other direction.
The generated From conversions are straightforward. Obviously it is always possible to convert from an enum case to the enum itself.
We also generate TryFrom conversions from the enum to each variant, as well as from a reference to the enum to a reference to the variant.
The conversions that take a value are different than the ones from derive_more: they return the unmodified input in the error case, allowing to chain conversion attempts.
let request = ...
match GetRequest::try_from(request) {
Ok(get) => // handle get request
Err(request) => {
// I still got the request and can try something else
match PutRequest::try_from(request) {
...
}
}
}
The conversions that take a reference just return a &'static str
as the error type. References are Copy
, so we can always retry anyway.