nested_enum_utils

Crates.ionested_enum_utils
lib.rsnested_enum_utils
version0.1.0
sourcesrc
created_at2024-07-03 16:31:10.365709
updated_at2024-07-03 16:31:10.365709
descriptionMacros to provide conversions for nested enums
homepage
repositoryhttps://github.com/n0-computer/nested-enum-utils
max_upload_size
id1290682
size31,702
RĂ¼diger Klaehn (rklaehn)

documentation

README

Nested enum utils

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.

Generated conversions

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.

Commit count: 3

cargo fmt