• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 
15 package com.google.common.hash;
16 
17 import static com.google.common.base.Preconditions.checkNotNull;
18 
19 import com.google.common.annotations.Beta;
20 
21 import java.io.FilterInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 
25 /**
26  * An {@link InputStream} that maintains a hash of the data read from it.
27  *
28  * @author Qian Huang
29  * @since 16.0
30  */
31 @Beta
32 public final class HashingInputStream extends FilterInputStream {
33   private final Hasher hasher;
34 
35   /**
36    * Creates an input stream that hashes using the given {@link HashFunction} and delegates all data
37    * read from it to the underlying {@link InputStream}.
38    *
39    * <p>The {@link InputStream} should not be read from before or after the hand-off.
40    */
HashingInputStream(HashFunction hashFunction, InputStream in)41   public HashingInputStream(HashFunction hashFunction, InputStream in) {
42     super(checkNotNull(in));
43     this.hasher = checkNotNull(hashFunction.newHasher());
44   }
45 
46   /**
47    * Reads the next byte of data from the underlying input stream and updates the hasher with
48    * the byte read.
49    */
50   @Override
read()51   public int read() throws IOException {
52     int b = in.read();
53     if (b != -1) {
54       hasher.putByte((byte) b);
55     }
56     return b;
57   }
58 
59   /**
60    * Reads the specified bytes of data from the underlying input stream and updates the hasher with
61    * the bytes read.
62    */
63   @Override
read(byte[] bytes, int off, int len)64   public int read(byte[] bytes, int off, int len) throws IOException {
65     int numOfBytesRead = in.read(bytes, off, len);
66     if (numOfBytesRead != -1) {
67       hasher.putBytes(bytes, off, numOfBytesRead);
68     }
69     return numOfBytesRead;
70   }
71 
72   /**
73    * mark() is not supported for HashingInputStream
74    * @return {@code false} always
75    */
76   @Override
markSupported()77   public boolean markSupported() {
78     return false;
79   }
80 
81   /**
82    * mark() is not supported for HashingInputStream
83    */
84   @Override
mark(int readlimit)85   public void mark(int readlimit) {}
86 
87   /**
88    * reset() is not supported for HashingInputStream.
89    * @throws IOException this operation is not supported
90    */
91   @Override
reset()92   public void reset() throws IOException {
93     throw new IOException("reset not supported");
94   }
95 
96   /**
97    * Returns the {@link HashCode} based on the data read from this stream. The result is
98    * unspecified if this method is called more than once on the same instance.
99    */
hash()100   public HashCode hash() {
101     return hasher.hash();
102   }
103 }
104