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 }