Background: I have a large serde_json value that I want to be read-only (the authoritative source is an encrypted SQLite DB and should only be updated when that gets updated)

The issue, I would like a single get function that returns a generic type

use serde_json;

pub struct Configuration {
    config: serde_json::Value,
}

impl Configuration {
    async fn get(&self, key: &str) -> Result {
        let tmp_value: = &self.config["test"];

        // This would be repeated for String, bool, etc
        if tmp_value.is_i64() {
            match tmp_value.as_i64 {
                Some(x) => Ok(x),
                Err(e) => Err(()),
            }
        } else {
            Err(())
        }
    }
}

However I get: “mismatched types expected type parameter T found type i64”

Is it even possible to return multiple types from a single function?

EDIT: SOLUTION

Here is the solution I came up with:

pub struct Configuration {}

impl Configuration {
    fn get std::str::FromStr>() -> Result {
        Ok(T::from_str("1234");
    }
}

fn main() {
    let my_conf_val = Configuration::get();
}
  • Ogeon@programming.dev
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    1 year ago

    It may be possible to use the Any trait to “launder” the value by first casting it to &Any and then downcasting it to the generic type.

    let any_value = match tmp_value {
        serde_json::Value::Number(x) => x as &Any,
        // ...
    };
    
    let maybe_value = any_value.downcast_ref::< T >();
    

    I haven’t tested it, so I may have missed something.

    Edit: to be clear, this will not actually let you return multiple types, but let the caller decide which type to expect. I assumed this was your goal.

    • wulf@lemmy.worldOP
      link
      fedilink
      arrow-up
      2
      ·
      1 year ago

      Correct, I would want the caller to know what they’re getting, I’ll see if this works, Thank you!