Pascal
Pascal

Reputation: 2174

Generic return type in function defined by caller

I need to write some Environment getters in rust

#[allow(non_camel_case_types)]
pub enum ENV {
    TEST_1,
    TEST_2,
}

impl ENV {
    pub fn as_str(&self) -> &'static str {
        match *self {
            ENV::TEST_1 => "TEST_1",
            ENV::TEST_2 => "TEST_2",
        }
    }
}

pub fn var<T: Into<String>>(key: ENV, def: T) -> String {
    return std::env::var(key.as_str()).unwrap_or(def.into());
}

pub fn var_int<T: Into<u16>>(key: ENV, def: T) -> u16 {
    return std::env::var(key.as_str())
        .map(|v| v.parse::<u16>().ok())
        .unwrap_or(None)
        .unwrap_or(def.into());
}

Now I do not want to write getters for u32 u16 ... is there anything working with generics to let the caller define the type?

let port: u16 = var(ENV::TEST_1, 80);

Upvotes: 0

Views: 134

Answers (1)

Masklinn
Masklinn

Reputation: 42572

Now I do not want to write getters for u32, u16 ... is there anything working with generics to let the caller define the type?

You can infer that there is from str::parse which can return different types parsed from strings based on the caller's decision. So all you need to do is work from there: parse works based on FromStr, so instead of a hardcoded output you need one bound to FromStr, and your default needs to be convertible to that as well. Then it's just jiggling around to get something working:

pub fn var_int<Q: FromStr, T: Into<Q>>(key: ENV, def: T) -> Q {
    std::env::var(key.as_str()).ok()
        .and_then(|v| v.parse::<Q>().ok())
        .unwrap_or_else(|| def.into())
}

Upvotes: 2

Related Questions