/*
 * Copyright (C) 2007 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.io;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * An implementation of {@link DataInput} that uses little-endian byte ordering for reading {@code
 * short}, {@code int}, {@code float}, {@code double}, and {@code long} values.
 *
 * <p><b>Note:</b> This class intentionally violates the specification of its supertype {@code
 * DataInput}, which explicitly requires big-endian byte order.
 *
 * @author Chris Nokleberg
 * @author Keith Bottner
 * @since 8.0
 */
@Beta
@GwtIncompatible
public final class LittleEndianDataInputStream extends FilterInputStream implements DataInput {

  /**
   * Creates a {@code LittleEndianDataInputStream} that wraps the given stream.
   *
   * @param in the stream to delegate to
   */
  public LittleEndianDataInputStream(InputStream in) {
    super(Preconditions.checkNotNull(in));
  }

  /** This method will throw an {@link UnsupportedOperationException}. */
  @CanIgnoreReturnValue // to skip a line
  @Override
  public String readLine() {
    throw new UnsupportedOperationException("readLine is not supported");
  }

  @Override
  public void readFully(byte[] b) throws IOException {
    ByteStreams.readFully(this, b);
  }

  @Override
  public void readFully(byte[] b, int off, int len) throws IOException {
    ByteStreams.readFully(this, b, off, len);
  }

  @Override
  public int skipBytes(int n) throws IOException {
    return (int) in.skip(n);
  }

  @CanIgnoreReturnValue // to skip a byte
  @Override
  public int readUnsignedByte() throws IOException {
    int b1 = in.read();
    if (0 > b1) {
      throw new EOFException();
    }

    return b1;
  }

  /**
   * Reads an unsigned {@code short} as specified by {@link DataInputStream#readUnsignedShort()},
   * except using little-endian byte order.
   *
   * @return the next two bytes of the input stream, interpreted as an unsigned 16-bit integer in
   *     little-endian byte order
   * @throws IOException if an I/O error occurs
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public int readUnsignedShort() throws IOException {
    byte b1 = readAndCheckByte();
    byte b2 = readAndCheckByte();

    return Ints.fromBytes((byte) 0, (byte) 0, b2, b1);
  }

  /**
   * Reads an integer as specified by {@link DataInputStream#readInt()}, except using little-endian
   * byte order.
   *
   * @return the next four bytes of the input stream, interpreted as an {@code int} in little-endian
   *     byte order
   * @throws IOException if an I/O error occurs
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public int readInt() throws IOException {
    byte b1 = readAndCheckByte();
    byte b2 = readAndCheckByte();
    byte b3 = readAndCheckByte();
    byte b4 = readAndCheckByte();

    return Ints.fromBytes(b4, b3, b2, b1);
  }

  /**
   * Reads a {@code long} as specified by {@link DataInputStream#readLong()}, except using
   * little-endian byte order.
   *
   * @return the next eight bytes of the input stream, interpreted as a {@code long} in
   *     little-endian byte order
   * @throws IOException if an I/O error occurs
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public long readLong() throws IOException {
    byte b1 = readAndCheckByte();
    byte b2 = readAndCheckByte();
    byte b3 = readAndCheckByte();
    byte b4 = readAndCheckByte();
    byte b5 = readAndCheckByte();
    byte b6 = readAndCheckByte();
    byte b7 = readAndCheckByte();
    byte b8 = readAndCheckByte();

    return Longs.fromBytes(b8, b7, b6, b5, b4, b3, b2, b1);
  }

  /**
   * Reads a {@code float} as specified by {@link DataInputStream#readFloat()}, except using
   * little-endian byte order.
   *
   * @return the next four bytes of the input stream, interpreted as a {@code float} in
   *     little-endian byte order
   * @throws IOException if an I/O error occurs
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public float readFloat() throws IOException {
    return Float.intBitsToFloat(readInt());
  }

  /**
   * Reads a {@code double} as specified by {@link DataInputStream#readDouble()}, except using
   * little-endian byte order.
   *
   * @return the next eight bytes of the input stream, interpreted as a {@code double} in
   *     little-endian byte order
   * @throws IOException if an I/O error occurs
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public double readDouble() throws IOException {
    return Double.longBitsToDouble(readLong());
  }

  @CanIgnoreReturnValue // to skip a field
  @Override
  public String readUTF() throws IOException {
    return new DataInputStream(in).readUTF();
  }

  /**
   * Reads a {@code short} as specified by {@link DataInputStream#readShort()}, except using
   * little-endian byte order.
   *
   * @return the next two bytes of the input stream, interpreted as a {@code short} in little-endian
   *     byte order.
   * @throws IOException if an I/O error occurs.
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public short readShort() throws IOException {
    return (short) readUnsignedShort();
  }

  /**
   * Reads a char as specified by {@link DataInputStream#readChar()}, except using little-endian
   * byte order.
   *
   * @return the next two bytes of the input stream, interpreted as a {@code char} in little-endian
   *     byte order
   * @throws IOException if an I/O error occurs
   */
  @CanIgnoreReturnValue // to skip some bytes
  @Override
  public char readChar() throws IOException {
    return (char) readUnsignedShort();
  }

  @CanIgnoreReturnValue // to skip a byte
  @Override
  public byte readByte() throws IOException {
    return (byte) readUnsignedByte();
  }

  @CanIgnoreReturnValue // to skip a byte
  @Override
  public boolean readBoolean() throws IOException {
    return readUnsignedByte() != 0;
  }

  /**
   * Reads a byte from the input stream checking that the end of file (EOF) has not been
   * encountered.
   *
   * @return byte read from input
   * @throws IOException if an error is encountered while reading
   * @throws EOFException if the end of file (EOF) is encountered.
   */
  private byte readAndCheckByte() throws IOException, EOFException {
    int b1 = in.read();

    if (-1 == b1) {
      throw new EOFException();
    }

    return (byte) b1;
  }
}
