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