Is it possible to await a future inside a result without a match statement?

305 views Asked by At

I have the following implementation block which isn't very readable.

impl Xbee {
    async fn new(xbee_ip: Ipv4Addr) -> Result<Self, std::io::Error> {
        match tokio::net::UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).await
            .map(|socket| async {
                match socket.connect((xbee_ip, 3054)).await {
                    Ok(_) => Ok(Xbee {
                        ip: xbee_ip,
                        socket: socket,
                        last_seen: SystemTime::now(),
                    }),
                    Err(error) => Err(error)
                }
            }) {
                Ok(xbee) => xbee.await,
                Err(err) => Err(err),
        }
    }
}

As a start, I would like to remove the outermost match statement which is just there to await the future inside a result before putting it back into a result. It seems like this would be a good candidate for Result::{and_then, map, map_or, map_or_else} etc., however, I don't think any of these will work since the await would end up being inside an async closure which in turn, would need to be awaited. Is it possible to await the future inside a result without a match statement?

1

There are 1 answers

3
mallwright On

This does not answer the question above, however, by using the ? operator correctly, it is possible to make the above code much more readable by not having the future inside the result in the first place. Refactored code:

impl Xbee {
    async fn new(xbee_ip: Ipv4Addr) -> Result<Self, std::io::Error> {
        let socket = tokio::net::UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).await?;
        socket.connect((xbee_ip, 3054)).await?;
        let xbee = Xbee {
            ip: xbee_ip,
            socket: socket,
            last_seen: SystemTime::now(),
        };
        Ok(xbee)
    }
}