public HashEntry readHashEntry(final DataInputStream input, final AtomicLong pos) {
    try {
      int keyLength = 0;

      if (isPrimitive) {
        if (!isAssociative) {
          keyLength = header.getKeySize().getSize();
        } else {
          // associative - keylength is always zero
        }
      } else {
        if (!isAssociative) {
          keyLength = (int) read(input, header.getKeySize());
          pos.addAndGet(header.getKeySize().getSize());
        } else {
          // associative - keylength is always zero
        }
      }

      int dataLength = 0;

      if (isPrimitive) {
        dataLength = header.getValueSize().getSize();
      } else {
        dataLength = (int) read(input, header.getValueSize());
        pos.addAndGet(header.getValueSize().getSize());
      }

      byte[] key = new byte[0];

      if (keyLength > 0) {
        key = new byte[keyLength];
        input.readFully(key);
        pos.addAndGet(keyLength);
      }

      byte[] data = new byte[dataLength];

      input.readFully(data);
      pos.addAndGet(dataLength);

      int padding = 0;

      if (isPrimitive) {
        padding = 4 - ((keyLength + dataLength) % 4);
      } else {
        padding =
            4 - ((header.getKeySize().getSize() + header.getValueSize().getSize() + keyLength + dataLength) % 4);
      }

      if (padding == 4) {
        padding = 0;
      }

      input.read(new byte[padding]);
      pos.addAndGet(padding);

      return new HashEntry(key, data);
    } catch (IOException ioException) {
      throw new IllegalArgumentException("invalid HashFile format");
    }
  }