• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc;
18 
19 import static com.google.common.base.Charsets.US_ASCII;
20 import static com.google.common.base.Preconditions.checkArgument;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 
23 import com.google.common.annotations.VisibleForTesting;
24 import com.google.common.base.Preconditions;
25 import com.google.common.io.BaseEncoding;
26 import java.nio.ByteBuffer;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.BitSet;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37 import java.util.NoSuchElementException;
38 import java.util.Set;
39 import javax.annotation.Nullable;
40 import javax.annotation.concurrent.Immutable;
41 import javax.annotation.concurrent.NotThreadSafe;
42 
43 /**
44  * Provides access to read and write metadata values to be exchanged during a call.
45  *
46  * <p>Keys are allowed to be associated with more than one value.
47  *
48  * <p>This class is not thread safe, implementations should ensure that header reads and writes do
49  * not occur in multiple threads concurrently.
50  */
51 @NotThreadSafe
52 public final class Metadata {
53 
54   /**
55    * All binary headers should have this suffix in their names. Vice versa.
56    *
57    * <p>Its value is {@code "-bin"}. An ASCII header's name must not end with this.
58    */
59   public static final String BINARY_HEADER_SUFFIX = "-bin";
60 
61   /**
62    * Simple metadata marshaller that encodes bytes as is.
63    *
64    * <p>This should be used when raw bytes are favored over un-serialized version of object. Can be
65    * helpful in situations where more processing to bytes is needed on application side, avoids
66    * double encoding/decoding.
67    *
68    * <p>Both {@link BinaryMarshaller#toBytes} and {@link BinaryMarshaller#parseBytes} methods do not
69    * return a copy of the byte array. Do _not_ modify the byte arrays of either the arguments or
70    * return values.
71    */
72   public static final BinaryMarshaller<byte[]> BINARY_BYTE_MARSHALLER =
73       new BinaryMarshaller<byte[]>() {
74 
75         @Override
76         public byte[] toBytes(byte[] value) {
77           return value;
78         }
79 
80         @Override
81         public byte[] parseBytes(byte[] serialized) {
82           return serialized;
83         }
84       };
85 
86   /**
87    * Simple metadata marshaller that encodes strings as is.
88    *
89    * <p>This should be used with ASCII strings that only contain the characters listed in the class
90    * comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and
91    * discarded by the transport, or the call may fail.
92    */
93   public static final AsciiMarshaller<String> ASCII_STRING_MARSHALLER =
94       new AsciiMarshaller<String>() {
95 
96         @Override
97         public String toAsciiString(String value) {
98           return value;
99         }
100 
101         @Override
102         public String parseAsciiString(String serialized) {
103           return serialized;
104         }
105       };
106 
107   /**
108    * Constructor called by the transport layer when it receives binary metadata. Metadata will
109    * mutate the passed in array.
110    */
Metadata(byte[]... binaryValues)111   Metadata(byte[]... binaryValues) {
112     this(binaryValues.length / 2, binaryValues);
113   }
114 
115   /**
116    * Constructor called by the transport layer when it receives binary metadata. Metadata will
117    * mutate the passed in array.
118    *
119    * @param usedNames the number of
120    */
Metadata(int usedNames, byte[]... binaryValues)121   Metadata(int usedNames, byte[]... binaryValues) {
122     assert (binaryValues.length & 1) == 0 : "Odd number of key-value pairs " + binaryValues.length;
123     size = usedNames;
124     namesAndValues = binaryValues;
125   }
126 
127   private byte[][] namesAndValues;
128   // The unscaled number of headers present.
129   private int size;
130 
name(int i)131   private byte[] name(int i) {
132     return namesAndValues[i * 2];
133   }
134 
name(int i, byte[] name)135   private void name(int i, byte[] name) {
136     namesAndValues[i * 2] = name;
137   }
138 
value(int i)139   private byte[] value(int i) {
140     return namesAndValues[i * 2 + 1];
141   }
142 
value(int i, byte[] value)143   private void value(int i, byte[] value) {
144     namesAndValues[i * 2 + 1] = value;
145   }
146 
cap()147   private int cap() {
148     return namesAndValues != null ? namesAndValues.length : 0;
149   }
150 
151   // The scaled version of size.
len()152   private int len() {
153     return size * 2;
154   }
155 
isEmpty()156   private boolean isEmpty() {
157     /** checks when {@link #namesAndValues} is null or has no elements */
158     return size == 0;
159   }
160 
161   /** Constructor called by the application layer when it wants to send metadata. */
Metadata()162   public Metadata() {}
163 
164   /** Returns the total number of key-value headers in this metadata, including duplicates. */
headerCount()165   int headerCount() {
166     return size;
167   }
168 
169   /**
170    * Returns true if a value is defined for the given key.
171    *
172    * <p>This is done by linear search, so if it is followed by {@link #get} or {@link #getAll},
173    * prefer calling them directly and checking the return value against {@code null}.
174    */
containsKey(Key<?> key)175   public boolean containsKey(Key<?> key) {
176     for (int i = 0; i < size; i++) {
177       if (bytesEqual(key.asciiName(), name(i))) {
178         return true;
179       }
180     }
181     return false;
182   }
183 
184   /**
185    * Returns the last metadata entry added with the name 'name' parsed as T.
186    *
187    * @return the parsed metadata entry or null if there are none.
188    */
189   @Nullable
get(Key<T> key)190   public <T> T get(Key<T> key) {
191     for (int i = size - 1; i >= 0; i--) {
192       if (bytesEqual(key.asciiName(), name(i))) {
193         return key.parseBytes(value(i));
194       }
195     }
196     return null;
197   }
198 
199   private final class IterableAt<T> implements Iterable<T> {
200     private final Key<T> key;
201     private int startIdx;
202 
IterableAt(Key<T> key, int startIdx)203     private IterableAt(Key<T> key, int startIdx) {
204       this.key = key;
205       this.startIdx = startIdx;
206     }
207 
208     @Override
iterator()209     public Iterator<T> iterator() {
210       return new Iterator<T>() {
211         private boolean hasNext = true;
212         private int idx = startIdx;
213 
214         @Override
215         public boolean hasNext() {
216           if (hasNext) {
217             return true;
218           }
219           for (; idx < size; idx++) {
220             if (bytesEqual(key.asciiName(), name(idx))) {
221               hasNext = true;
222               return hasNext;
223             }
224           }
225           return false;
226         }
227 
228         @Override
229         public T next() {
230           if (hasNext()) {
231             hasNext = false;
232             return key.parseBytes(value(idx++));
233           }
234           throw new NoSuchElementException();
235         }
236 
237         @Override
238         public void remove() {
239           throw new UnsupportedOperationException();
240         }
241       };
242     }
243   }
244 
245   /**
246    * Returns all the metadata entries named 'name', in the order they were received, parsed as T, or
247    * null if there are none. The iterator is not guaranteed to be "live." It may or may not be
248    * accurate if Metadata is mutated.
249    */
250   @Nullable
getAll(final Key<T> key)251   public <T> Iterable<T> getAll(final Key<T> key) {
252     for (int i = 0; i < size; i++) {
253       if (bytesEqual(key.asciiName(), name(i))) {
254         return new IterableAt<T>(key, i);
255       }
256     }
257     return null;
258   }
259 
260   /**
261    * Returns set of all keys in store.
262    *
263    * @return unmodifiable Set of keys
264    */
265   @SuppressWarnings("deprecation") // The String ctor is deprecated, but fast.
keys()266   public Set<String> keys() {
267     if (isEmpty()) {
268       return Collections.emptySet();
269     }
270     Set<String> ks = new HashSet<String>(size);
271     for (int i = 0; i < size; i++) {
272       ks.add(new String(name(i), 0 /* hibyte */));
273     }
274     // immutable in case we decide to change the implementation later.
275     return Collections.unmodifiableSet(ks);
276   }
277 
278   /**
279    * Adds the {@code key, value} pair. If {@code key} already has values, {@code value} is added to
280    * the end. Duplicate values for the same key are permitted.
281    *
282    * @throws NullPointerException if key or value is null
283    */
put(Key<T> key, T value)284   public <T> void put(Key<T> key, T value) {
285     Preconditions.checkNotNull(key, "key");
286     Preconditions.checkNotNull(value, "value");
287     maybeExpand();
288     name(size, key.asciiName());
289     value(size, key.toBytes(value));
290     size++;
291   }
292 
maybeExpand()293   private void maybeExpand() {
294     if (len() == 0 || len() == cap()) {
295       expand(Math.max(len() * 2, 8));
296     }
297   }
298 
299   // Expands to exactly the desired capacity.
expand(int newCapacity)300   private void expand(int newCapacity) {
301     byte[][] newNamesAndValues = new byte[newCapacity][];
302     if (!isEmpty()) {
303       System.arraycopy(namesAndValues, 0, newNamesAndValues, 0, len());
304     }
305     namesAndValues = newNamesAndValues;
306   }
307 
308   /**
309    * Removes the first occurrence of {@code value} for {@code key}.
310    *
311    * @param key key for value
312    * @param value value
313    * @return {@code true} if {@code value} removed; {@code false} if {@code value} was not present
314    * @throws NullPointerException if {@code key} or {@code value} is null
315    */
remove(Key<T> key, T value)316   public <T> boolean remove(Key<T> key, T value) {
317     Preconditions.checkNotNull(key, "key");
318     Preconditions.checkNotNull(value, "value");
319     for (int i = 0; i < size; i++) {
320       if (!bytesEqual(key.asciiName(), name(i))) {
321         continue;
322       }
323       @SuppressWarnings("unchecked")
324       T stored = key.parseBytes(value(i));
325       if (!value.equals(stored)) {
326         continue;
327       }
328       int writeIdx = i * 2;
329       int readIdx = (i + 1) * 2;
330       int readLen = len() - readIdx;
331       System.arraycopy(namesAndValues, readIdx, namesAndValues, writeIdx, readLen);
332       size -= 1;
333       name(size, null);
334       value(size, null);
335       return true;
336     }
337     return false;
338   }
339 
340   /** Remove all values for the given key. If there were no values, {@code null} is returned. */
removeAll(Key<T> key)341   public <T> Iterable<T> removeAll(Key<T> key) {
342     if (isEmpty()) {
343       return null;
344     }
345     int writeIdx = 0;
346     int readIdx = 0;
347     List<T> ret = null;
348     for (; readIdx < size; readIdx++) {
349       if (bytesEqual(key.asciiName(), name(readIdx))) {
350         ret = ret != null ? ret : new ArrayList<T>();
351         ret.add(key.parseBytes(value(readIdx)));
352         continue;
353       }
354       name(writeIdx, name(readIdx));
355       value(writeIdx, value(readIdx));
356       writeIdx++;
357     }
358     int newSize = writeIdx;
359     // Multiply by two since namesAndValues is interleaved.
360     Arrays.fill(namesAndValues, writeIdx * 2, len(), null);
361     size = newSize;
362     return ret;
363   }
364 
365   /**
366    * Remove all values for the given key without returning them. This is a minor performance
367    * optimization if you do not need the previous values.
368    */
369   @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4691")
discardAll(Key<T> key)370   public <T> void discardAll(Key<T> key) {
371     if (isEmpty()) {
372       return;
373     }
374     int writeIdx = 0;
375     int readIdx = 0;
376     for (; readIdx < size; readIdx++) {
377       if (bytesEqual(key.asciiName(), name(readIdx))) {
378         continue;
379       }
380       name(writeIdx, name(readIdx));
381       value(writeIdx, value(readIdx));
382       writeIdx++;
383     }
384     int newSize = writeIdx;
385     // Multiply by two since namesAndValues is interleaved.
386     Arrays.fill(namesAndValues, writeIdx * 2, len(), null);
387     size = newSize;
388   }
389 
390   /**
391    * Serialize all the metadata entries.
392    *
393    * <p>It produces serialized names and values interleaved. result[i*2] are names, while
394    * result[i*2+1] are values.
395    *
396    * <p>Names are ASCII string bytes that contains only the characters listed in the class comment
397    * of {@link Key}. If the name ends with {@code "-bin"}, the value can be raw binary. Otherwise,
398    * the value must contain only characters listed in the class comments of {@link AsciiMarshaller}
399    *
400    * <p>The returned individual byte arrays <em>must not</em> be modified. However, the top level
401    * array may be modified.
402    *
403    * <p>This method is intended for transport use only.
404    */
405   @Nullable
serialize()406   byte[][] serialize() {
407     if (len() == cap()) {
408       return namesAndValues;
409     }
410     byte[][] serialized = new byte[len()][];
411     System.arraycopy(namesAndValues, 0, serialized, 0, len());
412     return serialized;
413   }
414 
415   /**
416    * Perform a simple merge of two sets of metadata.
417    *
418    * <p>This is a purely additive operation, because a single key can be associated with multiple
419    * values.
420    */
merge(Metadata other)421   public void merge(Metadata other) {
422     if (other.isEmpty()) {
423       return;
424     }
425     int remaining = cap() - len();
426     if (isEmpty() || remaining < other.len()) {
427       expand(len() + other.len());
428     }
429     System.arraycopy(other.namesAndValues, 0, namesAndValues, len(), other.len());
430     size += other.size;
431   }
432 
433   /**
434    * Merge values from the given set of keys into this set of metadata. If a key is present in keys,
435    * then all of the associated values will be copied over.
436    *
437    * @param other The source of the new key values.
438    * @param keys The subset of matching key we want to copy, if they exist in the source.
439    */
merge(Metadata other, Set<Key<?>> keys)440   public void merge(Metadata other, Set<Key<?>> keys) {
441     Preconditions.checkNotNull(other, "other");
442     // Use ByteBuffer for equals and hashCode.
443     Map<ByteBuffer, Key<?>> asciiKeys = new HashMap<ByteBuffer, Key<?>>(keys.size());
444     for (Key<?> key : keys) {
445       asciiKeys.put(ByteBuffer.wrap(key.asciiName()), key);
446     }
447     for (int i = 0; i < other.size; i++) {
448       ByteBuffer wrappedNamed = ByteBuffer.wrap(other.name(i));
449       if (asciiKeys.containsKey(wrappedNamed)) {
450         maybeExpand();
451         name(size, other.name(i));
452         value(size, other.value(i));
453         size++;
454       }
455     }
456   }
457 
458   @SuppressWarnings("BetaApi") // BaseEncoding is stable in Guava 20.0
459   @Override
toString()460   public String toString() {
461     StringBuilder sb = new StringBuilder("Metadata(");
462     for (int i = 0; i < size; i++) {
463       if (i != 0) {
464         sb.append(',');
465       }
466       String headerName = new String(name(i), US_ASCII);
467       sb.append(headerName).append('=');
468       if (headerName.endsWith(BINARY_HEADER_SUFFIX)) {
469         sb.append(BaseEncoding.base64().encode(value(i)));
470       } else {
471         String headerValue = new String(value(i), US_ASCII);
472         sb.append(headerValue);
473       }
474     }
475     return sb.append(')').toString();
476   }
477 
bytesEqual(byte[] left, byte[] right)478   private boolean bytesEqual(byte[] left, byte[] right) {
479     return Arrays.equals(left, right);
480   }
481 
482   /** Marshaller for metadata values that are serialized into raw binary. */
483   public interface BinaryMarshaller<T> {
484     /**
485      * Serialize a metadata value to bytes.
486      *
487      * @param value to serialize
488      * @return serialized version of value
489      */
toBytes(T value)490     byte[] toBytes(T value);
491 
492     /**
493      * Parse a serialized metadata value from bytes.
494      *
495      * @param serialized value of metadata to parse
496      * @return a parsed instance of type T
497      */
parseBytes(byte[] serialized)498     T parseBytes(byte[] serialized);
499   }
500 
501   /**
502    * Marshaller for metadata values that are serialized into ASCII strings. The strings contain only
503    * following characters:
504    *
505    * <ul>
506    * <li>Space: {@code 0x20}, but must not be at the beginning or at the end of the value. Leading
507    *     or trailing whitespace may not be preserved.
508    * <li>ASCII visible characters ({@code 0x21-0x7E}).
509    * </ul>
510    *
511    * <p>Note this has to be the subset of valid characters in {@code field-content} from RFC 7230
512    * Section 3.2.
513    */
514   public interface AsciiMarshaller<T> {
515     /**
516      * Serialize a metadata value to a ASCII string that contains only the characters listed in the
517      * class comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and
518      * discarded by the transport, or the call may fail.
519      *
520      * @param value to serialize
521      * @return serialized version of value, or null if value cannot be transmitted.
522      */
toAsciiString(T value)523     String toAsciiString(T value);
524 
525     /**
526      * Parse a serialized metadata value from an ASCII string.
527      *
528      * @param serialized value of metadata to parse
529      * @return a parsed instance of type T
530      */
parseAsciiString(String serialized)531     T parseAsciiString(String serialized);
532   }
533 
534   /**
535    * Key for metadata entries. Allows for parsing and serialization of metadata.
536    *
537    * <h3>Valid characters in key names</h3>
538    *
539    * <p>Only the following ASCII characters are allowed in the names of keys:
540    *
541    * <ul>
542    * <li>digits: {@code 0-9}
543    * <li>uppercase letters: {@code A-Z} (normalized to lower)
544    * <li>lowercase letters: {@code a-z}
545    * <li>special characters: {@code -_.}
546    * </ul>
547    *
548    * <p>This is a strict subset of the HTTP field-name rules. Applications may not send or receive
549    * metadata with invalid key names. However, the gRPC library may preserve any metadata received
550    * even if it does not conform to the above limitations. Additionally, if metadata contains non
551    * conforming field names, they will still be sent. In this way, unknown metadata fields are
552    * parsed, serialized and preserved, but never interpreted. They are similar to protobuf unknown
553    * fields.
554    *
555    * <p>Note this has to be the subset of valid HTTP/2 token characters as defined in RFC7230
556    * Section 3.2.6 and RFC5234 Section B.1
557    *
558    * <p>Note that a key is immutable but it may not be deeply immutable, because the key depends on
559    * its marshaller, and the marshaller can be mutable though not recommended.
560    *
561    * @see <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">Wire Spec</a>
562    * @see <a href="https://tools.ietf.org/html/rfc7230#section-3.2.6">RFC7230</a>
563    * @see <a href="https://tools.ietf.org/html/rfc5234#appendix-B.1">RFC5234</a>
564    */
565   @Immutable
566   public abstract static class Key<T> {
567 
568     /** Valid characters for field names as defined in RFC7230 and RFC5234. */
569     private static final BitSet VALID_T_CHARS = generateValidTChars();
570 
571     /**
572      * Creates a key for a binary header.
573      *
574      * @param name Must contain only the valid key characters as defined in the class comment. Must
575      *     end with {@link #BINARY_HEADER_SUFFIX}.
576      */
of(String name, BinaryMarshaller<T> marshaller)577     public static <T> Key<T> of(String name, BinaryMarshaller<T> marshaller) {
578       return new BinaryKey<T>(name, marshaller);
579     }
580 
581     /**
582      * Creates a key for an ASCII header.
583      *
584      * @param name Must contain only the valid key characters as defined in the class comment. Must
585      *     <b>not</b> end with {@link #BINARY_HEADER_SUFFIX}
586      */
of(String name, AsciiMarshaller<T> marshaller)587     public static <T> Key<T> of(String name, AsciiMarshaller<T> marshaller) {
588       return of(name, false, marshaller);
589     }
590 
of(String name, boolean pseudo, AsciiMarshaller<T> marshaller)591     static <T> Key<T> of(String name, boolean pseudo, AsciiMarshaller<T> marshaller) {
592       return new AsciiKey<T>(name, pseudo, marshaller);
593     }
594 
of(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller)595     static <T> Key<T> of(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller) {
596       return new TrustedAsciiKey<T>(name, pseudo, marshaller);
597     }
598 
599     private final String originalName;
600 
601     private final String name;
602     private final byte[] nameBytes;
603 
generateValidTChars()604     private static BitSet generateValidTChars() {
605       BitSet valid = new BitSet(0x7f);
606       valid.set('-');
607       valid.set('_');
608       valid.set('.');
609       for (char c = '0'; c <= '9'; c++) {
610         valid.set(c);
611       }
612       // Only validates after normalization, so we exclude uppercase.
613       for (char c = 'a'; c <= 'z'; c++) {
614         valid.set(c);
615       }
616       return valid;
617     }
618 
validateName(String n, boolean pseudo)619     private static String validateName(String n, boolean pseudo) {
620       checkNotNull(n, "name");
621       checkArgument(!n.isEmpty(), "token must have at least 1 tchar");
622       for (int i = 0; i < n.length(); i++) {
623         char tChar = n.charAt(i);
624         if (pseudo && tChar == ':' && i == 0) {
625           continue;
626         }
627 
628         checkArgument(
629             VALID_T_CHARS.get(tChar), "Invalid character '%s' in key name '%s'", tChar, n);
630       }
631       return n;
632     }
633 
Key(String name, boolean pseudo)634     private Key(String name, boolean pseudo) {
635       this.originalName = checkNotNull(name, "name");
636       this.name = validateName(this.originalName.toLowerCase(Locale.ROOT), pseudo);
637       this.nameBytes = this.name.getBytes(US_ASCII);
638     }
639 
640     /**
641      * @return The original name used to create this key.
642      */
originalName()643     public final String originalName() {
644       return originalName;
645     }
646 
647     /**
648      * @return The normalized name for this key.
649      */
name()650     public final String name() {
651       return name;
652     }
653 
654     /**
655      * Get the name as bytes using ASCII-encoding.
656      *
657      * <p>The returned byte arrays <em>must not</em> be modified.
658      *
659      * <p>This method is intended for transport use only.
660      */
661     // TODO (louiscryan): Migrate to ByteString
662     @VisibleForTesting
asciiName()663     byte[] asciiName() {
664       return nameBytes;
665     }
666 
667     /**
668      * Returns true if the two objects are both Keys, and their names match (case insensitive).
669      */
670     @Override
equals(Object o)671     public boolean equals(Object o) {
672       if (this == o) {
673         return true;
674       }
675       if (o == null || getClass() != o.getClass()) {
676         return false;
677       }
678       Key<?> key = (Key<?>) o;
679       return name.equals(key.name);
680     }
681 
682     @Override
hashCode()683     public int hashCode() {
684       return name.hashCode();
685     }
686 
687     @Override
toString()688     public String toString() {
689       return "Key{name='" + name + "'}";
690     }
691 
692     /**
693      * Serialize a metadata value to bytes.
694      *
695      * @param value to serialize
696      * @return serialized version of value
697      */
toBytes(T value)698     abstract byte[] toBytes(T value);
699 
700     /**
701      * Parse a serialized metadata value from bytes.
702      *
703      * @param serialized value of metadata to parse
704      * @return a parsed instance of type T
705      */
parseBytes(byte[] serialized)706     abstract T parseBytes(byte[] serialized);
707   }
708 
709   private static class BinaryKey<T> extends Key<T> {
710     private final BinaryMarshaller<T> marshaller;
711 
712     /** Keys have a name and a binary marshaller used for serialization. */
BinaryKey(String name, BinaryMarshaller<T> marshaller)713     private BinaryKey(String name, BinaryMarshaller<T> marshaller) {
714       super(name, false /* not pseudo */);
715       checkArgument(
716           name.endsWith(BINARY_HEADER_SUFFIX),
717           "Binary header is named %s. It must end with %s",
718           name,
719           BINARY_HEADER_SUFFIX);
720       checkArgument(name.length() > BINARY_HEADER_SUFFIX.length(), "empty key name");
721       this.marshaller = checkNotNull(marshaller, "marshaller is null");
722     }
723 
724     @Override
toBytes(T value)725     byte[] toBytes(T value) {
726       return marshaller.toBytes(value);
727     }
728 
729     @Override
parseBytes(byte[] serialized)730     T parseBytes(byte[] serialized) {
731       return marshaller.parseBytes(serialized);
732     }
733   }
734 
735   private static class AsciiKey<T> extends Key<T> {
736     private final AsciiMarshaller<T> marshaller;
737 
738     /** Keys have a name and an ASCII marshaller used for serialization. */
AsciiKey(String name, boolean pseudo, AsciiMarshaller<T> marshaller)739     private AsciiKey(String name, boolean pseudo, AsciiMarshaller<T> marshaller) {
740       super(name, pseudo);
741       Preconditions.checkArgument(
742           !name.endsWith(BINARY_HEADER_SUFFIX),
743           "ASCII header is named %s.  Only binary headers may end with %s",
744           name,
745           BINARY_HEADER_SUFFIX);
746       this.marshaller = Preconditions.checkNotNull(marshaller, "marshaller");
747     }
748 
749     @Override
toBytes(T value)750     byte[] toBytes(T value) {
751       return marshaller.toAsciiString(value).getBytes(US_ASCII);
752     }
753 
754     @Override
parseBytes(byte[] serialized)755     T parseBytes(byte[] serialized) {
756       return marshaller.parseAsciiString(new String(serialized, US_ASCII));
757     }
758   }
759 
760   private static final class TrustedAsciiKey<T> extends Key<T> {
761     private final TrustedAsciiMarshaller<T> marshaller;
762 
763     /** Keys have a name and an ASCII marshaller used for serialization. */
TrustedAsciiKey(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller)764     private TrustedAsciiKey(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller) {
765       super(name, pseudo);
766       Preconditions.checkArgument(
767           !name.endsWith(BINARY_HEADER_SUFFIX),
768           "ASCII header is named %s.  Only binary headers may end with %s",
769           name,
770           BINARY_HEADER_SUFFIX);
771       this.marshaller = Preconditions.checkNotNull(marshaller, "marshaller");
772     }
773 
774     @Override
toBytes(T value)775     byte[] toBytes(T value) {
776       return marshaller.toAsciiString(value);
777     }
778 
779     @Override
parseBytes(byte[] serialized)780     T parseBytes(byte[] serialized) {
781       return marshaller.parseAsciiString(serialized);
782     }
783   }
784 
785   /**
786    * A specialized plain ASCII marshaller. Both input and output are assumed to be valid header
787    * ASCII.
788    */
789   @Immutable
790   interface TrustedAsciiMarshaller<T> {
791     /**
792      * Serialize a metadata value to a ASCII string that contains only the characters listed in the
793      * class comment of {@link io.grpc.Metadata.AsciiMarshaller}. Otherwise the output may be
794      * considered invalid and discarded by the transport, or the call may fail.
795      *
796      * @param value to serialize
797      * @return serialized version of value, or null if value cannot be transmitted.
798      */
toAsciiString(T value)799     byte[] toAsciiString(T value);
800 
801     /**
802      * Parse a serialized metadata value from an ASCII string.
803      *
804      * @param serialized value of metadata to parse
805      * @return a parsed instance of type T
806      */
parseAsciiString(byte[] serialized)807     T parseAsciiString(byte[] serialized);
808   }
809 }
810