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();
}
  • I_like_cats@lemmy.one
    link
    fedilink
    arrow-up
    10
    ·
    1 year ago

    No. You can only return a single type from the function. You could return the serde_json::Value though so that the code calling this function can get the value it needs itself

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

      Afraid this might have been the case, if Ogeon’s suggestion doesn’t work out, I’ll probably end up with multiple getters, one per type. There aren’t that many anyway

      Thank you!

  • 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!

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

    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();
    }