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    }