#Get random enum until it has the correct type. Comparing enum to generic.

19 messages · Page 1 of 1 (latest)

rugged mica
#

Not sure what to put in the title. My example code looks like this:

use rand::Rng;
use serde::Deserialize;
use serde_json::json;

#[derive(Deserialize, Debug)]
#[serde(tag = "id")]
enum FooBar {
    #[serde(rename = "1")]
    Foo(Foo),
    #[serde(rename = "2")]
    Bar(Bar),
}

#[derive(Deserialize, Debug, PartialEq)]
struct Foo {
    foo: String,
}

#[derive(Deserialize, Debug, PartialEq)]
struct Bar {
    bar: String,
}

// Returns message with random id
fn read() -> FooBar {
    let messages = [
      json!({"id":"1","foo":"Foo"}),
      json!({"id":"2","bar":"Bar"}),
    ];
    let mut rng = rand::thread_rng();
    let number: usize = rng.gen_range(0..2);
    let random_message = messages.get(number).unwrap().clone();
    serde_json::from_value::<FooBar>(random_message).unwrap()
}

// Should call read() until it gets a message of type T and return it
fn wait<T>() -> T {
    loop {
        let _message: FooBar = read();
        todo!("If message is the type of T, return it.")
    }
}

fn main() {
    let foo_or_bar = read();
    println!("Foo or Bar: {:?}", foo_or_bar);

    let foo: Foo = wait();
    println!("Foo: {:?}", foo.foo);

    let bar: Bar = wait();
    println!("Foo: {:?}", bar.bar);
}

read currently returns one of the two messages as FooBar, which works fine. Now I want wait to call read until it returns the correct message depending on the generic. Is something like that possible?

#

Foo and Bar are different structs because I want to implement different functions for them later on, in case anyone is wondering.

queen ginkgo
#

you can't check the type of a generic, but you can implement a trait for both

chrome meadow
#

maybe an enum is what you want here

#

can you not match on it?

rugged mica
rugged mica
queen ginkgo
#

i don't fully understand your criteria for what's the correct message

#

the way the trait would look depends on what behavior you want both types to share

#

i don't fully understand the goal... but if you want a short example to get the string

trait InnerString {
    fn inner(&self) -> String;
}

impl InnerString for Foo {
    fn inner(&self) -> String {
        self.foo.clone()
    }
}
rugged mica
#

let foo: Foo = wait(); should call read() until it returns an enum of type Foo.
let bar: Bar = wait(); should call read() until it returns an enum of type Bar.

#

In reality foo and bar could contain totally different content and functions

chrome meadow
#

what about rust impl TryFrom<FooBar> for Foo { type Error = (); fn try_from(fb: FooBar) -> Result<Self, ()> { match fb { FooBar::Foo(f) => Ok(f), _ => Err(()), } } }

#

then you can write ```rust
fn wait<T>() -> T {
loop{
if let Ok(item) = T::try_from(read()){
//..
}

}

}```

#

(it will need a bound on T)

queen ginkgo
#

Ok(item), but yes, that

chrome meadow
#

you can invent your own trait if Tryfrom fits poorly

rugged mica
#

Yes, that works! Thanks!

chrome meadow
#

Also, consider something where you return the foobar if it didn't match