001 /*
002 * Copyright (C) 2011 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015 package com.google.common.hash;
016
017 import static com.google.common.base.Preconditions.checkArgument;
018
019 import com.google.common.annotations.Beta;
020
021 import java.io.Serializable;
022
023 /**
024 * Static factories for creating {@link HashCode} instances; most users should never have to use
025 * this. All returned instances are {@link Serializable}.
026 *
027 * @author Dimitris Andreou
028 * @since 12.0
029 */
030 @Beta
031 public final class HashCodes {
032 private HashCodes() {}
033
034 /**
035 * Creates a 32-bit {@code HashCode}, of which the bytes will form the passed int, interpreted
036 * in little endian order.
037 */
038 public static HashCode fromInt(int hash) {
039 return new IntHashCode(hash);
040 }
041
042 private static final class IntHashCode extends HashCode implements Serializable {
043 final int hash;
044
045 IntHashCode(int hash) {
046 this.hash = hash;
047 }
048
049
050 @Override
051 public int bits() {
052 return 32;
053 }
054
055
056 @Override
057 public byte[] asBytes() {
058 return new byte[] {
059 (byte) hash,
060 (byte) (hash >> 8),
061 (byte) (hash >> 16),
062 (byte) (hash >> 24)};
063 }
064
065
066 @Override
067 public int asInt() {
068 return hash;
069 }
070
071
072 @Override
073 public long asLong() {
074 throw new IllegalStateException("this HashCode only has 32 bits; cannot create a long");
075 }
076
077 private static final long serialVersionUID = 0;
078 }
079
080 /**
081 * Creates a 64-bit {@code HashCode}, of which the bytes will form the passed long, interpreted
082 * in little endian order.
083 */
084 public static HashCode fromLong(long hash) {
085 return new LongHashCode(hash);
086 }
087
088 private static final class LongHashCode extends HashCode implements Serializable {
089 final long hash;
090
091 LongHashCode(long hash) {
092 this.hash = hash;
093 }
094
095
096 @Override
097 public int bits() {
098 return 64;
099 }
100
101
102 @Override
103 public byte[] asBytes() {
104 return new byte[] {
105 (byte) hash,
106 (byte) (hash >> 8),
107 (byte) (hash >> 16),
108 (byte) (hash >> 24),
109 (byte) (hash >> 32),
110 (byte) (hash >> 40),
111 (byte) (hash >> 48),
112 (byte) (hash >> 56)};
113 }
114
115
116 @Override
117 public int asInt() {
118 return (int) hash;
119 }
120
121
122 @Override
123 public long asLong() {
124 return hash;
125 }
126
127 private static final long serialVersionUID = 0;
128 }
129
130 /**
131 * Creates a {@code HashCode} from a byte array. The array is defensively copied to preserve
132 * the immutability contract of {@code HashCode}. The array must be at least of length 4.
133 */
134 public static HashCode fromBytes(byte[] bytes) {
135 checkArgument(bytes.length >= 4, "A HashCode must contain at least 4 bytes.");
136 return fromBytesNoCopy(bytes.clone());
137 }
138
139 /**
140 * Creates a {@code HashCode} from a byte array. The array is <i>not</i> copied defensively,
141 * so it must be handed-off so as to preserve the immutability contract of {@code HashCode}.
142 * The array must be at least of length 4 (not checked).
143 */
144 static HashCode fromBytesNoCopy(byte[] bytes) {
145 return new BytesHashCode(bytes);
146 }
147
148 private static final class BytesHashCode extends HashCode implements Serializable {
149 final byte[] bytes;
150
151 BytesHashCode(byte[] bytes) {
152 this.bytes = bytes;
153 }
154
155
156 @Override
157 public int bits() {
158 return bytes.length * 8;
159 }
160
161
162 @Override
163 public byte[] asBytes() {
164 return bytes.clone();
165 }
166
167
168 @Override
169 public int asInt() {
170 return (bytes[0] & 0xFF)
171 | ((bytes[1] & 0xFF) << 8)
172 | ((bytes[2] & 0xFF) << 16)
173 | ((bytes[3] & 0xFF) << 24);
174 }
175
176
177 @Override
178 public long asLong() {
179 if (bytes.length < 8) {
180 // Checking this to throw the correct type of exception
181 throw new IllegalStateException("Not enough bytes");
182 }
183 return (bytes[0] & 0xFFL)
184 | ((bytes[1] & 0xFFL) << 8)
185 | ((bytes[2] & 0xFFL) << 16)
186 | ((bytes[3] & 0xFFL) << 24)
187 | ((bytes[4] & 0xFFL) << 32)
188 | ((bytes[5] & 0xFFL) << 40)
189 | ((bytes[6] & 0xFFL) << 48)
190 | ((bytes[7] & 0xFFL) << 56);
191 }
192
193 private static final long serialVersionUID = 0;
194 }
195 }