    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    }