0

Given enum values implement the same trait, is it possible to extract trait object from enum value?

Form the doc example:

fn main() {
    enum IpAddr {
        V4(String),
        V6(String),
    }

    let home = IpAddr::V4(String::from("127.0.0.1"));

    let loopback = IpAddr::V6(String::from("::1"));
}

Here all the enum values hold a String, is it possible to extract it without enumerating all the options with match?

Something like:

   let result = factory.get_enum(); // -> IpAddr
   let str: String = (some_cast)result.getValue();

I'd like to avoid:

    match result {
       Product1(product1) => {},
       ...
       ProductN(productN) => {}
    } 

And more complicated case: let's say all the enum values hold a trait object:

trait TProduct {
   fn something();
}

impl TProduct for Product1 {}
...
impl TProduct for ProductN {}

enum ProductResult {
  product1(Product1),
  ..
  productN(ProductN)
}

...

let result: ProductResult = factory.build();
let product = result.getValue() as dyn TProduct; // is it possible with Rust?
let something = product.something();

4ntoine
  • 19,816
  • 21
  • 96
  • 220
  • Does this answer your question? [Read from an enum without pattern matching](https://stackoverflow.com/questions/45473656/read-from-an-enum-without-pattern-matching) Or perhaps this? [Converting an enum where all variants implement the same trait to a box in Rust?](https://stackoverflow.com/questions/54056660/converting-an-enum-where-all-variants-implement-the-same-trait-to-a-box-in-rust) – kmdreko Feb 02 '21 at 08:37
  • Implement such method for `IpAddr` or `ProductResult` and use the method. Or use a crate that implemented it for you (see links given by kmdreko) – Alexey S. Larionov Feb 02 '21 at 08:44
  • Does it meat `match` will be just inside of `IpAddr.something()`? With "enum_dispatch: create it seems to be conceptually the same, but just without manual typing. – 4ntoine Feb 02 '21 at 09:02
  • 3
    I think the answer to the titular question is just "no". The idea behind enum is that it contains *different* values with different types and meanings. If you really have a value that is common in type and meaning, you should use a `struct` instead and make it a field: `enum AddrType { V4, V6 }; struct IPAddr { type: AddrType, raw_addr: String }`. – user4815162342 Feb 02 '21 at 10:02
  • fair enough. However keeping it in the same structure can be undesired/impossible if it's different trait objects with different fieldsset – 4ntoine Feb 02 '21 at 10:19
  • If all your enum variants implement the same trait, consider using a trait object like `Box` instead of the enum. – Sven Marnach Feb 02 '21 at 12:40
  • @SvenMarnach that's the original problem - how to cast it to concrete trait impl later (without using `as_any` trick)? – 4ntoine Feb 02 '21 at 12:41
  • Are you referring to mplementing an `as_any()` method on the trait? That's a common solution for downcasting trait objects. Why are you ruling it out? Another solution is the [downcast_rs crate](https://docs.rs/downcast-rs/1.2.0/downcast_rs/). – Sven Marnach Feb 02 '21 at 12:57
  • @SvenMarnach I can be wrong but i had a feeling that `as_any` is not a Rust canonical way but rather a trick. Thanks for suggesting `downcast_rs` crate – 4ntoine Feb 03 '21 at 08:37
  • I'm not sure it's the "canonical" way, but it's definitely a perfectly fine approach, and there is nothing wrong with it. The `downcast_rs` crate does the same – it's just a bit more convenient. – Sven Marnach Feb 03 '21 at 15:24

0 Answers0