Optional function argument that is specified as a trait instead of a concrete type

663 views Asked by At

I have been watching Rust for the past few months but I just started into an actual project. I am not sure if the terminology in the title is correct. Please let me know how it can be corrected.

I am writing a rust wrapper around the ENet library (http://enet.bespin.org). My goal is to keep the rust API as similar to the C API as possible except to refactor functions that take C style handle pointers into member functions of structure objects. I want to keep the API similar so that the official C documentation will apply equally well to the rust wrapper.

ENet exposes a single function to create either a client host or a server host. When creating a server you pass a pointer to an IP Address structure to the function. When creating a client you pass NULL.

I am trying to emulate that behavior using the ToSocketAddr trait and Option but I am running into problems using them in conjunction.

This is a reduced example of what I am trying to do:

use std::io::net::ip::ToSocketAddr;

fn create_host<A: ToSocketAddr>(addr: Option<A>) {
    match addr {
        Some(a) => println!("Address is {}. Return a server host object.",a.to_socket_addr()),
        None    => println!("no address... Return a client.")
    };
}


fn main() {
    create_host(Some("localhost:12345"));
    create_host(None);
}

The first call to create_host() works like a charm. The second call however will not compile.

Rustc returns

error: unable to infer enough type information about `_`; type annotations required

I am guessing that error is occurring because None doesn't provide any resolution to the generic A. I tried the following but this doesn't work either because ToSocketAddr does not implement the trait core::kinds::Sized.

fn create_host(addr: Option<ToSocketAddr>) {
    ...
}

Is there a way I can do this or do I need to take a different approach?

1

There are 1 answers

3
Francis Gagné On BEST ANSWER
fn main() {
    create_host(Some("localhost:12345"));
    create_host(None::<&str>);
}

I've chosen &str here as it is the same type as on the first call, so that the compiler wouldn't generate another monomorphized version of the generic function. You could choose any type that implements ToSocketAddr.