class SendAsyncUtils {

  private SendAsyncUtils() {
    // just utils
  }

  static CompletableFuture<HttpResponse<Reader>> reader(HttpRequest request, HttpClient client) {
    return inputStream(request, client)
        .thenApply(res -> new HttpResponseAdapter<>(res, new InputStreamReader(res.body(), StandardCharsets.UTF_8)));
  }

  static CompletableFuture<HttpResponse<InputStream>> inputStream(HttpRequest request, HttpClient client) {<FILL_FUNCTION_BODY>}

  static CompletableFuture<HttpResponse<byte[]>> bytes(HttpRequest request, HttpClient client) {
    ByteArrayBodyHandler byteArrayBodyHandler = new ByteArrayBodyHandler();
    CompletableFuture<HttpResponse<AsyncBody>> futureResponse = client.consumeBytes(request, byteArrayBodyHandler);
    return futureResponse.thenCompose(res -> {
      byteArrayBodyHandler.onResponse(res);
      return byteArrayBodyHandler.getResult()
          .thenApply(b -> new HttpResponseAdapter<>(res, b));
    });
  }

  static CompletableFuture<HttpResponse<String>> string(HttpRequest request, HttpClient client) {
    return bytes(request, client)
        .thenApply(res -> new HttpResponseAdapter<>(res, new String(res.body(), StandardCharsets.UTF_8)));
  }

}

    HttpClientReadableByteChannel byteChannel = new HttpClientReadableByteChannel();
    CompletableFuture<HttpResponse<AsyncBody>> futureResponse = client.consumeBytes(request, byteChannel);
    return futureResponse.thenApply(res -> {
      byteChannel.onResponse(res);
      return new HttpResponseAdapter<>(res, Channels.newInputStream(byteChannel));
    });
  
<no_super_class>