This is an unpublished version (with bugs) forked from enum_delegate (revision f99967517e925f9630735836fb1601747df9c71d
).
The original authors are Reinis Mazeiks, 50U10FCA7. This crate is to resolve dependency conflicts in another crate concurrent_tor
. Since that crate depends on enum_delegate ^= "0.3.0"
,
this is a temporary upload of enum_delegate
.
Provides trait delegation functionality for enums and structs.
Note: Name contains enum_*
part due to historical reasons. It is not limited to enums.
toml
[dependencies]
enum_delegate = "0.4"
```rust use enum_delegate::delegate;
trait AsStr { fn as_str(&self) -> &str; }
impl AsStr for String { fn as_str(&self) -> &str { self } }
struct FirstName(String);
struct LastName { name: String, }
enum Name { First(FirstName), Last(LastName), }
fn main() { let name = Name::First(FirstName("John".tostring())); asserteq!(name.as_str(), "John");
let name = Name::Last(LastName {
name: "Doe".to_string(),
});
assert_eq!(name.as_str(), "Doe");
} ```
Crate provides several definitions:
- delegate
macro - derives trait on a new-type struct or enum, invoking it on its inner type.
- Convert
trait - converts enum or struct to type represents "any of its variant".
#[delegate]
expansion on typeImplements Convert
trait to enum/struct, which allows to convert it to "any of its variant" type.
```rust,ignore
enum Name { First(FirstName), Last { name: LastName, }, } ```
Note: Example is simplified for readability.
```rust,ignore
impl Convert for Name {
type Output = Either
fn convert(self) -> Self::Output {
match self {
Name::First(first_name) => Either::Left(first_name),
Name::Last { name } => Either::Right(name),
}
}
} ```
#[delegate]
expansion on traitImplements the trait for any type that implements Convert
trait, which "any variant" implements target trait.
I.e. each method in generated impl
convert self
to "any of its variant" and invokes target trait method on it.
```rust,ignore
trait AsStr { fn as_str(&self) -> &str; } ```
Note: Example is simplified for readability.
```rust,ignore
// Implementation for "any variant of enum or struct" type.
impl
// Implementation for any type that implements Convert
trait.
impl
#[delegate]
macro attribute.Self
trait/method bounds except marker traits like Sized
, Send
or Sync
are not supported yet.#[delegate(for(Enum<Generics>))]
supports only concrete generic types.Rust mechanism for dynamic dispatch using trait objects, which adds runtime overhead.
```rust trait AsStr { fn as_str(&self) -> &str; }
impl AsStr for String { fn as_str(&self) -> &str { self } }
struct FirstName(String);
impl AsStr for FirstName { fn as_str(&self) -> &str { &self.0 } }
fn dosomethingwithstring(s: &dyn AsStr) { println!("{}", s.asstr()); }
fn main() { let name = "John".tostring(); dosomethingwithstring(&name);
let name = FirstName(name);
do_something_with_string(&name);
} ```
enum_delegate
was highly inspired by enum_dispatch crate. It provides similar functionality, but has more limitations:
- Supports only enums.
- Using enum_dispatch
between crates is impossible due to limitations of its design.
- Order-dependent macro expansion (in some cases your code fails if items marked with the macro has different order than macro expects).
Derive a method to return a borrowed pointer to the inner value, cast to a trait object, using enum_derive::EnumInnerAsTrait
.
Slower though, more similar to Dynamic dispatch.