I'm trying to make a rust codegen frontend for swagger, and I'm stuck at polishing the generated API.
Swagger API calls require a configuration
, which is, basically a URL basePath
and a http client (using hyper.rs there). Everything works just fine as long as my api looks like:
pub fn add_pet<C: hyper::client::Connect>(
prefix: &str,
cli: &hyper::client::Client<C>,
pet: &models::Pet,
) -> Box<Future<Item = (), Error = Error>>
all api calls are functions and you pass in the configuration explicitly. Now, on the consumer side, that sucks. What I want to have is something like:
let api = apis::Client::new(
apis::Configuration::new(
Client::configure().connector(http_connector).build(&handle)));
let work = api.pet_api().add_pet(&new_pet)
For that I have this semi-working code:
pub struct Configuration<C: hyper::client::Connect> {
pub base_path: String,
pub client: hyper::client::Client<C>,
}
pub trait PetAPI {
fn add_pet(&self, pet: &models::Pet) -> Box<Future<Item = (), Error = Error>>;
}
pub struct PetAPIImpl<'a, C: hyper::client::Connect> {
configuration: &'a configuration::Configuration<C>
// api implementation needs to access the configuration implicitly to keep the ags list clean
}
pub struct APIClient<C: hyper::client::Connect> {
configuration: Configuration<C>,
pet_api: Box<pet_api::PetAPI>, // preferably shouldn't be box-ed somehow
// it's a trait to allow for easier mocking.
}
impl<C: hyper::client::Connect> APIClient<C> {
pub fn new(configuration: Configuration<C>) -> APIClient<C> {
let cli = APIClient {
configuration: configuration,
pet_api: Box::new(pet_api::PetAPIImpl::new(&cli.configuration))
// doesn't work at all, how do I pass in the cli's configuration in there?
};
cli
}
How do I solve the circular-reference on Configuration without RefCell? It that at all possible given there is a strong guarantee that pet_api will not outlive the client?