I've found cases where `MediaType::toString` generates erroneous results.

One case is when the `MediaType` instance has a parameter of an empty value. This can happen when calling `withParameter("foo", "")`, or parsing `text/plain; foo=""`. When the parameters are later joined, the value is erroneously matched as a token instead of being quoted (as tokens cannot be empty). This will lead the following to throw `IllegalArgumentException`: 
```java
MediaType type1 = MediaType.parse("text/plain; foo=\"\"");
MediaType type2 = MediaType.parse(type1.toString()); // Trying to parse 'text/plain; foo=' will fail
```
 I think [this line](https://github.com/google/guava/blob/5a8f19bd3556012ed9e65cd4268a85ddde95733f/guava/src/com/google/common/net/MediaType.java#L1091) should first check if the string is empty before matching against `TOKEN_MATCHER`, or maybe just return the literal `"\"\""` on that case to avoid the `StringBuilder` allocation.

Another case is when parameters are set explicitly using `withParameter[s](...)`, where parameter value[s] contain non-ASCII characters. For example this will also throw `IllegalArgumentException`:
```java
MediaType type1 = MediaType.create("text", "plain").withParameter("let_me_in!", "\"جوافة\"");
MediaType type2 = MediaType.parse(type1.toString()); // The tokenizer will fail to consume QUOTED_TEXT_MATCHER
```
I don't know whether this is the intended behaviour or not but `MediaType::toString` can be used in HTTP header values which shouldn't contain non-ASCII octets. IMHO `normalizeParameterValue(...)` should validate the value against the `ascii()` matcher.
* ByteArrayOutputStream}. The given output stream is not reset before being written to by the
   * returned {@code ByteArrayDataOutput} and new data will be appended to any existing content.
   *
   * <p>Note that if the given output stream was not empty or is modified after the {@code
   * ByteArrayDataOutput} is created, the contract for {@link ByteArrayDataOutput#toByteArray} will
   * not be honored (the bytes returned in the byte array may not be exactly what was written via
   * calls to {@code ByteArrayDataOutput}).
   *
   * @since 17.0
   */
  @Beta
  public static ByteArrayDataOutput newDataOutput(ByteArrayOutputStream byteArrayOutputStream) {
    return new ByteArrayDataOutputStream(checkNotNull(byteArrayOutputStream));
  }
  private static class ByteArrayDataOutputStream implements ByteArrayDataOutput {
    final DataOutput output;
    final ByteArrayOutputStream byteArrayOutputStream;
    ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
      this.byteArrayOutputStream = byteArrayOutputStream;
      output = new DataOutputStream(byteArrayOutputStream);
    }
    @Override
    public void write(int b) {
      try {
        output.write(b);
      } catch (IOException impossible) {
        throw new AssertionError(impossible);
      }
    }
    @Override