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 @Override public int bits() {
050 return 32;
051 }
052
053 @Override public byte[] asBytes() {
054 return new byte[] {
055 (byte) hash,
056 (byte) (hash >> 8),
057 (byte) (hash >> 16),
058 (byte) (hash >> 24)};
059 }
060
061 @Override public int asInt() {
062 return hash;
063 }
064
065 @Override public long asLong() {
066 throw new IllegalStateException("this HashCode only has 32 bits; cannot create a long");
067 }
068
069 private static final long serialVersionUID = 0;
070 }
071
072 /**
073 * Creates a 64-bit {@code HashCode}, of which the bytes will form the passed long, interpreted
074 * in little endian order.
075 */
076 public static HashCode fromLong(long hash) {
077 return new LongHashCode(hash);
078 }
079
080 private static final class LongHashCode extends HashCode implements Serializable {
081 final long hash;
082
083 LongHashCode(long hash) {
084 this.hash = hash;
085 }
086
087 @Override public int bits() {
088 return 64;
089 }
090
091 @Override public byte[] asBytes() {
092 return new byte[] {
093 (byte) hash,
094 (byte) (hash >> 8),
095 (byte) (hash >> 16),
096 (byte) (hash >> 24),
097 (byte) (hash >> 32),
098 (byte) (hash >> 40),
099 (byte) (hash >> 48),
100 (byte) (hash >> 56)};
101 }
102
103 @Override public int asInt() {
104 return (int) hash;
105 }
106
107 @Override public long asLong() {
108 return hash;
109 }
110
111 private static final long serialVersionUID = 0;
112 }
113
114 /**
115 * Creates a {@code HashCode} from a byte array. The array is defensively copied to preserve
116 * the immutability contract of {@code HashCode}. The array must be at least of length 4.
117 */
118 public static HashCode fromBytes(byte[] bytes) {
119 checkArgument(bytes.length >= 4, "A HashCode must contain at least 4 bytes.");
120 return fromBytesNoCopy(bytes.clone());
121 }
122
123 /**
124 * Creates a {@code HashCode} from a byte array. The array is <i>not</i> copied defensively,
125 * so it must be handed-off so as to preserve the immutability contract of {@code HashCode}.
126 * The array must be at least of length 4 (not checked).
127 */
128 static HashCode fromBytesNoCopy(byte[] bytes) {
129 return new BytesHashCode(bytes);
130 }
131
132 private static final class BytesHashCode extends HashCode implements Serializable {
133 final byte[] bytes;
134
135 BytesHashCode(byte[] bytes) {
136 this.bytes = bytes;
137 }
138
139 @Override public int bits() {
140 return bytes.length * 8;
141 }
142
143 @Override public byte[] asBytes() {
144 return bytes.clone();
145 }
146
147 @Override public int asInt() {
148 return (bytes[0] & 0xFF)
149 | ((bytes[1] & 0xFF) << 8)
150 | ((bytes[2] & 0xFF) << 16)
151 | ((bytes[3] & 0xFF) << 24);
152 }
153
154 @Override public long asLong() {
155 if (bytes.length < 8) {
156 // Checking this to throw the correct type of exception
157 throw new IllegalStateException("Not enough bytes");
158 }
159 return (bytes[0] & 0xFFL)
160 | ((bytes[1] & 0xFFL) << 8)
161 | ((bytes[2] & 0xFFL) << 16)
162 | ((bytes[3] & 0xFFL) << 24)
163 | ((bytes[4] & 0xFFL) << 32)
164 | ((bytes[5] & 0xFFL) << 40)
165 | ((bytes[6] & 0xFFL) << 48)
166 | ((bytes[7] & 0xFFL) << 56);
167 }
168
169 private static final long serialVersionUID = 0;
170 }
171 }