Skip to content

Commit

Permalink
clean(core): Factor out ResourceHasher
Browse files Browse the repository at this point in the history
  • Loading branch information
vorburger committed Jan 4, 2025
1 parent b72f637 commit cf2305d
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package dev.enola.common.io.hashbrown;

import com.google.common.hash.Hasher;
import com.google.common.io.ByteSource;
import com.google.common.io.CharSource;

Expand Down Expand Up @@ -72,31 +71,19 @@ public CharSource charSource() {
private synchronized void validate() {
if (validated) return;

var delegateByteSource = delegate.byteSource();
var hashFunction = Multihashes.toGuavaHashFunction(expectedHash.multihash());

Hasher hasher;
var optSize = delegateByteSource.sizeIfKnown();
if (optSize.isPresent()) hasher = hashFunction.newHasher(Math.toIntExact(optSize.get()));
else hasher = hashFunction.newHasher();

try (var is = delegateByteSource.openBufferedStream()) {
var read = is.read();
while (read != -1) {
hasher.putByte((byte) read);
read = is.read();
var resourceHasher = new ResourceHasher();
try {
var actualHash = resourceHasher.hash(delegate, expectedHash.multihash().getType());
if (!expectedHash.multihash().equals(actualHash)) {
throw new IntegrityViolationException(
"Expected "
+ expectedHash
+ " but got "
+ Multihashes.toString(actualHash, expectedHash.multibase()));
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
var hashCode = hasher.hash();
var actualBytes = hashCode.asBytes();
var actualHash = expectedHash.copy(actualBytes);

if (!expectedHash.equals(actualHash)) {
throw new IntegrityViolationException(
"Expected " + expectedHash + " but got " + actualHash);
}

validated = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public Multihash multihash() {
return multihash;
}

public Multibase.Base multibase() {
return multibase;
}

@Override
public boolean equals(Object o) {
if (!(o instanceof MultihashWithMultibase other)) return false;
Expand Down
3 changes: 1 addition & 2 deletions java/dev/enola/common/io/hashbrown/Multihashes.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
/** Extension methods for {@link io.ipfs.multihash.Multihash}. */
public final class Multihashes {

public static HashFunction toGuavaHashFunction(Multihash multihash) {
var type = multihash.getType();
public static HashFunction toGuavaHashFunction(Multihash.Type type) {
return switch (type) {
// NB: Please BEWARE of what types are added here; the (sub)selection is intentional!

Expand Down
52 changes: 52 additions & 0 deletions java/dev/enola/common/io/hashbrown/ResourceHasher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2025 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.common.io.hashbrown;

import com.google.common.hash.Hasher;

import dev.enola.common.io.resource.Resource;

import io.ipfs.multihash.Multihash;

import java.io.IOException;

public class ResourceHasher {

@SuppressWarnings("UnstableApiUsage")
public Multihash hash(Resource resource, Multihash.Type hashType) throws IOException {
var hashFunction = Multihashes.toGuavaHashFunction(hashType);
var byteSource = resource.byteSource();

Hasher hasher;
var optSize = byteSource.sizeIfKnown();
if (optSize.isPresent()) hasher = hashFunction.newHasher(Math.toIntExact(optSize.get()));
else hasher = hashFunction.newHasher();

try (var is = byteSource.openBufferedStream()) {
var read = is.read();
while (read != -1) {
hasher.putByte((byte) read);
read = is.read();
}
}

var hashCode = hasher.hash();
var actualBytes = hashCode.asBytes();
return new Multihash(hashType, actualBytes);
}
}

0 comments on commit cf2305d

Please sign in to comment.