/**
   * Called by transport implementations when they receive headers.
   *
   * @param headers the parsed headers
   */
  protected void inboundHeadersReceived(Metadata headers) {
    if (headers.containsKey(GrpcUtil.MESSAGE_ENCODING_KEY)) {
      String messageEncoding = headers.get(GrpcUtil.MESSAGE_ENCODING_KEY);
      try {
        setDecompressor(messageEncoding);
      } catch (IllegalArgumentException e) {
        Status status =
            Status.INVALID_ARGUMENT
                .withDescription("Unable to decompress encoding " + messageEncoding)
                .withCause(e);
        abortStream(status, true);
        return;
      }
    }
    // This checks to see if the client will accept any encoding.  If so, a compressor is picked for
    // the stream, and the decision is recorded.  When the Server Call Handler writes the first
    // headers, the negotiated encoding will be added in #writeHeaders().  It is safe to call
    // pickCompressor multiple times before the headers have been written to the wire, though in
    // practice this should never happen.  There should only be one call to inboundHeadersReceived.

    // Alternatively, compression could be negotiated after the server handler is invoked, but that
    // would mean the inbound header would have to be stored until the first #writeHeaders call.
    if (headers.containsKey(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY)) {
      Compressor c =
          pickCompressor(
              ACCEPT_ENCODING_SPLITER.split(headers.get(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY)));
      if (c != null) {
        messageEncoding = c.getMessageEncoding();
      }
    }

    inboundPhase(Phase.MESSAGE);
  }
  @Test
  public void prepareHeaders_acceptedEncodingsAdded() {
    Metadata m = new Metadata();
    DecompressorRegistry customRegistry =
        DecompressorRegistry.emptyInstance()
            .with(
                new Decompressor() {
                  @Override
                  public String getMessageEncoding() {
                    return "a";
                  }

                  @Override
                  public InputStream decompress(InputStream is) throws IOException {
                    return null;
                  }
                },
                true)
            .with(
                new Decompressor() {
                  @Override
                  public String getMessageEncoding() {
                    return "b";
                  }

                  @Override
                  public InputStream decompress(InputStream is) throws IOException {
                    return null;
                  }
                },
                true)
            .with(
                new Decompressor() {
                  @Override
                  public String getMessageEncoding() {
                    return "c";
                  }

                  @Override
                  public InputStream decompress(InputStream is) throws IOException {
                    return null;
                  }
                },
                false); // not advertised

    ClientCallImpl.prepareHeaders(m, customRegistry, Codec.Identity.NONE);

    Iterable<String> acceptedEncodings =
        ACCEPT_ENCODING_SPLITER.split(m.get(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY));

    // Order may be different, since decoder priorities have not yet been implemented.
    assertEquals(ImmutableSet.of("b", "a"), ImmutableSet.copyOf(acceptedEncodings));
  }