Unpacking from Result<Box<Any>, Box<Error>> to float32 rust. How to do it?

44 Views Asked by At
struct ExchangeCurrencyRequestsMock {
  base: String,
  to: String,
  amount: f32,
}
use core::any::Any;
use task::api::Requests;
use std::error;
use serde_json::Value;
use serde_json::Map;

type Result<T> = std::result::Result<T, Box<dyn error::Error>>;

impl Requests for ExchangeCurrencyRequestsMock {
    async fn call(&mut self) -> Result<Box<dyn Any>> {
        let data = r#"
            [
              "USD": {
                "USD": "1.0",
                "PLN": "3.96",
                "AUD": "1.52",
                "EUR": "0.92"
              },
              "PLN": {
                "PLN": "1.0"
                "USD": "0.25",
                "AUD": "0.38",
                "EUR": "0.23"
              }
            ]
        "#;
        let resp: Result<Box<serde_json::Value>> = Ok(serde_json::from_str(&data)?);
        match resp {
            Ok(value)  => {
              let obj: Map<String, Value> = value.as_object().unwrap().clone();
              let ratio: f32 = obj[&self.base.to_ascii_uppercase()][self.to.to_ascii_uppercase()].to_string().parse()?;

              return Ok(Box::new(ratio*self.amount))
            },
            Err(_) => {
              let b: Box<dyn error::Error> = "Request got bad".into();

              return Err(b)
            },
        };
    }
}

#[tokio::test]
async fn call() {
      let mut client = ExchangeCurrencyRequestsMock{
        base: "USD".to_string(),
        to: "AUD".to_string(),
        amount: 100.0,
      };
      let result: std::result::Result<Box<dyn Any>, Box<dyn std::error::Error>> = client.call().await;
      assert_eq!(result, 152.0);

}

How to return f32 from client.call ? I should unwrap result to get Box, then * to Box, get Any and downcast it to float32 and assert it. That's how I did, then I deleted it, because It didn't work.

I unwrapped result to get Box, then * to Box, get Any and downcast it to float32 and assert it, yet It didn't work

1

There are 1 best solutions below

6
SparkyPotato On

Looking at the docs for Any, downcast is implemented on Box<dyn Any>, and it returns a Result<Box<T>, Box<dyn Any>>.

So, all we have to do is:

*result.unwrap().downcast::<f32>().unwrap()

This unwraps the original Results, downcasts to f32, then unwraps again (because the dyn Any may not be of type f32), and then moves out of the returned Box<f32>.

However, this sounds like an XY problem due to weird code architecture, perhaps the Requests trait should be changed to make it easier to use?