Skip to content

Commit 324e85e

Browse files
committed
feat: 754 Add WritableMessageDigest.digestInto method.
Signed-off-by: Ivan Malygin <ivan@swirldslabs.com>
1 parent 9cc32d7 commit 324e85e

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

pbj-core/pbj-runtime/src/main/java/com/hedera/pbj/runtime/hashing/WritableMessageDigest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ public byte[] digest() {
4848
return digest.digest();
4949
}
5050

51+
/**
52+
* A delegate for the wrapped {@link MessageDigest#digest(byte[], int, int)} method.
53+
*
54+
* <p>The digest is written into {@code buf} starting at {@code offset}. The length used is
55+
* {@link MessageDigest#getDigestLength()}, and {@link #position()} is reset to {@code 0},
56+
* matching the behavior of {@link #digest()}.
57+
*
58+
* @param buf the destination buffer for the digest bytes
59+
* @param offset the offset in {@code buf} where digest bytes are written
60+
* @throws RuntimeException if writing the digest into the destination buffer fails
61+
*/
62+
public void digestInto(final byte[] buf, final int offset) {
63+
position = 0;
64+
try {
65+
digest.digest(buf, offset, digest.getDigestLength());
66+
} catch (final java.security.DigestException e) {
67+
throw new RuntimeException("Failed to write digest into buffer", e);
68+
}
69+
}
70+
5171
@Override
5272
public void writeByte(byte b) throws BufferOverflowException, UncheckedIOException {
5373
digest.update(b);

pbj-core/pbj-runtime/src/test/java/com/hedera/pbj/runtime/hashing/WritableMessageDigestTest.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import com.hedera.pbj.runtime.io.buffer.BufferedData;
88
import com.hedera.pbj.runtime.io.buffer.Bytes;
9-
import com.hedera.pbj.runtime.io.buffer.RandomAccessData;
109
import java.nio.ByteBuffer;
1110
import java.security.MessageDigest;
1211
import java.security.NoSuchAlgorithmException;
12+
import java.util.Arrays;
1313
import java.util.stream.Stream;
1414
import org.junit.jupiter.api.Test;
1515
import org.junit.jupiter.params.ParameterizedTest;
@@ -66,10 +66,6 @@ private static Stream<byte[]> provideByteArrays() {
6666
FULL_RANGE_ARRAY);
6767
}
6868

69-
private static Stream<Arguments> provideByteArrayArguments() {
70-
return provideByteArrays().map(Arguments::of);
71-
}
72-
7369
@ParameterizedTest
7470
@MethodSource("provideByteArrays")
7571
void testWriteByteArray(byte[] array) {
@@ -155,8 +151,29 @@ void testWriteRandomAccessData(byte[] array) {
155151
final Bytes bytes = Bytes.wrap(array);
156152
final MessageDigest testDigest = buildDigest();
157153
final WritableMessageDigest wmd = new WritableMessageDigest(testDigest);
158-
wmd.writeBytes((RandomAccessData) bytes);
154+
wmd.writeBytes(bytes);
159155

160156
assertArrayEquals(ctrlDigest.digest(), testDigest.digest());
161157
}
158+
159+
@ParameterizedTest
160+
@MethodSource("provideByteArrays")
161+
void testDigestInto(byte[] array) {
162+
final MessageDigest ctrlDigest = buildDigest();
163+
ctrlDigest.update(array);
164+
final byte[] expectedDigest = ctrlDigest.digest();
165+
166+
final WritableMessageDigest wmd = new WritableMessageDigest(buildDigest());
167+
wmd.writeBytes(array);
168+
assertEquals(array.length, wmd.position());
169+
170+
final byte[] output = new byte[expectedDigest.length + 4];
171+
Arrays.fill(output, (byte) 0x55);
172+
wmd.digestInto(output, 2);
173+
174+
assertEquals(0, wmd.position());
175+
assertArrayEquals(expectedDigest, Arrays.copyOfRange(output, 2, 2 + expectedDigest.length));
176+
assertArrayEquals(new byte[] {(byte) 0x55, (byte) 0x55}, Arrays.copyOfRange(output, 0, 2));
177+
assertArrayEquals(new byte[] {(byte) 0x55, (byte) 0x55}, Arrays.copyOfRange(output, 2 + expectedDigest.length, output.length));
178+
}
162179
}

0 commit comments

Comments
 (0)