Skip to content

De-generify client and endpoint codegen? #501

@sfackler

Description

@sfackler

We currently rely on generic type parameters to represent a few things in the codegen for clients and servers:

  • The underlying "raw" HTTP client is a type parameter on the generated client type.
  • For streaming client requests and streaming endpoint responses, the body writer type.
  • For streaming client responses and streaming endpoint requests, the body type.

This has a few disadvantages:

  • For clients, the name gets a bit stutter-steppy: SomeServiceClient<Client>.
  • For endpoints, the parameter bounds will cause methods on the endpoint to not be callable with the standard self.some_method() convention. If there are any endpoints with a streaming response, there will be a type parameter on the trait that's only used as a bound on the associated response type. When making a method call, that parameter won't be specifiable so you either need to fall back to the UFCS syntax: <Self as SomeService>::some_method(self) or add the type parameter to your implementing type via a PhantomData.
  • For streaming requests and responses in both clients and endpoints, the type you get back is oddly underspecified. The standard conversion traits will have Stream<Bytes> or Iterator<Bytes> requirements, and the actual underlying types in witchcraft-server and conjure-runtime have some additional methods to handle trailers.

We could de-generify all of this logic:

  • Add AsyncBody, and AsyncBodyWriter traits to conjure-http. These'll probably need to extend AsyncRead/AsyncWrite and Stream<Bytes>/Sink<Bytes>, and have the extra trailer methods.
  • The AsyncClient trait loses its BodyWriter and ResponseBody associated types in favor of Pin<Box<dyn AsyncBodyWriter>> and Pin<Box<dyn AsyncBody>> trait objects.
  • Generated clients now hold a Box<dyn Client> instead of being parameterized over the client type.
  • Generated endpoints now work with Pin<Box<dyn AsyncBodyWriter>> and Pin<Box<dyn AsyncBody>> trait objects instead of being parameterized.

The equivalent changes would be made to the blocking and local async APIs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions