This `FromStr` impl feels clunky, is there a better way to write it?

⚓ Rust    📅 2025-09-14    👤 surdeus    👁️ 1      

surdeus

I don't love this FromStr implementation. It feels non-uniform -- the same basic job of considering one possible parse after another is being done three different ways -- and potentially awkward to extend. How would you write it?

(I sort of want a anti-? operator here, that returns early if the result is Ok.)

const DNS_PORT: u16 = 53;

/// A parsed command line argument specifying one or more DNS
/// resolvers to use.
#[derive(Debug, Eq, PartialEq)]
enum ResolverArg {
    System,
    Quad9,
    Ip(SocketAddr),
}

impl FromStr for ResolverArg {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(match s {
            "system" => Self::System,
            "quad9" => Self::Quad9,
            other => if let Ok(addr) = other.parse::<IpAddr>() {
                Ip(SocketAddr::new(addr, DNS_PORT))
            } else {
                Ip(other.parse::<SocketAddr>()?)
            }
        })
    }
}

(N.B. The full program has several more keyword alternatives in the match statement.)

6 posts - 5 participants

Read full topic

🏷️ Rust_feed