Conversion from generic type to some concrete types

code here:

trait TA
{
    fn set<T>(&mut self, field:&str, value:&T);
}

struct A
{
    id: u32,
    name: String
}

impl A
{
    fn new()->Self
    {
        A
        {
            id:0,
            name:String::from("")
        }
    }
}


impl TA for A
{
    fn set<T>(&mut self, field:&str, value:&T)
    {
        if field == "id"
        {
            self.id = *(value as &u32);
        }
        if field == "name"
        {
            self.name = (value as &str).to_string();
        }
    }
}

fn main()
{
    let mut a = A::new();
    // only two possible types u32 and String is ensured
    a.set(&"id", &1);
}

*Playground

Some abstraction of the logic is similar to above the code and it sets the field via the field name(just for example, in fact the code is in proc_macro). For this case, the input value types in set method are ensured but the cast does not work. so is there any way to cast it.
After google, found From and 'Into' trait , but using From to convert type to type self makes no scene.

Rust's generics are not that dynamic. They can't have a relationship between a runtime value like field and a compile-time type like T. If you set field to "name", but passed an integer, the code would be invalid and crash, and Rust won't allow such possibility to exist.

There's Any interface that allows casting types at runtime, but the usual solution is to use an enum

enum Field {
   String(String),
   Number(i32),
}

match field_enum {
   Field::String(s) => self.name = s,
   Field::Number(n) => self.id = n,
}
3 Likes

enum is a good idea, but i think i need something similar to reflection through which field could be setted by its name string. I will look inside serde lib for something.
Thanks again.

If you want to map arbitrary keys to values, you probably want a HashMap<String, …>. Although it's not clear what you are trying to achieve. Chances are there's a better, simpler, more idiomatic way of doing what you want to do, if you tell us your high-level goal.

Is it fair to say, “fixed” to the first type the compiler can infer? In fact, this inference event occurring only once is required in order for the compiler to identify type mismatches when using generics. Yes?

Hmm, if use the HashMap<String, Field>, it could not set the field through the assignment self.name = xxx.
if i store the field's mut reference in HashMap<String, &mut Field> , then it is borrowed, the assignment self.name = xxx could not be done also.
My global is that setting the field through the assignment self.name = xxx and the method obj.set("name", value).

#[inline]
fn set<T: CustomAny>(&mut self, field: &str, val: T) {
   match field {
       "name" => self.name = val.as_string(),
       "id" => self.id = val.as_i32(),
       _ => panic!(),
   }
}


trait CustomAny {
fn as_string(self) -> String;
fn as_i32(self) -> i32;
}

impl CustomAny for String 
#[inline]
fn as_string(self) -> String {self}
fn as_i32(self) -> i32 {panic!()}
}

The cool thing about it is that with a constant for the name it optimizes to code identical to self.name = value.

COOL! I get the idea! Thank you!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.