Add Fingerprint#addBytes(ByteString)

Use this GenQuery.QueryResultAction#computeKey, since it (should be) more
efficient than copying the ByteString into a new byte[] first.

PiperOrigin-RevId: 257833778
diff --git a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
index 1cf05c8..118e783 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
@@ -402,7 +402,7 @@
 
     @Override
     protected void computeKey(ActionKeyContext actionKeyContext, Fingerprint fp) {
-      fp.addBytes(result.toByteArray());
+      fp.addBytes(result);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/util/Fingerprint.java b/src/main/java/com/google/devtools/build/lib/util/Fingerprint.java
index 79c8894..45c4c46 100644
--- a/src/main/java/com/google/devtools/build/lib/util/Fingerprint.java
+++ b/src/main/java/com/google/devtools/build/lib/util/Fingerprint.java
@@ -18,6 +18,7 @@
 import com.google.devtools.build.lib.vfs.DigestHashFunction;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.protobuf.ByteString;
 import com.google.protobuf.CodedOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -99,6 +100,19 @@
     return hexDigest(digestAndReset());
   }
 
+  /**
+   * Updates the digest with 0 or more bytes. Same as {@link #addBytes(byte[])}, but potentially
+   * more performant when only a {@link ByteString} is available.
+   */
+  public Fingerprint addBytes(ByteString bytes) {
+    try {
+      codedOut.writeRawBytes(bytes);
+    } catch (IOException e) {
+      throw new IllegalStateException("failed to write bytes", e);
+    }
+    return this;
+  }
+
   /** Updates the digest with 0 or more bytes. */
   public Fingerprint addBytes(byte[] input) {
     addBytes(input, 0, input.length);
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index ee51028..4bbaadb 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -371,6 +371,7 @@
         "//src/main/java/com/google/devtools/common/options",
         "//third_party:mockito",
         "//third_party:truth8",
+        "//third_party/protobuf:protobuf_java",
     ],
 )
 
diff --git a/src/test/java/com/google/devtools/build/lib/util/FingerprintTest.java b/src/test/java/com/google/devtools/build/lib/util/FingerprintTest.java
index b3fd3c4..27953ad 100644
--- a/src/test/java/com/google/devtools/build/lib/util/FingerprintTest.java
+++ b/src/test/java/com/google/devtools/build/lib/util/FingerprintTest.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
+import com.google.protobuf.ByteString;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -52,14 +53,19 @@
     assertThat(f1Latin1.hexDigestAndReset()).isNotEqualTo(f2Latin1.hexDigestAndReset());
   }
 
-  // You can validate the md5 of the simple string against
-  // echo -n 'Hello World!'| md5sum
   @Test
-  public void bytesFingerprint() {
-    assertThat(new Fingerprint().addBytes("Hello World!".getBytes(UTF_8)).hexDigestAndReset())
-        .isEqualTo("ed076287532e86365e841e92bfc50d8c");
-    assertThat(Fingerprint.getHexDigest("Hello World!"))
-        .isEqualTo("ed076287532e86365e841e92bfc50d8c");
+  public void equivalentBytesAndStringsFingerprintsMatch() {
+    String helloWorld = "Hello World!";
+    // $ echo -n "Hello World!" | md5sum
+    String helloWorldMd5 = "ed076287532e86365e841e92bfc50d8c";
+
+    assertThat(new Fingerprint().addBytes(helloWorld.getBytes(UTF_8)).hexDigestAndReset())
+        .isEqualTo(helloWorldMd5);
+
+    assertThat(Fingerprint.getHexDigest(helloWorld)).isEqualTo(helloWorldMd5);
+
+    assertThat(new Fingerprint().addBytes(ByteString.copyFromUtf8(helloWorld)).hexDigestAndReset())
+        .isEqualTo(helloWorldMd5);
   }
 
   @Test